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

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

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

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

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

Предыдущий тред был тут: >>1049651 (OP) . Еще предыдущие треды ищутся в гугле по словам "клуб изучающих php" или в архиваче.

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

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

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

С чего начать

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

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

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

Ты прошел весь учебник? Молодец, но это были лишь основы языка 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 месяцев
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
56 Кб, 500x644
#2 #1067945
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

Если тебе лень выравнивать код руками, закачай его на 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
#3 #1067949
Если я кому-то не ответил в прошлом треде >>1049651 (OP) , напомните пожалуйста о себе.

Напомню, что надо проверить:

- >>1066512 26.09 https://github.com/vadimyen/students
- >>1066173 25.09 https://github.com/radiodog/studentlist
#4 #1067993
>>1067810

>Почкму ты думаешь проблема не в хостинге?


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

>>1067860

>почему бы не посмотреть логи ошибок веб-сервера


Maximum number of connection to host has been reached. Такие дела.
#5 #1067996
>>1067993

>Module 'PDO' already loaded in Unknown on line 0


И такое еще добро есть. Думаю-с что делать.
#6 #1068010
>>1067949
ОП, а задачу про студентов можно на фреймворке сделать? Или там весь смысл в "чистом php"?
ньюфаг
#7 #1068041
>>1067993

>Maximum number of connection to host has been reached



Это нагруженный проект?

Когда ты сам заходишь, получал ли 503?

Кинь ссылку, потестим. Если сикаешь, через pastebin закинь.

Если тебе самому выпадает через раз, попробуй
1) в корне html-страничку хелловорлд без PHP положи и раз 100 зайди.

2) Если будет опять 503, то, возможно:

а) >Боты-индексаторы, сканирующие ресурсы сайтов (поисковые системы, Sape и другие).

Nuff said. Настраивай robots.

б) >Использование элементов ресурсов или скриптов на чужих сайтах (ссылки на картинки, скрипты-информёры). Используйте антилич-модули/настройки.

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

в) >На сайте установлен элемент, который периодически посылает на сервер AJAX-запросы (например, чат). Количество запросов зависит не только от числа посетителей, но и от их привычки открывать несколько вкладок в браузере.

Также все понятно.

г) >DDoS

Зависит от сайта, если он небольшой, кому он сдался дудосить?
#7 #1068041
>>1067993

>Maximum number of connection to host has been reached



Это нагруженный проект?

Когда ты сам заходишь, получал ли 503?

Кинь ссылку, потестим. Если сикаешь, через pastebin закинь.

Если тебе самому выпадает через раз, попробуй
1) в корне html-страничку хелловорлд без PHP положи и раз 100 зайди.

2) Если будет опять 503, то, возможно:

а) >Боты-индексаторы, сканирующие ресурсы сайтов (поисковые системы, Sape и другие).

Nuff said. Настраивай robots.

б) >Использование элементов ресурсов или скриптов на чужих сайтах (ссылки на картинки, скрипты-информёры). Используйте антилич-модули/настройки.

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

в) >На сайте установлен элемент, который периодически посылает на сервер AJAX-запросы (например, чат). Количество запросов зависит не только от числа посетителей, но и от их привычки открывать несколько вкладок в браузере.

Также все понятно.

г) >DDoS

Зависит от сайта, если он небольшой, кому он сдался дудосить?
#8 #1068048
>>1068041

>Боты-индексаторы, сканирующие ресурсы сайтов (поисковые системы, Sape и другие).


This. Контрол панель без инглиша, онли на эльфийском. Пока нашел логи, то проклял свою работу, небо и аллаха. Пошел настраивать robots.
В любом случае, спасибо.
#9 #1068062
Решил задачу про палиндром, вроде работает. Заранее сорри за быдлокод:
http://sandbox.onlinephpfunctions.com/code/b6bdc5bd19ad6af9c4c3ac0914c5236ecea111d7
Буду рад, если кто-то оценит.
#10 #1068065
Покопался в кишках плагина и увидел, что там код чисто низкофункциональный, с объявлением коснтант, private static функций, классов, создаваемых синглетонами.
Короче, нихрена пхп надо не первым языком учить, а после серьезной базы типа C/C++/Asm/Java
#11 #1068087
>>1068041

>Боты-индексаторы, сканирующие ресурсы сайтов (поисковые системы, Sape и другие).


Есть еще 1 вопрос на эту тему.
503 выдает 24/7, а googlebot не реагирует на delay. Единственный шанс снизить поток этого говна - Search Console, но я не могу подвердить правана сайт - он не отвечает.
Как поднять сайт максимально быстро 10 минут назад? бить по морде 403 всем подряд?
#12 #1068089
>>1068041

>The robots.txt file must be in the top-level directory of the host, accessible though the appropriate protocol and port number.


>accessible though the appropriate protocol and port number.


Еще за это поясни плз.
#13 #1068093
>>1068010

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

Если делать на фреймворке - то с модификациями. Ну например, авторизацию сделать как указано в задаче, а не как удобнее фреймворку.
#14 #1068095
>>1068041

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

>>1068065

Какого плагина?

>>1068089

протокол http или https, соответствено порты 80 или 443.
someApprentice #15 #1068108
Уже второй день не могу справиться с циклами в Обещаниях.

Вчера, я не мог асинхронно выполнить цикл

>getMessages().then(function(messages) {


>


>for (var key in messages) {


>console.log("LOOP: " + messages[key].id);


>


>decrypt(messages[key].content).then(function(decrypted) {


>console.log("PROMISE: " + messages[key].id);


>});


>}


>


>});


>


>//LOOP: 1


>//LOOP: 2


>//PROMISE: 2;


>//PROMISE: 2;



Поискав в интернете я нашел похожую проблему https://stackoverflow.com/questions/40328932/javascript-es6-promise-for-loop , и из её решения я понял что нужно написать функцию, которая рекурсивно вызывает Обещание одно за другим, и написал обёртку

decryptMessages(messages) {
var that = this;

function loop(messages, i) {
if (i === undefined) {
i = 0;
}

var length = Object.keys(messages).length;

encrypted = messages.content;

// + check if privateKey added
decrypted = that.decrypt(encrypted);

decrypted.then(function(decrypted) {
messages.content = decrypted.data;

if (i < length - 1) {
loop(messages, i + 1);
}
});
}

loop(messages);
};

----

getMessages().then(function(messages) {

decryptMessages(messages);

// Object {0: Object {id: 1, content:"DECRYPTED"}, 1: Object {id:2, content:"ONE MORE DECRYPTED"}}
// Perfect
console.log(messages);

for (key in messages) {
console.log(messages[key].content; // -----BEGIN PGP MESSAGE...
}

});

Из примера выше, внутри цикла, свойства итерируемых объектов почему-то остаются нерасшифрованными, не смотря на то что в коллекции они расшифровались.
Ещё одно странное поведение, при обращении к объекту в коллекции по ключу (messages[0].content) значение тоже выводиться не расшифрованным, значит дело не цикле, а в функции которая преобразует эти объекты. Для меня странно, что моя функция decryptMessages() ничего не возвращает, но это, наверно, потому что передается ссылка на объект, и далее он преобразуется в функции. Я ошибся тут? Что ещё тут я делаю не правильно (потому что корень проблемы начался с того что нельзя выполнять асинхронный код в синхронных циклах)?
someApprentice #15 #1068108
Уже второй день не могу справиться с циклами в Обещаниях.

Вчера, я не мог асинхронно выполнить цикл

>getMessages().then(function(messages) {


>


>for (var key in messages) {


>console.log("LOOP: " + messages[key].id);


>


>decrypt(messages[key].content).then(function(decrypted) {


>console.log("PROMISE: " + messages[key].id);


>});


>}


>


>});


>


>//LOOP: 1


>//LOOP: 2


>//PROMISE: 2;


>//PROMISE: 2;



Поискав в интернете я нашел похожую проблему https://stackoverflow.com/questions/40328932/javascript-es6-promise-for-loop , и из её решения я понял что нужно написать функцию, которая рекурсивно вызывает Обещание одно за другим, и написал обёртку

decryptMessages(messages) {
var that = this;

function loop(messages, i) {
if (i === undefined) {
i = 0;
}

var length = Object.keys(messages).length;

encrypted = messages.content;

// + check if privateKey added
decrypted = that.decrypt(encrypted);

decrypted.then(function(decrypted) {
messages.content = decrypted.data;

if (i < length - 1) {
loop(messages, i + 1);
}
});
}

loop(messages);
};

----

getMessages().then(function(messages) {

decryptMessages(messages);

// Object {0: Object {id: 1, content:"DECRYPTED"}, 1: Object {id:2, content:"ONE MORE DECRYPTED"}}
// Perfect
console.log(messages);

for (key in messages) {
console.log(messages[key].content; // -----BEGIN PGP MESSAGE...
}

});

Из примера выше, внутри цикла, свойства итерируемых объектов почему-то остаются нерасшифрованными, не смотря на то что в коллекции они расшифровались.
Ещё одно странное поведение, при обращении к объекту в коллекции по ключу (messages[0].content) значение тоже выводиться не расшифрованным, значит дело не цикле, а в функции которая преобразует эти объекты. Для меня странно, что моя функция decryptMessages() ничего не возвращает, но это, наверно, потому что передается ссылка на объект, и далее он преобразуется в функции. Я ошибся тут? Что ещё тут я делаю не правильно (потому что корень проблемы начался с того что нельзя выполнять асинхронный код в синхронных циклах)?
36 Кб, 777x777
#16 #1068146
>>1067944 (OP)
Мне просто хочется плакать, я так хочу научится погромировать, но не могу блять, не понимаю я его. Я завидую людям которые умеют это делать. Говорят пхп освоит любой - хуйня это все ебаная, если ты тупой, а я тупой, то будь то пхп, питон, неважно, не освоить никак блять. Просто сижу нахуй и плачу от того, ебаное погромирование единственный шанс выбратся из говна ебаного, но почему я родился ТУПЫМ??????
Читаешь теорию - все понятно, после теории приступаешь к задаче и просто не одуупляешь что от тебя требуется! Как блять реализовывать и грамотно использовать изученный материал - у меня не хватает на это мозгов, я тупорылый даун.
А как люди генерируют идеи, а после все это реализуют на ЯП? Это просто за гранью воображения, я не понимаю этого, гении.
Как же меня демотивируют задачи которые я не могу решить, это какой-то психологический барьер или хуй знает. Например, читаю книгу и решаю параллельно задачи по книге и если какую либо из задач я не могу решить - злость, фрустрация, закрываю книгу и лежу неделями на диване хуесося себя.

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

Создайте две случайные даты (с помощью mt_rand()) и установив их в 2 объекта класса DateTime.
Найдите количество дней, часов, минут и секунд, на которое одна дата отличается от другой.
Сделайте разбиение на периоды с интервалом 1 день.
В цикле выведите все даты, которые содержатся между созданными в 1-м пункте, с интервалом из 3-го пункта.

Я не понимаю как можно генерировать случайную дату юзая мт_ранд, если мы генерим дату в формате d.m.Y H:i:s то на выходе получим 29.09.2017 16:55:16, точки двоеточия и прочее, а мт ранд работает с числами только. Разбивать регулярым вырежения или что, я понимаю что в этой ебучей задаче от меня требуют.

>Сделайте разбиение на периоды с интервалом 1 день.


>В цикле выведите все даты, которые содержатся между созданными в 1-м пункте, с интервалом из 3-го пункта.


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

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

я уебище тупое
36 Кб, 777x777
#16 #1068146
>>1067944 (OP)
Мне просто хочется плакать, я так хочу научится погромировать, но не могу блять, не понимаю я его. Я завидую людям которые умеют это делать. Говорят пхп освоит любой - хуйня это все ебаная, если ты тупой, а я тупой, то будь то пхп, питон, неважно, не освоить никак блять. Просто сижу нахуй и плачу от того, ебаное погромирование единственный шанс выбратся из говна ебаного, но почему я родился ТУПЫМ??????
Читаешь теорию - все понятно, после теории приступаешь к задаче и просто не одуупляешь что от тебя требуется! Как блять реализовывать и грамотно использовать изученный материал - у меня не хватает на это мозгов, я тупорылый даун.
А как люди генерируют идеи, а после все это реализуют на ЯП? Это просто за гранью воображения, я не понимаю этого, гении.
Как же меня демотивируют задачи которые я не могу решить, это какой-то психологический барьер или хуй знает. Например, читаю книгу и решаю параллельно задачи по книге и если какую либо из задач я не могу решить - злость, фрустрация, закрываю книгу и лежу неделями на диване хуесося себя.

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

Создайте две случайные даты (с помощью mt_rand()) и установив их в 2 объекта класса DateTime.
Найдите количество дней, часов, минут и секунд, на которое одна дата отличается от другой.
Сделайте разбиение на периоды с интервалом 1 день.
В цикле выведите все даты, которые содержатся между созданными в 1-м пункте, с интервалом из 3-го пункта.

Я не понимаю как можно генерировать случайную дату юзая мт_ранд, если мы генерим дату в формате d.m.Y H:i:s то на выходе получим 29.09.2017 16:55:16, точки двоеточия и прочее, а мт ранд работает с числами только. Разбивать регулярым вырежения или что, я понимаю что в этой ебучей задаче от меня требуют.

>Сделайте разбиение на периоды с интервалом 1 день.


>В цикле выведите все даты, которые содержатся между созданными в 1-м пункте, с интервалом из 3-го пункта.


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

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

я уебище тупое
#17 #1068147
>>1068095

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


Нет доступа к верверу. Если буду мерять на локалке - поможет ли мне это?

>протокол http или https, соответствено порты 80 или 443.


Мне нада поднять сайт максимально быстро. Я вьебал
User-agent: *
Disallow: /
В роботс, т.к. он был пустым.
Боты игнорят это говно. Вопрос: говно с портами или ботам поебать?
#18 #1068149
>>1068146
Не умеешь срать, не мучай жопу. Займись чем нибудь другим, хуйли тебе этот кодинг так вперся?
#19 #1068152
>>1068149
Чем другим? Рисовать не люблю, верстать сайты не нравится, СЕО хуета, поступить в университет на какого-то ТИХНАРЯ? Так там тоже обосрусь из-за ебучих задачек, условий которые в голове не укладываются.
Я нищук с мухосранска 5к, кодинк это был мой ласт шанс стать человеком и перебратся в более крупный город, получать норм даллары и прочее.
Мне нравится стезя погромирования, мне интересно изучать это, но блять у меня нет мозгов чтобы реализовать изученное, бесит нахуй.
#20 #1068160
>>1068146
У тебя хуевое отношение к задачам. Если ты встречаешь задачу которую не можешь сходу решить: ЭТО ХОРОШО. Это значит, что ты научишься чему то НОВОМУ. В твоем случае, начни с узнавания что такое: unix timestamp, как это получить в PHP, как это конвертировать в понятный формат даты.
#21 #1068166
>>1068146

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

Ну вот например, смотри, у тебя задача на объект DateTime. А ты вообще изучал этот класс, знаешь, какие у него есть методы? Начни с изучения мануала и прочитай весь раздел про дату/время: http://php.net/manual/ru/book.datetime.php

Наизусть учить не надо, но прочесть надо. Раз учебник, по которому ты учишься, ничего подробно не объясняет, придется читать мануал.

Кто тебе сказал, что дату можно задавать только в формате дней/месяцев/лет? Это не так.

Также, можешь прочесть мой урок про дату/время, вдруг что полезное найдется: https://github.com/codedokode/pasta/blob/master/php/datetime.md
#22 #1068167
>>1068146

>Я не понимаю как можно генерировать случайную дату юзая мт_ранд, если мы генерим дату в формате d.m.Y H:i:s то на выходе получим 29.09.2017 16:55:16, точки двоеточия и прочее, а мт ранд работает с числами только. Разбивать регулярым вырежения или что, я понимаю что в этой ебучей задаче от меня требуют.


Можно преобразовать число в дату с помощью функции date() и получившуюся строку передать в класс DateTime.

https://secure.php.net/manual/ru/function.date.php
https://secure.php.net/manual/ru/datetime.construct.php

$format = ...;

$random = mt_rand();

$date = date($format, $random)

$datetime = new DateTime($date);
$datetime->format($format);

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

>Сделайте разбиение на периоды с интервалом 1 день.


Здесь, наверно, имелось ввиду разделение полученной даты на дни. Т.е. если получившиеся значение было бы, к примеру, 2 дня и 12 часов, то получился бы массив состоящий из 0 => 24:00, 1 => 24:00, 2 => 12:00;

Ну вообще тут действительно не так очевидно.

P.S.
В шапке треда, кстати, есть задачи на любой уровень сложности.
#23 #1068168
>>1068147

Для начала, проверь, открывается ли этот файл robots.txt, причем в http и в https версиях.

>>1068152

В твоем случае нужно было полистать мануал и погуглить уроки про дату/время в PHP.
#24 #1068170
>>1068167

Это костыль, таймстамп можно напрямую передать в DateTime.
#25 #1068173
>>1068170

>Это костыль, таймстамп можно напрямую передать в DateTime.


Значит можно обойтись без функции date(). В мануале просто написано что конструктор DateTime принимает именно строку.

https://secure.php.net/manual/ru/datetime.construct.php
public DateTime::__construct ([ string $time = "now" [, DateTimeZone $timezone = NULL ]] )
#26 #1068206
>>1068173

Во-первых, там есть метод для задания таймстампа. Во-вторых, там есть еще createFromFormat которая может принимать таймстамп.
#28 #1068317
Никак не могу найти ошибку. Задача про айпад и школьника.
https://ideone.com/EbjMYs
Я вбил данные из старой задачи про айфон. Там еще ответ за спойлером был, я его решил и сверить. И получается он разный.
Банки я пока что закомментил.
И еще есть вопросы:
1) Правильно ли я использую команду return ?
2) Можно ли было в данном случае использовать эту команду как-то по-другому, но тоже правильно? Спасибо.
#29 #1068320
Нубский вопрос. Есть форма, у нее action="make_huynya.php". Как сделать так, чтобы этот make_huynya не генерировал новую страницу, а дописывал содержимое к той, на которой форма?
#30 #1068324
>>1068317
Переделал. Теперь вроде все совпадает. Но вопросы по return остались. Прошу проверить, правильно ли я сделал. Пишу ли я как говнокодер? Если да, то как и где надо было правильно писать? Спасибо
#31 #1068325
>>1068324
забыл ссылку https://ideone.com/2EheEI
280 Кб, 600x610
#32 #1068328
Какие существуют подходы для загрузки файлов к посту, до того как пост создан?

Например - Жмем кнопку добавить новость, загружаем сначала к ней картинки (AJAX), далее пишем сам текст и только после этого жмем кнопку сохранить новость.
Как лучше загружать связанные файлы вообще до того как родитель существует?
#33 #1068342
>>1068317

>Я вбил данные из старой задачи про айфон. Там еще ответ за спойлером был, я его решил и сверить. И получается он разный.


У меня вывелось столько же сколько и под спойлером.

https://ideone.com/EbjMYs

>stdout


>61270.186744521



>1) Правильно ли я использую команду return ?


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


Оператор return нужен чтобы функция завершила своё выполнение и вернула какой либо результат. Как его использовать зависит от тебя.

https://secure.php.net/manual/ru/functions.returning-values.php

>>1068324
Небольшая придирка к оформлению кода - где-то есть лишнее пробелы и переводы строки, где-то их нет. Аккуратно оформленный код проще читать. Как правильно оформлять код можно почитать здесь >>1067945 В частности, советую почитать стандарты PSR-1 и PSR-2.

>>1068325
https://ideone.com/2EheEI

Выражения вида $a = $a + $b можно писать проще $a += $b.

К сожалению комментарий об этом на английском:
https://php.net/manual/ru/language.operators.assignment.php#40084

Вроде правильно, но лучше спросить у codedecode разрешает ли он "имитировать" количество месяцев в цикле, а не считать их самому.
Расчёт маршрута #34 #1068347
Делаю задачу, где надо найди минимальный маршрут. Воспользовался алгоритмом Дейкстры, чтобы найти самые короткие маршруты. Аноны, как можно найти остановки маршрута?

https://3v4l.org/9rcVt
#35 #1068352
>>1068328
После отправки поста обновить записи о картинках к какому посту они привязаны.
#36 #1068356
>>1068342
Спасибо огромное!
#37 #1068358
>>1068328

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

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

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

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

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

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

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

Помни, что скрипт (да и сервер целиком) может упасть в любой момент и продумывай логику так, чтобы минимизировать урон. Например, использование транзакций гарантирует, что в БД не будет "не до конца" вставленных данных. Это немного усложняет код, но экономит тебе много времени на исправление ошибок в БД.
#38 #1068363
>>1068347

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

> $numberOfPaths


Название неудачное, лучше назвать например pointIds

> for ($i = 0; $i < count($numberOfPaths); $i++){


Посмотри функции array_fill и array_fill_keys.

Вообще, массив communications можно было и не делать, эти данные уже есть в массиве paths.

> for ($i = 0; $i < count($connectedStops); $i++){


Для перебора массива лучше подойдет foreach

> //ПОСТРОЕНИЕ ТАБЛИЦЫ ДОРОГ


Что-то выглядит сложно и запутанно. Это точно нужно?

> $maxTime[$i] = 1000000;


Если что, в PHP есть константа INF, а также функция is_finite():

http://php.net/manual/ru/math.constants.php
http://php.net/manual/ru/function.is-infinite.php
#39 #1068364
>>1068342

Количество месяцев - это защита от вечного зацикливания. Можно сделать и по-другому, сделав например условие:

продолжать, пока (долг > 0) {
...
если (новый долг > предыдущего долга) {
получается вечный цикл, выходим;
}
}

Другой вариант - делать остановку после 200 лет например.

Желательно избегать циклов, где есть возможность зацикливания. Указание заведомо большего числа месяцев позволяет это сделать, хотя может вместо цифры 20 стоило бы как-то делать грубую оценку исходя из суммы долга и месячной платы, либо исходя из оценки времени жизни заемщика.
#40 #1068367
>>1068320

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


Простая отправка формы всегда заставляет браузер рендерить ответ.
Поэтому есть ajax. Что бы вкатится вполне пойдет старый добрый jquey.
#41 #1068368
Мне из моего скрипта надо взаимодействовать с API стороннего сайта. Нужно указать TOKEN, который мне выдал этот API... я не пойму куда его прописывать, в headers?
#42 #1068369
>>1068367
т.е. без javascript я эту задачу вообще никак не решу?
#43 #1068371
>>1068369

>т.е. без javascript я эту задачу вообще никак не решу?


Да. Без js не получится.
Но там на самом деле оч мало то нужно.
#44 #1068372
>>1068371
Лол, я JS знаю лучше чем php, просто удмал, что может как-то можно не плодя сущности и не добавляя js К существующей поделке
#45 #1068374
>>1068368
Кратко: смотри документацию.
Если ее нет, то пробуй без токена и может в ошибке, что вернет сервер, будет ответ.
А так, и в хидерах бывает, и в теле. У многих можно и так и так.

Но в теле, при гет запросе, не советуется. Т.к. при хттпс запросе, строка с адресом не кодируется.
#46 #1068375
>>1068372

> я JS знаю лучше чем php, просто удмал, что может как-то можно не плодя сущности и не добавляя js К существующей поделке


Ты сам подумай. Браузер должен знать, как твой ответ распарсить, чего там ковырнуть, как это отрендерить и куда это потом запихнуть.
#47 #1068379
>>1068320
Слушай ну если это форма ты можешь просто проверять наличие ПОСТА и инклудить ее.
#48 #1068383
>>1068146
Спасибо за ответы парни, я остыл и решил заново трайнуть решить задачу.
https://ideone.com/XyB3i1
Написал функцую которая генерирует рандомную дату, потому что блять я ума не приложу как это по другому сделать.
Если кто-то знает каким образом по другому генерить рандом дату - отпишитесь плиз.
я не выебываюсь, а просто нарабатываю привычку писать в стиле ооп

тупое уебище
#49 #1068385
>>1068383
Алсо, если часто обновлять страницу, то получим вместо рандом даты нужного диапазона мы получим дату 19700101, с чем может быть связана проблема? Установлен последний апач.
#50 #1068388
>>1068383
Самый изич, это сгенерить юникс теймстамп и потом спарсить в дейт тайм.
Правда, эта рандом дата никогда не будет ранее 1970 года.

Но твоя функция тоже норм. Единственное, сделай ее сразу конструктором твоего класса.
#51 #1068389
>>1068385
Ты точки забыл. Которые разделители в рандомной дате.
#52 #1068390
>>1068379
но ведь она будет отрисовываться заново
#53 #1068393
Еще один нубский вопрос. Вот мой скрипт обработал что-то полученное из формы и теперь ему нужно сгенерировать новую(простенькую) страницу для ответа. Как делают приличные люди? Смешать в одном файле код php и html?
#54 #1068394
>>1068383

А куда делся DateTime? Ты же вроде хотел его использовать?

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

Во-вторых, ты передаешь дату в виде строки YYYYmmdd. Зачем? С этой строкой не будет работать ни одна функция. Я же писал в своем уроке, что время представляется либо в виде timestamp, либо в виде DateTime. С этими значениями можно делать что угодно и преобразовывать их потом в любой формат.

Наконец, с точки зрения ООП выглядит тоже довольно бессмысленно. Вот что у тебя представляет объект класса RandomDate? Непонятно. Непонятно, зачем у тебя свойство date, которое никак вообще не используется.

Если ты хотел сделать объект, представляющий дату, то надо было либо хранить внутри него timestamp, либо по отдельности год/месяц/день. Хотя не очень понятно зачем это делать, когда есть DateTime.

Я бы тебе советовал все же прочесть мой урок https://github.com/codedokode/pasta/blob/master/php/datetime.md . Насчет ООП, я бы советовал почитать учебник из ОП поста, главу про ООП, и попробовать решить там задачу про Вектор. Тут у тебя ООП просто за уши притянут, ты вроде как используешь класс, но смысла в нем никакого нет, проще было сделать просто функцию либо статический метод в классе без свойств.
#55 #1068395
>>1068385

С тем, что ты генерируешь неправильную дату (вроде 2017131) которая не парсится. Прочти уже мануал по strtotime. Прочти описание поддерживаемых форматов даты. Никто за тебя это делать не будет.
#56 #1068396
>>1068393

Вообще, почитай про алгоритм работы с формами https://github.com/codedokode/pasta/blob/master/forms.md

Что касается отделения логики от вывода, это делается за счет шаблонов: http://web.archive.org/web/20161119062218/http://www.phpinfo.su/articles/practice/shablony_v_php.html
255 Кб, 1079x1024
#57 #1068397
>>1068394
Читал твой урок, я тупой поэтому наговнокодил только вот это, днем буду переделывать https://ideone.com/ItLFPe
Завтра продолжу изучать, спокойной ночи всем итт.
#58 #1068564
Несколько у меня вопросов.
1. Чем в PDO bindValue и bindParam отличаются? Несколько раз перечитывал описание но так и не понял.
2. Нормально ли в конструкторе объекта дохуя кода писать? У меня такая привычка, я через него кучу всякой хуйни объявляю и даже некоторые вычисления, но подозреваю что это не очень хорошо.
3. Не очень понимаю что относить к моделям в MVC. Нет, ну понятно что работу с БД, сущности там. А всякие вещи типа валидации и пагинации - это тоже модели?
#59 #1068572
>>1068564
3. Ну вообще да, модели, а контроллеры для них выступают в роли клиентского кода (вызывают методы этих моделей)
#60 #1068576
>>1068062
Бамп. Скажите, правильно ли я сделал эту задачку.
#61 #1068585
>>1068572
Т.е. пагинатор можно пихать в пространство имен к моделям? У меня такие сервисы пока просто App
#62 #1068593
>>1068585

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

Насчет пагинатора - трудно сказать, скорее это вспомогательный класс.
126 Кб, 960x1280
#63 #1068623
>>1068358
Спасибо. Собственно так и сделал, как самый простой вариант.
Только алгоритм сохранения такой:
- открыть транзакцию
- сохранить запись в бд
- если сохранилась сохранить файл
- если файл сохранился комит
- во всех остальных случая ролбэк

Таким образом насколько я понимаю я не получу загруженных файлов без записей в бд.
#64 #1068625
>>1068585
>>1068593
Да, это вообще концептуальное разделение, а не название папок/пространств.
#65 #1068635
>>1068623

Получишь. Если скрипт упадет после сохранения файла, но до коммита. Но это не так страшно (по сути просто лишний файл), хуже если запись в БД есть, а файла на диске нет.
#66 #1068646
>>1068635
Понял. Спасибо еще раз.
#67 #1068673
Поможите пожалуйста!
Есть Слим 3 и есть Твиг в качестве шаблонизатора. Есть проект файлообменника и короче после загрузки файла, я редиректю пользователя на другой контроллер и есть ссылочка вот такого вида которую успешно обрабатывает контроллер /download/id/cocy-xyu.jpg я получаю данные из базы данных в объект и вот как теперь мне передать эти данные в странчку download.twig.
$this->view->render($response,'home.twig'); вот так я попадаю на главную странчику.
а вот так мне предглагает мануал
echo $this->view->render('download.twig', array('file' => $file));
Как делать я чего-то не ябу.
#68 #1068676
Все же поясните нубу чуть подробнее:
У меня отработал скрипт, в нем я получил данные которые нужны для того, чтобы сгенерировать страницу, как мне ее отобразить, ну не echo же. Могу ли я это сделать без шаблонизатора? Потому что не хочется его прикручивать ради двухстраничного тестового задания
#69 #1068678
>>1068676
...вариант подключения шаблона(в котором тоже php) через require подойдет?
#70 #1068698
>>1068673
Разобрался вроде
return $this->view->render($response,'download.twig', array('file' => $file));
#71 #1068712
А в продакшне что нужно с исключениями делать?
#72 #1068748
>>1068712
Логировать, слать ошибку в телегу, юзеру показывать 500. Чего ты с ними еще сможешь сделать?
#73 #1068778
>>1068748
Ну вот да, а как это грамотно организовать? В set_exception_handler, ну и во всех имеющихся catch'ах просто вставить header('HTTP/1.1 500 Internal Server Error'); die()? Телега – это телеграм?
#74 #1068786
Объясните. У меня есть форма. Я ее обрабатываю php-скриптом. Я по его итогам получил данные, которые мне нужны, чтобы сгенерировать страницу ответа. Как мне данные из php ей передать? У меня получилось через require_once('aaa.html'), но тогда я как бы продолжаю находиться в своем скрипте, меня это не устраивает. Правильный(вроде бы) переход получается через header("Location: /aaa.html"), но как тогда передать ему данные(их довольно много) из php?
#75 #1068812
И сразу же еще один вопрос. Я в скрипте получаю нужный мне массив и делаю require_once('aaa.html'), в этом html файле, используя php как шаблонизатор я циклом for отрисовываю нужные мне div'ы. Я бы хотел, чтобы каждый div был ссылкой и в качестве href указать адрес с параметрами, которые зависят от номера данного элемента массива. Как мне в href запихать переменную?
#76 #1068847
>>1068812
Div - это div, его нельзя сделать ссылкой, только средствами JS. Но возможно тебе подойдет обычный тег "a" с display:block. Возможно ошибаюсь, ибо последние 3 года занимаюсь только backend, может что-то поменялось в мире html
#77 #1068859
>>1068847
блин, да я обернул div в а, вот и все.... ты не понял вопроса, но я его уже решил. Зато появился другой вопрос.
Логика работы моей поделки: на главной странице форма, куда вбивается поисковая строка, результат обрабатывается php-скриптом и получается некий результат. На основе этого результата выдаем html страницу. На этой странице есть ссылка(пока одна, но потом будет много), она работает- направляет на правильную страницу, НО... на этой странице почему-то не работает php, вот просто игнорируется все, что внутри <?php ?>. Что за херня?
#78 #1068860
>>1068847
Можно ещё за место <div> использовать <label> с display:block и заключить его в ссылку.
#79 #1068863
>>1068860
На мой первый вопрос забей
#80 #1068865
>>1068564
1. Ну написано же русским языком в оффициальном php.net

>В отличие от PDOStatement::bindValue(), переменная привязывается по ссылке, и ее значение будет вычисляться во время вызова PDOStatement::execute().


Значит, в случае с bindValue ты привязываешь значение переменной, а bindParam привязываешь саму переменную. Например, у тебя есть подготовленное "pdo-выражение" bindParam, где ты привязал переменную $megaHash, а этот мега-хеш вычислять 10 раз потом и сделать $stmt->execute(). И у тебя привяжется последнее значение этого мега-хеша
2. Это плохо. В идеальном случае ты через конструктор должен передать только зависимости для твоего объекта.
3. Вот то, про что ты пишешь - так сделано вроде в Yii2. Но лучше, чтобы модель не была слишком толстой. В моем понимании модель - это бизнес-логика и все. Форма лежит рядом, но отдельно. Так как у тебя может быть одна модель User и куча форм с валидацией к ней: Registration, ChangePassword, etc.
#81 #1068868
>>1068859
Выглядит так, как будто ты хочешь чтобы php работал у тебя в браузере, такому не бывать. PHP выполняется на стороне веб-сервера, браузер лишь выполняет отрисовку результата работы веб-сервера + php
#82 #1068870
>>1068868
Блядь... и действительно
#83 #1068873
>>1068786
Да, нужно делать через require\require_once.
Переход через header нужен если нужно куда-то перенаправить. Например, на заглавное странице есть форма регистрации с action="register.php", в register.php мы обрабатываем данные и если всё ок, то куда-нибудь перенаправляем например на заглавную страницу.

>>1068812

>Как мне в href запихать переменную?


href="<?= $variable ?>"
#84 #1068875
>>1068868
Последний вопрос и я перестану трахать мозг:
вот пользователь ввел данные в форму и нажал кнопку отправки, включается скрипт, он вычисляет нужное и делает require_once('aaa.html')- внутри этого html я искпользую переменные из моего скрипта. Как мне сделать так, чтобы я по-прежнему мог внутри aaa.html использовать переменные из скрипта, но при этом именно перенаправлять пользователя на готовый aaa.html. Ведь при текущей реализации, после нажатия кнопки в форме я вижу в адресной строке /обработчик формы.php
#85 #1068877
>>1068873

>href="<?= $variable ?>"


Я думал об этом, но у меня там массив, который может быть недетской длины. Некрасиво как-то
#86 #1068881
>>1068576
Норм. Как решишь эту же задачу, если по условию будет, что на вход подается только однобайтная строка, а не utf8?
#87 #1068883
>>1068877

>>href="<?= $variable ?>"


>Я думал об этом, но у меня там массив, который может быть недетской длины. Некрасиво как-то


Тогда нужно использовать цикл.

Для шаблонов придумали альтернативный синтаксис:
https://php.net/manual/ru/control-structures.alternative-syntax.php
#88 #1068887
>>1068883
Я хочу, чтобы у пользователя в адресной строке всегда было/что_то_там.html Для этого, мне нужно использовать header(). Но мне на той странице, куда я перехожу, нужны переменные из скрипта. Есть ли решения,кроме передачи их параметрами запроса типа ?a=1&b=2 ???
#89 #1068889
>>1068887
Тебе нужно что-то вроде Rewrite Rules, чтобы, когда пользователь переходит на page.html, на самом деле выполнялся скрипт page.php
Почитай про Rewrite Rules в nginx, apache, lighttpd или что ты там используешь
#90 #1068891
>>1068889
Да даже к php -S, вроде, можно написать маршрутизацию как тебе надо
#91 #1068893
>>1068887
Гугли htaccess и RewriteEngine
#92 #1068895
>>1068889
Почитаю на досуге, мысль вроде ясна.
А вообще, когда я нажимаю на кнопку формы, получаю страницу результата, но вижу в адресной строке /обработчик_формы.php это вообще плохо?
#93 #1068896
>>1068895
для поделки и тестового задания - нет, для крупного интернет-магазина не очень.
#94 #1068901
>>1068896
Так. А если зайти с другой стороны. Сейчас я в php обработчике формы взаимодействую со сторонним api которое мне возвращает нужные данные, я это делаю с помощью file_get_contents.
Могу ли я делать то же самое на стороне клиента с помощью JavaScript? Если да, могу ли я потом передать результаты из скрипта другой html странице?
#95 #1068903
>>1068901

>Могу ли я делать то же самое на стороне клиента с помощью JavaScript?


Скорее всего нет, почитай про Access-Control-Allow-Origin
#96 #1068906
>>1068903
На досуге почитаю. Можешь в двух словах объяснить что помешает мне это сделать?
#97 #1068907
>>1068906
типа нельзя делать кроссдоменные запросы?
#98 #1068908
>>1068906
Браузер, но тут скорее нужно мнение frontend эксперта
#99 #1068914
>>1068908
Смотри, мне дали такое задание:
попробуйте на любом бесплатном хостинге сделать страницу, которая будет позволять любому пользователю ввести адрес или кадастровый номер объекта недвижимости, а в ответ на введенные данные получить информацию по этому объекту. Далее выбрав объект (если их несколько) пройти процедуру оплаты. Саму интеграцию платежного шлюза делать не надо, это потребует времени.
Интеграцию получения сведений об объектах недвижимости необходимо производить через API проекта apirosreestr.ru

ТО есть стек технологий и технические пожелания по реализации не указаны. Делать это на php- норм, или изначально плохая идея?
#100 #1068916
>>1068914
... я не очень понимаю что они подразумевают под процедурой оплаты. Первая мысль- просто сделать страницу вида "вот тут мы будем платить за объект такой-то"
#101 #1068929
>>1068896
А если бы это был крупный интернет магазин. И нужно из php обработчика формы передать результат(большой массив) html странице. Неужели передаче через ?a=12b=22c=15... ,которые маячат в адресной строке, это нормально?
#102 #1068931
>>1068929
?a=12&b=22&c=15
быстрофикс
#103 #1068940
>>1068914
php, nodejs - проще простого. Но судя по твоим вопросам в треде, тобi пизда, ибо как я вижу наипростейший алгоритм
1) юзер на index.html вводит номер и нажимает поиск
2) аякс запрос на твой скрипт api.php, откуда возвращается список и рендерится на странице средствами js
3) юзер переходит по ссылке на /pay.php?objectId=7 и показывается простая форма оплаты с вводом номера Карты, имени с кода. И кнопка оплатить
4) по нажатию на кнопку форма ведёт на result.php?objectId=7, где ты выводишь инфу по объекту

Вот это самое простое решение
#104 #1068945
>>1068940
Мне было бы даже комфортнее на node.js, но
1) Хочется немного пощупать php
2) Думаю, что могут быть проблемы с поиском бесплатного хостинга поддерживающего ноду
Аякс запросы на php я не знал что так можно, лол. Идея хорошая, попробую реализовать
#105 #1068947
>>1068931
Из php в html ничего не передаётся. Считай, что php - это шаблонизатор, который может динамически в зависимости от запроса строить html страничку. Большие магазины сидят на jsonrpc, protobuff и не гоняют статику просто так.
#106 #1068950
>>1068945
У тебя аякс запрос уходит со странички в браузере на твой php скрипт. Он не в php.
#107 #1068955
>>1068950
хочу помогать ньюфажикам, но чёт пиздец, видимо поясняю как-то плохо или невнятно. Извините если что
#108 #1068956
>>1068940
У меня сейчас есть работоспособное решение такое:
У формы action='api.php' и там в конце этого скрипта require_one('results.html')
На странице results у найденных объектов ссылки вида /pay.php?тут данные описывающие объект которая ведет на страницу оплаты
#109 #1068977
>>1068940
Сюда залил https://afradkova.000webhostapp.com/

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

Только вбивай адрес не как можно более конкретный вплоть до номера дома, а то выдаст тебе 100500 объектов
#110 #1068982
>>1068977
*как можно более конкретный
#111 #1068983
>>1068982
Норм, работает чёт медленно только. И причеши
#112 #1068985
>>1068983
Я так понял, что api не очень быстро отвечает
#113 #1068989
>>1068985
Я могу сделать чтоюы по нажатию на кнопку и мой php скрипт запускался и параллельно с ним запускался js скрипт, который бы выводил вращающийся спиннер с надписью "ждем результатов"?
#114 #1069005
https://ideone.com/wRo3RI

Почему он мне 5000 выдаёт? Я не понимаю. Я же написал как ему считать $paymentTotal, а он к ему только месячный взнос прибавляет. Он поехавший? Что он пишет?
#115 #1069006
Кстати, а чего это полетел http://www.softtime.ru/bookphp/gl5_1.php
?
#116 #1069010

>return возвращает управление программой модулю, из которого была вызвана функция.



Это почти как break работает?

>Значения возвращаются при помощи необязательного оператора возврата.



Что? Куда они возвращаются?
#117 #1069018
>>1069010
мне кидали хороший пример по return https://2ch.hk/pr/res/1049651.html#1067893 (М) и это https://ideone.com/0dAmrv
#118 #1069029
>>1069010

Во-первых, вот мой пост про return, прочти >>1067893

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

// определяем функцию, в этот момент просто создается функция, но ее код пока не запускается
function someFunc($a, $b)
{
// создаем временную переменную $c, которая
// существует только до момента выхода из функции
$c = $a + $b;
return $c;
}

// вызываем ее, PHP начинает выполнять функцию, а ее результат после выхода сохранит в $x
$x = someFunc(3, 4);

// а можно сразу вывести результат, без переменной
echo someFunc(3, 4); // выведет 7

Функция не видит переменные, созданные снаружи ее (это сделано специально, и это хорошо, иначе в большой программе был бы риск, что функция затрет какую-то созданную снаружи переменную). С помощью аргументов в скобках мы передаем значения ($a = 3, $b = 4) внутрь функции. Она выполняется. И затем команда return выходит из функции и возвращает результат, который сохраняется в переменную $x (в данном случае 7).

> Это почти как break работает?


Да, break выходит из цикла, return из функции. Но на этом аналогия заканчивается.

> Что? Куда они возвращаются?


В место, откуда была вызвана функция. В примере выше return вернет результат, который будет сохранен в переменную $x. Функция может, если хочет, вернуть одно какое-то значение как результат своей работы (если в функции нет команды return, то считается что она вернула значение null). А тот, кто вызвал функцию, может, если хочет, сохранить это значение, или сделать что-то еще с ним. А может ничего не делать.
#118 #1069029
>>1069010

Во-первых, вот мой пост про return, прочти >>1067893

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

// определяем функцию, в этот момент просто создается функция, но ее код пока не запускается
function someFunc($a, $b)
{
// создаем временную переменную $c, которая
// существует только до момента выхода из функции
$c = $a + $b;
return $c;
}

// вызываем ее, PHP начинает выполнять функцию, а ее результат после выхода сохранит в $x
$x = someFunc(3, 4);

// а можно сразу вывести результат, без переменной
echo someFunc(3, 4); // выведет 7

Функция не видит переменные, созданные снаружи ее (это сделано специально, и это хорошо, иначе в большой программе был бы риск, что функция затрет какую-то созданную снаружи переменную). С помощью аргументов в скобках мы передаем значения ($a = 3, $b = 4) внутрь функции. Она выполняется. И затем команда return выходит из функции и возвращает результат, который сохраняется в переменную $x (в данном случае 7).

> Это почти как break работает?


Да, break выходит из цикла, return из функции. Но на этом аналогия заканчивается.

> Что? Куда они возвращаются?


В место, откуда была вызвана функция. В примере выше return вернет результат, который будет сохранен в переменную $x. Функция может, если хочет, вернуть одно какое-то значение как результат своей работы (если в функции нет команды return, то считается что она вернула значение null). А тот, кто вызвал функцию, может, если хочет, сохранить это значение, или сделать что-то еще с ним. А может ничего не делать.
#119 #1069030
>>1069005

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

$paymentTotal;

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

>>1068989

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

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

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

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

>>1068977

Нужно сделать защиту от выдачи 100500 объектов.
#120 #1069031
>>1068929

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

Ну или мы о разных вещах думаем.

>>1068916

Так спроси.

>>1068914

Задание надо делать самому.

>>1068901

Если владельцы этого API разрешают кроссдоменные запросы, читай документацию или смотри заголовки.

>>1068895

Нет

>>1068875

Вообще, тебе надо изучать теорию .Есть 2 метода - GET и POST для отправки форм, у них свои недостатки и достоинства, читай урок https://github.com/codedokode/pasta/blob/master/forms.md

>>1068873

Ты про htmlspecialchars забыл. Обязательно используй его в примерах. А то будет XSS уязвимость (и что характерно, многие плохие учебники по PHP точно также про него либо не пишут либо упоминают вскользь).
#120 #1069031
>>1068929

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

Ну или мы о разных вещах думаем.

>>1068916

Так спроси.

>>1068914

Задание надо делать самому.

>>1068901

Если владельцы этого API разрешают кроссдоменные запросы, читай документацию или смотри заголовки.

>>1068895

Нет

>>1068875

Вообще, тебе надо изучать теорию .Есть 2 метода - GET и POST для отправки форм, у них свои недостатки и достоинства, читай урок https://github.com/codedokode/pasta/blob/master/forms.md

>>1068873

Ты про htmlspecialchars забыл. Обязательно используй его в примерах. А то будет XSS уязвимость (и что характерно, многие плохие учебники по PHP точно также про него либо не пишут либо упоминают вскользь).
#121 #1069034
>>1068564

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

>>1068859

Расширение наверно надо сделать php, а не html.

>>1068812

div не может быть ссылкой, надо использовать тег a. Тебе стоило бы изучить HTML/CSS получше.

>>1068712

- логгировать в лог
- показывать страницу с простыми понятными словами для пользователя
- отдавать страницу с кодом 5xx
- при желании делать еще что-то

Описано у меня в уроке https://github.com/codedokode/pasta/blob/master/php/exceptions.md

Увы, по умолчанию PHP это не умеет, и это ошибка имхо. надо будет предложить им поменять поведение по умолчанию (хотя они вряд ли согласятся).
#122 #1069035
>>1068564

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



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

> 3. Не очень понимаю что относить к моделям в MVC. Нет, ну понятно что работу с БД, сущности там. А всякие вещи типа валидации и пагинации - это тоже модели?



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

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

То есть модель и есть само приложение, а контроллеры/вью, это так, обертка, чтобы человек мог взаимодействовать с моделью.
#123 #1069037
>>1068564

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

То есть мы это MVC используем не из фанатизма и не чтобы побольше денег взять с заказчика, а чтобы:

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

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

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

Я видел приложения без MVC, ну например, там регистрация пользователя дублировалась в нескольких контроллерах (так как было несколько мест, где это можно сделать). Если ты хочешь поменять логику проверки email, например, то надо было менять код в нескольких местах, и тестировать каждое по отдельности. Очень неудобно.
#124 #1069103
Так, снова проблема, отношения к php не имеет, но ладно, пусть уж будет тут. Этот тот анон, что вчера поздним вечером показывал свою поделку.
Проблема такая: я решил поставить скрипт на кнопку формы, для мгновенного отклика на нажатие, чтобы юзер понимал, нажалось ли, сработало ли и тп. Делают тег SCRIPT, туда функцию, в onclick ее указываю и.... ничего, не срабатывает. А если в onclick напрямую что-то указываю типа alert('bla-bla-bla'), то срабатывает.
75 Кб, 2560x588
#125 #1069121
Я упоротый или у IE бледнее палитра?
#126 #1069123
Так. Я смог осилить написание Ajax запроса из JS на php, он выполняется. Но есть проблема, в PHP я получаю переменную и мне нужно ее передать как результат этого Ajax запроса. Как это сделать? Я думал тупо return $result, но нихера
#127 #1069126
>>1069123
И еще... сейчас подробнее опишу: форма, а кнопке отправки стоит JS обработчик, который делает AJAX запрос на PHP скрипт.(сам запрос выполняется, проверено) 2 проблемы:
1. Даже если в PHP скрипте нет ничего такого, что должно выводить что-то на экран, все равно появляется пустое окошко после нажатия кнопки.
2. Как отдать переменную $result как результат Ajax запроса?
#128 #1069127
>>1069126
первый вопрос снимается, второй актуален
#129 #1069142
>>1069127
Так... проблема вот в чем. У меня запрос отправляется и данные получаются обратно, в xhr.responseText все нужное я получаю. НО у меня почему-то после выполнения php страница перезагружается, как поправить?
#130 #1069183
Are Parent constructors called implicitly inside a class constructor?

No, a parent constructor have to be called explicitly as follows:

parent::constructor($value)

Это странно. Пишу сейчас программу и у меня есть класс Контроллер от которого другие контроллеры наследуются. И вот у контроллера есть конструктор, а у других нет. Хотя я обращаюсь к свойству родителя без проблем. Как так?
#131 #1069185
>>1069183
Потому что когда ты переопределяешь метод родителя у тебя два пути - или ты полностью пишешь новый метод затирая старый, или ты дополняешь старый - parent::__construct() в твоем случае.
#132 #1069233
>>1069121

Вообще, у IE есть особенность, влияющая на вывод картинок.

ИЕ и другие браузеры по-разному интерпретируют блок GAMA, который задает гамма-коррекцию для цветов в PNG.

Гамма-коррекция была введена из-за того, что одни и те же RGB цвета могли по-разному выглядеть на разных системах (Mac vs PC). Благодаря ей можно добиться того, что картинка будет выглядеть одинаково в этих системах.

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

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

https://jonathannicol.com/blog/2006/12/01/fixing-png-gamma/
https://hsivonen.fi/png-gamma/

Решение - не добавлять гамму при сохранении PNG (наверняка есть опция) или вырезать ее утилитами вроде pngcrush.

Кстати, на моем бледном экране оба логотипа на твоей картинке выглядят почти одинаково. Я даже на телефон скопировал картинку и там оба логотипа тоже выглядят одинаково. Но проверка гимпом (через окошка Pointer Info) показала - вверху красный цвет eb6661, а внизу ea6661, так что ты прав, что они разные.
#133 #1069236
>>1069183

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

Текст, который ты процитировал, относится к случаю, когда конструктор определен и в предке, и в наследнике - в этом случае конструктор предка по умолчанию не вызывается, если ты это не делаешь явно.
#134 #1069308
Отправляю почту через пхп, понадобилось прикрутить select, но с него ничего не отправляется. Что я делаю не так?
#135 #1069324
>>1069308

>var user_dlina


Ай си вот ю дид зер
#136 #1069327
>>1069324
Не мой код.
#137 #1069341
>>1069324
Во первых убери у селекта тайп
Во вторых <option value="pizda">вагина</option>
Вот при отправке (при выборе "Вагина") отправляться будет pizda.
22 Кб, 529x195
#138 #1069346
>>1069341
Попробовал уже так, не отправляет.
#139 #1069352
Тут такая проблема: поставил OpenServer, в php скрипте обращаюсь к файлу blablabla.html- все работает. Когда же просто в html ставлю на него ссылку, он ругается, пишет, что доступ запрещен. Как и где поправить?
#140 #1069354
>>1069352
причем, если я тупо в адресной строке вбиваю путь к нему- все нормально переходит
60 Кб, 640x640
#141 #1069364
>>1068146
Помню некоторые простые задачки по джс по 3-5 дней обдумывал. http://learn.javascript.ru/ за полгода осилил. А ты сколько над своей задачкой сидел?
#142 #1069378
>>1068146

>Я не понимаю как можно генерировать случайную дату юзая мт_ранд, если мы генерим дату в формате d.m.Y H:i:s то на выходе получим 29.09.2017 16:55:16, точки двоеточия и прочее, а мт ранд работает с числами только. Разбивать регулярым вырежения или что



Время в формате юникс не не слышал?
Займись лучше задачками опа, сделай МВЦ приложение, а потом файлообменник.
#143 #1069394
В задаче про файлообменник каким размером делать превью для картинок?
Нужно ли перекодировать видео для превью?
#144 #1069405
>>1069346
Бамп вопросу.
#145 #1069424
>>1069346
Выведи в консоль содержимое переменных, которые передаешь, если все в порядке, то пусть на сервере скрипт через эхо вернет содержимое $_POST. Будет видно где проебался.

Алсо, обычно содержимое формы через .serialize() конвертируют в массив и его передают. Хуй знает что у тебя в свойстве data, никогда так не пробовал

Я делал так https://github.com/grigoryMovchan/2ch_get_img/blob/master/public/js/download-result.js#L13-L40
#146 #1069432
>>1069424

>Выведи в консоль содержимое переменных


Не могу, код на хостинге.
#147 #1069453
Почему nginx все время работает: включил компьютер, nginxне запускал, а все прописанные в файле hosts адреса переходят на "Welcome to nginx!"?
#148 #1069464
Привет тред, помогите ньюфагу.
https://ideone.com/FMplvx
При нажатии на кнопку получаю 404, wtf?
Object not found!

The requested URL was not found on this server. The link on the referring page seems to be wrong or outdated. Please inform the author of that page about the error.

If you think this is a server error, please contact the webmaster.

Error 404

localhost
Apache/2.4.27 (Win32) OpenSSL/1.0.2l PHP/7.0.22
#149 #1069473
>>1069464
Здесь СТОЛЬКО ошибок, что я просто в ахуе.
#150 #1069475
>>1069473
Пример из книги модного издательства Орейли.
#151 #1069480
>>1069464
Исправил ошибочку сам.
#152 #1069513
Ребят, я тут думал. Скрою на всякий случай, чтобы оффтопа не было. А то тема на /b похожа. А сколько можно зарабатывать фрилансом на верстке, включая функционал JS? Видел недавно парня который брал 500 руб за обычный сайт и его дизайн, и цену постепенно повышал на 500 за каждую услугу, ну мол "Добавить падающее меню" и судя по всему у него были клиенты. Сколько вообще может взять человек знающий все в совокупности, для верстки, типа HTML/CSS/JS/BootStrap и др. типа Blueprint. Что если вообще создать сайт с набором заверстанных тобой макетов с интернета? Грешить на дизайн можно, мол не тобой сделанное, но ведь ты предлагаешь верстку. Так вот, в чем подводные камни?
Спасибо за ответ заранее.
#153 #1069514
>>1069475
У О'рейли ток справочники нормальные. Да и то я в них что-то глоссария не наблюдаю удобного. Ну разве что в HTML Pocker reference.
#154 #1069516
>>1068146
Не тупой, просто больше практики нужно, вот и все. Не умеешь решить задачку - Не стоит себя обманывать, старайся думать, думать, думать. У меня когда я писал программы на C, пирамидку например, которая выводится с помощью символов алфавита, там нужно было выравнивание поставить, сделать так, чтобы с каждой линией символы менялись, кода там было... Сидел долго, перечитывал, но проблема была в одном - Я не писал код, а учил теорию, а этого делать нельзя. По статистике все выпускники из больших университетов учащих PC Science или как ее назвать - 99% не умеют программировать, совсем. Нужно уметь отдыхать и одновременно не расслабляться. Много ли людей решают задачи в один день? С одной стороны ответ - Да, потому что времени на самом деле не существует, а временные рамки созданы для удобства. Но если подумать, они ведь тоже создавались не один день, согласись? В общем, как это у нас говорят - ПИШИКОД.
#155 #1069517
>>1068160
>>1068166
>>1068167
>>1069364
Кстати да, спасибо за то что поделились.

мимокрокодил
#156 #1069585
<img src=../upload/2017-10-01/2.jpg height=216 alt=2.jpg >

Картинка не отображается потому что не в паблике лежит?
5 Кб, 299x168
#157 #1069593
Господи, какой же брееееееед. Когда в <a> заключаешь <img> ТЕГ БУДЕТ МЕРДЖИТЬСЯ ТОЛЬКО ЕСЛИ ПОСТАВИТЬ TEXT-ALIGN: CENTER
150 Кб, 1610x630
#158 #1069614
>>1067944 (OP)

>- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк.



Опчик, поясни пожалуйста моменты:
по программированию: что значит "знать Гит"? Это же вроде программа с резервными копиями. На каком уровне я должен ее знать? Просто в ней работать? Или ее дорабатывать как-то?
И вопрос по верстке: я знаю jquery на уровне просто подключить с какой-нибудь каруселью и забыть. Верстальщики реально правят ее код?
344 Кб, 343x391
indexedDB #159 #1069620
Вопрос по indexedDB
Читаю документацию, но что-то понимаю смутно.
В доках говорится, что дескать любая запись\чтение происходит через транзакцию.
Даже небо, даже Аллах.
И в примерах кода всюду:

>var transaction = db.transaction(["customers"], "readwrite");



Но что если я просто сделаю

>DB.objectStore("hui").add({cocol:"semen"});



Без получения богомерзких транзакций?

Это легально вообще?

Будет создана транзакция негласно?
Или браузер сломается?

И если транзакция все равно автоматически будет созданна, почему нигде в примерах нет такого использования?
57 Кб, 702x553
#160 #1069626
Оп и все помогаторы, я просто хочу вас поблагодарить и сказать, что вы делаете богоугодное дело, добра вам
#161 #1069727
регулятивные выражения в ideone работают?

вбил пример и вот результат: https://ideone.com/o4nr9D
#162 #1069729
>>1069727
регулярные*
#163 #1069743
>>1069727
Там вообще ничего не работает. Тупо отдает код обычным текстом.
#164 #1069745
>>1069743
и что тогда делать?
#165 #1069766
>>1069727
Все работает, ты таг забыл.
https://ideone.com/xWcs7Y
#166 #1069767
Посоветуйте гайд по регуляркам. На сайте из ОП-поста нормально написано, но не полно.
#167 #1069779
>>1069766
Точно! Вот я тупенький ¯\_(ツ)_/¯
Спасибо!
#168 #1069783
>>1069767
Не на русском, но самое разжёванное и подробное, что находил: https://www.regular-expressions.info/tutorial.html
Алсо автор сайта из ОП-поста обитает в треде и отвечает на вопросы, ну и мы подскажем как сможем, так что уточняй что непонятно.
#169 #1069795
>>1069783
Добра тебе! Как раз что-то подобное искал.
40 Кб, 801x216
#170 #1069814
Добрый вечер.
Я не совсем по теме,так как работаю с нодой, но в жс-треде вряд ли ответят на такой вопрос.

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

Проблема может быть решена посредством закрытия/открытия соединения с БД, но это рушит всю архитектуру моего приложения и совсем не изящно. Подскажите, как дропать таблицы?
#171 #1069816
>>1069814
C какой субд работаешь? Подкинь модуль. Почему не MySQL?
54 Кб, 714x349
#172 #1069817
>>1069816
С этой, которую модифицирую, на скрине.
https://github.com/mapbox/node-sqlite3
Не знаю, почему. Просто эта первая на глаза попалась. Я вообще начал это копать для расширения кругозора, чтобы освоить SQL.
#173 #1069818
>>1069814

Проблема не может быть в промисах и асинхронности? Попробуй там console.log натыкать, чтобы увидеть что в каком порядке выполняется.

Также, промисы по умолчанию съедают ошибки, убедись что у тебя любые ошибки выбрасываются в виде исключений и отображаются.
#174 #1069819
>>1069817

Также, зачем ты функцию описываешь словом const? разве не логичнее использовать function, которое для этого и придумано? Читать тяжело эти скобки и стрелки.
#175 #1069822
>>1069818
Пробовал, путаница ужасная. Если верить логам, то тесты выполняются ещё до того, как сервер подключится к базе, но подключение внутри них работает. Сейчас пробую другое решение.
>>1069819
Это фича из нового стандарта ЖС, на самом деле удобно.
#176 #1069824
Проблема решена. Спасибо async/await, превратил практически весь код, свящанный с подключением к БД и её подготовке к первому запуску в псевдосинхронный + конкретно для этого теста создаю новую БД вместо подключения общей.
#177 #1069832
>>1069822

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

array.map(x => x.getName());

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

function doSomething() { // ok

const doSomething = () => { // какая-то невнятная фигня

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


Значит ты накосячил с промисами.
#178 #1069841
>>1069832
А мне вот конфиг еслинта от эйрбнб наоборот советует везде использовать стрелочные. Пожалуй, буду следовать его совету, а то тимлид обоссыт.

Да, накосячил. Один тест проходит, зато попадали все другие, и при ручном тестировании не работает. Ух, лучше бы дальше монгой пользовался.
132 Кб, 449x546
#179 #1069948
https://ideone.com/WBUof5

Ну тут я даже не вижу, где ошибка и почему оно неправильно работает. Или правильно? Я не понимаю.
#180 #1069950
>>1069948
Неправильно, STR не может быть на один миллион. Ошибка в самом цикле или я return не туда впихнул?
#181 #1069952
>>1069950
Ошибка при подсчёте softcredit. Чего он отказывается его считать?
#182 #1069955
Какова должна быть логика в Yii2, если нужно сделать несколько форм на одной странице?
Допустим, на странице регистрации пользователей есть форма для ввода данных нового пользователя и таблица уже зарегистрированных юзеров, к каждому из которых прикреплена кнопка "Удалить". С регистрацией понятно: вводим данные, нажимаем "Зарегистрировать", срабатывает контроллер, проверяет данные, запускает модель и прописывает юзера в таблицу базы данных. А как правильно добавить удаление? Я пока что вижу такой алгоритм:
- Генерировать под каждую кнопку:
<?php $form = ActiveForm::begin(['id' => 'form1']); ?>
<?= $form->field($model, 'city_name')->textInput(); ?>
<?= Html::submitButton('button1', ['class' => 'btn btn-primary', 'name' => 'button1']); ?>
<?php ActiveForm::end(); ?>

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

Или нужно делать две разных модели?
#183 #1069964
Сделай на кнопку ссылку вида этастраница/user=del и разбирай в контроллере
#184 #1069965
>>1069964
А модель одна?
#185 #1069977
Программошки, выполняю уроки из оп-поста про строки. Задание - взять слова из массивов и сделать стих. Поясните, так вот нельзя выбирать рандомное слово из массива:

$word1[rand(1, count($word1))]

https://ideone.com/e.js/Bcxkl4

? Я имею ввиду какой-нибудь тим-лид - сноб от програмирования - не скажет "да вы гляяяньте на дурачка, тут же код будет выполняться на целую пикосекунду доооольше!"
#186 #1069982
>>1069977
Ой, аноши, накосячил, там, наверное, надо писать вот так

$word1[rand(0, count($word1)-1)]
#187 #1069987
>>1069965
Зачем тебе сабмит кнопки на удаление? Мути просто ссылки с айди или еще каким-нибудь уникальным атрибутом пользователя. И в роутере разбирай эти ссылки, делай чо надо и редиректь обратно. Хотя это просто мысли я сам вкатывальщик не знаю насколько это правильно
#188 #1069988
>>1069965
Зачем тебе сабмит кнопки на удаление? Мути просто ссылки с айди или еще каким-нибудь уникальным атрибутом пользователя. И в роутере разбирай эти ссылки, делай чо надо и редиректь обратно. Хотя это просто мысли я сам вкатывальщик не знаю насколько это правильно
#189 #1069989
>>1069988
Движок же. Там "ни единого слова в простоте". Я пока его не освоил (и освоение идёт, как восход солнца вручную).
350 Кб, 992x1072
#190 #1070014
Когда ты накосячил с классами.
#191 #1070016
И, судя по всему, Yii я не смогу освоить. Уже почти два месяца пытаюсь, но воз и ныне там. Шайтан машина просто. Именно тот случай, когда "смотришь в книгу - видишь фигу". Слишком сложно для самостоятельного освоения.
#192 #1070017
Какой самый простой способ добавить httpBasicAuth в yii2 глобально чтобы не подключать в каждом контроллере? Вариант с промежуточным контроллером в котором будет реализовываться behaviour с httpBasicAuth тоже так себе, придется менять предков для всех контроллеров
#193 #1070024
>>1070016
Slim освоил?
#194 #1070026
Чому картика не отображается? Заебался уже!
#195 #1070031
>>1070026
Покажи ошибку в консоли браузера (там будет 404 и указан путь по которому он пытался найти картинку)
#196 #1070036
>>1070026
Потому что тег не может ее найти и она скорее всего вне директорий разметки.
12 Кб, 472x41
#197 #1070041
>>1070031

> Аноним 03/10/17 Втр 19:33:27 №107

12 Кб, 375x50
#198 #1070061
Получается если у меня урл такого вида, то я должен делать что-то типа <img src="../../../upload/1.jpg?
При этом аплоад должен быть в паблике?
хтмл не может выйти выше из паблик директори?

Или я тупой?
#199 #1070075
>>1070061
../../../../../filename.jpg
#200 #1070079
Для верстки есть какой-нибудь фреймворк с визуальным перетаскиванием блоков, или я фига губу раскатал иди в блокноте пиши ленивый ебантяй
#201 #1070084
>>1070061

Суть паблик директории как раз в том, что все, что за ее пределами, не видно снаружи.
#202 #1070089
>>1070084
спасибо друг!
#203 #1070095
>>1070079
Pinegrow
#204 #1070097
>>1070095

>Pinegrow


спс
106 Кб, 1680x900
#205 #1070104
Это прям вселяет уверенность.
Большое искреннее спасибо автору учебника, он няшка, а мать его - милашка.
#206 #1070109
>>1070104
А теперь то же самое, но в плюсах.
#207 #1070116
>>1070109
До дома доеду - попробую. С телефона неудобно.
#208 #1070117
>>1070109
Что значит в плюсах?
#209 #1070132
Что можно окромя крудошлепства в PHP?
#210 #1070141
>>1070117
Мож инкремент имеют ввиду.
147 Кб, 1920x1080
#211 #1070178
>>1070109
Вот и я не знаю. : (
#212 #1070183
https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html

>MySQL uses the type keyword and these constructions produce DATE, TIME, and DATETIME values, respectively, including a trailing fractional seconds part if specified. The TIMESTAMP syntax produces a DATETIME value in MySQL because DATETIME has a range that more closely corresponds to the standard SQL TIMESTAMP type, which has a year range from 0001 to 9999. (The MySQL TIMESTAMP year range is 1970 to 2038.)



Ненавижу. Что имел ввиду автор документации?
#213 #1070202
>>1070178

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

>>1070183

Для начала, надо изучить, что такое литерал: https://ru.wikipedia.org/wiki/Литерал_(информатика)

Литерал - это конструкция в исходном коде, обозначающая какое-то постоянное значение. Например, число, строку.

В синтаксисе стандартного SQL и в диалекте MySQL есть специальный синтаксис для записи литералов, представляющих значения даты или времени. Синтаксис описан в мануале. Пример синтаксиса: DATE '2010-01-01' описывает значение типа DATE, представляющее указанную дату. Пример использования литерала для сравнения с колонкой типа DATE:

SELECT ... WHERE addedDate = DATE '2010-01-01';

Абзац, который ты выделил, говорит о том, что синтаксис с ключевым словом TIMESTAMP или ts:

TIMESTAMP '1999-01-01T12:00:00.123' (из стандарта SQL, формат ISO8601)
{ ts '....' } (из ODBC, это общее API для соединения с разными видами БД)

- создает значение типа DATETIME, а не TIMESTAMP. Потому что DATETIME позволяет представить более широкий диапазон дат. Могут ли от этого быть проблемы? Для этого придется изучить в мануале отличия типов DATETIME и TIMESTAMP и сделать выводы.

От себя скажу, что мне не приходилось использовать такой синтаксис. MySQL позволяет использовать в INSERT или в WHERE просто строку:

INSERT INTO x (addedTime) VALUES ('2018-01-01 12:00:00');
SELECT ... WHERE x = '2012-01-01'

Но я не уверен, что это соответствует стандарту SQL и будет работать в любой СУБД. Стандарт SQL, увы, платный (180 евро по моему за самый новый), потому ссылку дать не могу, могу дать только ссылку на http://modern-sql.com/standard с сборником бесплатных ссылок.
#213 #1070202
>>1070178

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

>>1070183

Для начала, надо изучить, что такое литерал: https://ru.wikipedia.org/wiki/Литерал_(информатика)

Литерал - это конструкция в исходном коде, обозначающая какое-то постоянное значение. Например, число, строку.

В синтаксисе стандартного SQL и в диалекте MySQL есть специальный синтаксис для записи литералов, представляющих значения даты или времени. Синтаксис описан в мануале. Пример синтаксиса: DATE '2010-01-01' описывает значение типа DATE, представляющее указанную дату. Пример использования литерала для сравнения с колонкой типа DATE:

SELECT ... WHERE addedDate = DATE '2010-01-01';

Абзац, который ты выделил, говорит о том, что синтаксис с ключевым словом TIMESTAMP или ts:

TIMESTAMP '1999-01-01T12:00:00.123' (из стандарта SQL, формат ISO8601)
{ ts '....' } (из ODBC, это общее API для соединения с разными видами БД)

- создает значение типа DATETIME, а не TIMESTAMP. Потому что DATETIME позволяет представить более широкий диапазон дат. Могут ли от этого быть проблемы? Для этого придется изучить в мануале отличия типов DATETIME и TIMESTAMP и сделать выводы.

От себя скажу, что мне не приходилось использовать такой синтаксис. MySQL позволяет использовать в INSERT или в WHERE просто строку:

INSERT INTO x (addedTime) VALUES ('2018-01-01 12:00:00');
SELECT ... WHERE x = '2012-01-01'

Но я не уверен, что это соответствует стандарту SQL и будет работать в любой СУБД. Стандарт SQL, увы, платный (180 евро по моему за самый новый), потому ссылку дать не могу, могу дать только ссылку на http://modern-sql.com/standard с сборником бесплатных ссылок.
#214 #1070206
>>1070202

>Неправильно, индексы массивов начинаются с 0, а не с 1.


Ой ладно тебе. Представь, что там не 6 + 1, а 5. Я вообще плюсы первый раз в жизни увидел, код надерган копипастой из гугла.
#215 #1070207
>>1070206

В Си++ вроде принято использовать для вывода потоки:

cout << question; (если у string определен оператор вывода в поток, я думаю, определен)

printf используется для форматированного вывода и вообще не очень правильно использовать его для вывода просто строки.
#216 #1070211
>>1070207
Да мне пофигу, если честно. Ты просил на плюсах - ты получил на плюсах.
https://github.com/radiodog/studentlist #217 #1070224
>>1065726
>>1066173
>>1067949

> https://github.com/radiodog/studentlist/blob/master/composer.json


Тут name и description можно не указывать. У тебя же не библиотека.

> https://github.com/radiodog/studentlist/blob/master/mydb.sql


тут в дампе явно лишние команды, требующие администраторских привилегий, например, CREATE EXTENSION.

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

Папку vendor нужно внести в gitignore.

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

https://github.com/radiodog/studentlist/blob/master/src/Classes/Router.php
В конструкторе класса Router указан аргумент $url, но на самом деле туда передается массив. Причем нигде не описано какой именно массив, с какими полями. Не нужно так делать, нужно указать конкретные аргументы.

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

Тем более ненормально, что роутер еще и exit вызывает в конструкторе. Это вообще не роутер, а FrontController получается.

Сам алгоритм роутинга переусложнен, не проще сделать через сравнение строк или регулярки?

URL можно разобрать на части с помощью parse_url.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Controller.php
Базовый контроллер выглядит странно. Например, почему там прописана установка соединения с БД? Как-то немного странно. Зачем вообще в контроллере иметь объект PDO?

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

Проверку/установку авторизационных кук лучше сделать в отдельном классе/функциях, а не размазывать кусочками по коду.

Для хранения данных формы можно было использовать объект Student, а не массив.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Controller.php
Тут у тебя в случае успеха сообщение об успехе выводится до DOCTYPE, это неправильно. Это вообще может привести к тому, что кодировка не определится правильно. И после успешной обработки POST-формы надо делать редирект, а не выводит снова эту форму. Это описано в моем уроке про формы.

> public function getValuesFromPost()


Тут надо было использовать цикл, а не копипастить код.

> $validator->validate($values,$dataGateway);


> $message = $validator->message;


Что мешает вернуть результат функции через return? Зачем городить такой странный способ передачи результата?

> if ($values['e_mail']==$valuesFromDB['e_mail']) {


> $errors['e_mail'] ='';


Лучше в валидаторе сделать проверку, что при редактировании можно использовать тот же email.

> $student->setId($this->dataGateway->getCount()+1);


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

> getMarks($placeholder)


Это бы конечно лучше делать во view, а не тут.

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

Название MainController неудачное, не отражает назначение контроллера. И PageController тоже.

https://github.com/radiodog/studentlist/blob/master/src/Classes/PageController.php#L22

> if ($_SERVER['REQUEST_METHOD']=="GET"){


А если не GET, то что тогда произойдет?

> public function createNext($request)


> public function createPrev($request)


Тут сплошная копипаста. Лучше сделать одну универсальную функцию для генерации URL, и не в контроллере.

> $numPattern = "/(0-9)*/ui";


нет привязки к краям строки (^$)

> https://github.com/radiodog/studentlist/blob/master/src/Classes/PageController.php#L42


> $request['order'] = ....


> $request['order'] = ....



Создается впечатление, что первая строчка ничего не делает и не нужна.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Pager.php#L25
Тут какая-то переусложненная формула. Посчитать число страниц можно проще.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Student.php#L16
Слишком много аргументов в конструкторе. Лучше сделать либо пустой конструктор, либо сделать метод вроде updateAttributes, принимающий массив.

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

https://github.com/radiodog/studentlist/blob/master/src/Classes/UserDataGateway.php#L19

> return $row = ...


Зачем здесь создается переменная?

> https://github.com/radiodog/studentlist/blob/master/src/Classes/UserDataGateway.php


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

https://github.com/radiodog/studentlist/blob/master/src/Classes/UserDataGateway.php#L33

> OFFSET $index");


Тут SQL инъекция.

> ORDER BY $sort $order


И тут

> $name = $student->getName();


> $stmt->bindValue(':name', $name);


Что мешает сразу писать $student->getName() без создания промежуточной переменной?

> $result = $stmt->fetch();


> return $result['count'];


Есть метод для получения одного значения.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Validator.php#L153

> checkArr($message)


Название ничего не говорит о том, что делает метод. "проверить массив" ничего не значит.

Для пола и locality нужно завести константы.

> [1-2][90]


Лучше вместо регулярки использовать сравнения вида $x > 1900 либо писать (19|20)

> OR ($form['name']=='Имя'))


Странная проверка.

> elseif ((preg_match($name_pattern, $form['name'])==1)&(mb_strlen($form['name'])>40)) {


> elseif ((preg_match($name_pattern, $form['name'])==1)&(mb_strlen($form['name'])>40)) {


> elseif ((preg_match($name_pattern, $form['name'])==1) &(preg_match($tag_pattern, $form['name'])==0) &(preg_match($digits_pattern,$form['name'])==0) &(40>mb_strlen($form['name'])) & (mb_strlen($form['name'])>0)){



Эта копипаста до добра не доведет. Надо либо перегруппировать ифы, либо вынести проверку имени в отдельный метод.

> href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css"


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

https://github.com/radiodog/studentlist/blob/master/src/View/Form.php
HTML код не отформатирован (отступы не соблюдаются) и его тяжело читать. Вместо табов лучше использовать 4 пробела.

https://github.com/radiodog/studentlist/blob/master/src/View/Form.php#L27

> value = "<?=$values['name']?>"


Тут XSS уязвимость.

> placeholder = "<


А HTML стандарт позволяет ставить пробел между названием атрибута и знаком равенства? Поищи-ка https://html.spec.whatwg.org/multipage/syntax.html#attributes-2

> <div class="invalid-feedback">


Возможно, стоит не показывать эти блоки, если ошибки нету.

> <a href='http://localhost/index.php/list'>Список студентов</a>


Используй относительные ссылки, где не указан протокол и домен. У меня есть урок про URL.

В шаблонах Form и List общая шапка и подвал, нужно убрать копипасту. Иначе замучаешься потом править в нескольких местах сразу.

https://github.com/radiodog/studentlist/blob/master/src/View/List.php#L49

> <?php $thisStudent = ($value->getEmail()==$this->dataGateway->getByHash($this->hashUser)['e_mail']) ? "table-active" : "" ?>


Этот код не должен быть во view. С каких это пор у нас View отвечает за проверку кук или поиск в БД?

https://github.com/radiodog/studentlist/blob/master/src/View/List.php#L64
Пагинатор очень громоздкий. Нельзя ли его сократить?

Вообще, ты бы мог сделать класс ViewHelper с обычными или статическими методами, которые бы помогали при выводе шаблона.
https://github.com/radiodog/studentlist #217 #1070224
>>1065726
>>1066173
>>1067949

> https://github.com/radiodog/studentlist/blob/master/composer.json


Тут name и description можно не указывать. У тебя же не библиотека.

> https://github.com/radiodog/studentlist/blob/master/mydb.sql


тут в дампе явно лишние команды, требующие администраторских привилегий, например, CREATE EXTENSION.

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

Папку vendor нужно внести в gitignore.

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

https://github.com/radiodog/studentlist/blob/master/src/Classes/Router.php
В конструкторе класса Router указан аргумент $url, но на самом деле туда передается массив. Причем нигде не описано какой именно массив, с какими полями. Не нужно так делать, нужно указать конкретные аргументы.

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

Тем более ненормально, что роутер еще и exit вызывает в конструкторе. Это вообще не роутер, а FrontController получается.

Сам алгоритм роутинга переусложнен, не проще сделать через сравнение строк или регулярки?

URL можно разобрать на части с помощью parse_url.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Controller.php
Базовый контроллер выглядит странно. Например, почему там прописана установка соединения с БД? Как-то немного странно. Зачем вообще в контроллере иметь объект PDO?

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

Проверку/установку авторизационных кук лучше сделать в отдельном классе/функциях, а не размазывать кусочками по коду.

Для хранения данных формы можно было использовать объект Student, а не массив.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Controller.php
Тут у тебя в случае успеха сообщение об успехе выводится до DOCTYPE, это неправильно. Это вообще может привести к тому, что кодировка не определится правильно. И после успешной обработки POST-формы надо делать редирект, а не выводит снова эту форму. Это описано в моем уроке про формы.

> public function getValuesFromPost()


Тут надо было использовать цикл, а не копипастить код.

> $validator->validate($values,$dataGateway);


> $message = $validator->message;


Что мешает вернуть результат функции через return? Зачем городить такой странный способ передачи результата?

> if ($values['e_mail']==$valuesFromDB['e_mail']) {


> $errors['e_mail'] ='';


Лучше в валидаторе сделать проверку, что при редактировании можно использовать тот же email.

> $student->setId($this->dataGateway->getCount()+1);


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

> getMarks($placeholder)


Это бы конечно лучше делать во view, а не тут.

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

Название MainController неудачное, не отражает назначение контроллера. И PageController тоже.

https://github.com/radiodog/studentlist/blob/master/src/Classes/PageController.php#L22

> if ($_SERVER['REQUEST_METHOD']=="GET"){


А если не GET, то что тогда произойдет?

> public function createNext($request)


> public function createPrev($request)


Тут сплошная копипаста. Лучше сделать одну универсальную функцию для генерации URL, и не в контроллере.

> $numPattern = "/(0-9)*/ui";


нет привязки к краям строки (^$)

> https://github.com/radiodog/studentlist/blob/master/src/Classes/PageController.php#L42


> $request['order'] = ....


> $request['order'] = ....



Создается впечатление, что первая строчка ничего не делает и не нужна.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Pager.php#L25
Тут какая-то переусложненная формула. Посчитать число страниц можно проще.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Student.php#L16
Слишком много аргументов в конструкторе. Лучше сделать либо пустой конструктор, либо сделать метод вроде updateAttributes, принимающий массив.

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

https://github.com/radiodog/studentlist/blob/master/src/Classes/UserDataGateway.php#L19

> return $row = ...


Зачем здесь создается переменная?

> https://github.com/radiodog/studentlist/blob/master/src/Classes/UserDataGateway.php


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

https://github.com/radiodog/studentlist/blob/master/src/Classes/UserDataGateway.php#L33

> OFFSET $index");


Тут SQL инъекция.

> ORDER BY $sort $order


И тут

> $name = $student->getName();


> $stmt->bindValue(':name', $name);


Что мешает сразу писать $student->getName() без создания промежуточной переменной?

> $result = $stmt->fetch();


> return $result['count'];


Есть метод для получения одного значения.

https://github.com/radiodog/studentlist/blob/master/src/Classes/Validator.php#L153

> checkArr($message)


Название ничего не говорит о том, что делает метод. "проверить массив" ничего не значит.

Для пола и locality нужно завести константы.

> [1-2][90]


Лучше вместо регулярки использовать сравнения вида $x > 1900 либо писать (19|20)

> OR ($form['name']=='Имя'))


Странная проверка.

> elseif ((preg_match($name_pattern, $form['name'])==1)&(mb_strlen($form['name'])>40)) {


> elseif ((preg_match($name_pattern, $form['name'])==1)&(mb_strlen($form['name'])>40)) {


> elseif ((preg_match($name_pattern, $form['name'])==1) &(preg_match($tag_pattern, $form['name'])==0) &(preg_match($digits_pattern,$form['name'])==0) &(40>mb_strlen($form['name'])) & (mb_strlen($form['name'])>0)){



Эта копипаста до добра не доведет. Надо либо перегруппировать ифы, либо вынести проверку имени в отдельный метод.

> href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css"


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

https://github.com/radiodog/studentlist/blob/master/src/View/Form.php
HTML код не отформатирован (отступы не соблюдаются) и его тяжело читать. Вместо табов лучше использовать 4 пробела.

https://github.com/radiodog/studentlist/blob/master/src/View/Form.php#L27

> value = "<?=$values['name']?>"


Тут XSS уязвимость.

> placeholder = "<


А HTML стандарт позволяет ставить пробел между названием атрибута и знаком равенства? Поищи-ка https://html.spec.whatwg.org/multipage/syntax.html#attributes-2

> <div class="invalid-feedback">


Возможно, стоит не показывать эти блоки, если ошибки нету.

> <a href='http://localhost/index.php/list'>Список студентов</a>


Используй относительные ссылки, где не указан протокол и домен. У меня есть урок про URL.

В шаблонах Form и List общая шапка и подвал, нужно убрать копипасту. Иначе замучаешься потом править в нескольких местах сразу.

https://github.com/radiodog/studentlist/blob/master/src/View/List.php#L49

> <?php $thisStudent = ($value->getEmail()==$this->dataGateway->getByHash($this->hashUser)['e_mail']) ? "table-active" : "" ?>


Этот код не должен быть во view. С каких это пор у нас View отвечает за проверку кук или поиск в БД?

https://github.com/radiodog/studentlist/blob/master/src/View/List.php#L64
Пагинатор очень громоздкий. Нельзя ли его сократить?

Вообще, ты бы мог сделать класс ViewHelper с обычными или статическими методами, которые бы помогали при выводе шаблона.
#218 #1070254
https://ideone.com/E5dpXQ

Я сделал. Правильно?
#219 #1070261
>>1068108
Решил проблему

Как я уже говорил, в моей обёртке ничего не возвращалось, и вообще странно что я в итоге что-то получил. Мне пришла в голову мысль, что странно, что я получил значения вне обещания (обычно мы в таком случае получаем undefined), и решил что сначала нужно получить все обещания, а потом проходить по ним циклом, в итоге даже обёртка не понадобилась:

getMessages.then(function(messages) {
var promises = [];

for (var key in messages) {
var decrypted = decrypt(messages[key]);

promises.push(decrypted); // Можно даже не выставлять ключ, обещания добавятся синхронно, а асинхронное выполнение будет позже
}

Promise.all(promises).then(function(decrypted) {
for (var key in messages) {
messages[key] = decrypted[key].data;
}

showMessages(messages);
});

});

Вот и всё! Всё оказалось очень просто.
Немого смущает что один и тот же цикл повторяется дважды, но в этом ничего плохого.


Немного пугает, что я не мучился над решением этой задачи, её решение пришло мне в голову само собой. Можно сказать, что мне просто повезло.
Я просто подумал, как бы я её решил если не было возможности получить вашего совета, и единственное что пришло в голову, это то что бы я просто выводил бы сообщения по одному внутри метода расшифровки, что являлось бы самим по себе нарушением инкапсуляции. Только через некоторое время мысль о том, что можно получить обещания и выполнить их все сразу, пришла сама собой.
Если бы не ваши наставления, я бы писал довольно хаотичный код, и даже не чувствовал за это угрызение совести.
#219 #1070261
>>1068108
Решил проблему

Как я уже говорил, в моей обёртке ничего не возвращалось, и вообще странно что я в итоге что-то получил. Мне пришла в голову мысль, что странно, что я получил значения вне обещания (обычно мы в таком случае получаем undefined), и решил что сначала нужно получить все обещания, а потом проходить по ним циклом, в итоге даже обёртка не понадобилась:

getMessages.then(function(messages) {
var promises = [];

for (var key in messages) {
var decrypted = decrypt(messages[key]);

promises.push(decrypted); // Можно даже не выставлять ключ, обещания добавятся синхронно, а асинхронное выполнение будет позже
}

Promise.all(promises).then(function(decrypted) {
for (var key in messages) {
messages[key] = decrypted[key].data;
}

showMessages(messages);
});

});

Вот и всё! Всё оказалось очень просто.
Немого смущает что один и тот же цикл повторяется дважды, но в этом ничего плохого.


Немного пугает, что я не мучился над решением этой задачи, её решение пришло мне в голову само собой. Можно сказать, что мне просто повезло.
Я просто подумал, как бы я её решил если не было возможности получить вашего совета, и единственное что пришло в голову, это то что бы я просто выводил бы сообщения по одному внутри метода расшифровки, что являлось бы самим по себе нарушением инкапсуляции. Только через некоторое время мысль о том, что можно получить обещания и выполнить их все сразу, пришла сама собой.
Если бы не ваши наставления, я бы писал довольно хаотичный код, и даже не чувствовал за это угрызение совести.
#220 #1070279
>>1070254

>$monthlyPay = 5000;


>if ($totalSum <= 5000)


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

И ещё пара придирок:

>echo "{$month} месяц спустя: долг = {$totalSum} руб, выплачено всего {$paymentTotal} руб. \n";


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

Если это не редактор кода сломал оформление, то советую почитать >>1067945
Очень много лишних отступов и табуляций.
#221 #1070462
>>1070024

>Slim


Нет. Что это?
#222 #1070472
>>1070117

>Что значит в плюсах?


напсать эту прогу на с++
#223 #1070475
Сколько нужно изучать php чтобы понимать о чем тут говорит 90% людей?
#224 #1070476
>>1070475
Неделю
#225 #1070493
>>1070472

Вот жи >>1070178, только с индексацией в массиве обосрался чуть. Ничего ведь сложного, десять минут гугла.
#227 #1070501
Погромисты, поясните про регулярку пожалуйста
чем вот эта: [a-z][a-z][0-9][0-9][0-9][a-z]
отличается от этой: [a-z]{2}[0-9]{3}[a-z]{1}

число в {} говорит о количестве повторений, правильно?
#228 #1070502
Как понять ООП, MVC и прочие сложные концепции? Осилил большинство задач для ньюфагов от ОПа кроме бонусных, теперь приступил к уроку по ООП, но мне кажется, что этого будет мало. Я совсем ньюфаг в программировании. Вроде примитивный computational thinking освоил, но когда открываю профессиональный код какого-нибудь сайта, то охуеваю. Что еще можно почитать про ООП? Неважно на каком языке, главное чтобы было максимально просто разжевано.
#229 #1070505
>>1070224
Спасибо большое!
#230 #1070507
>>1070502
Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования

Ну и практика
124 Кб, 1680x900
#231 #1070522
https://ideone.com/uMaxHO

Понимаю, что плохо и криво. Не понимаю, как сделать лучше. Очень хочется уйти от принципа "но ведь работает же!" и перестать писать говнокод.
#232 #1070528
>>1070522
я занимаюсь php вот уже который год два дня, но мне все нравится, особенно рандом внутри ключа массива. Идеальней ведь не напишешь. Есть тут гуру? Все же верно вроде и не говнокод
#233 #1070544
Начал делать задачу с файлообменником, не могу разобраться с nginx: установил, сделал конфиг как в руководстве от Slim (там, кстати, два немного отличающихся в разделе web servers и в first application, но он мне отдает – 504 Gateway Time-out. Время ожидания пробовал менять, nginx -s reload незабывал, все равно результат одинаков. Как быть?
#234 #1070548
В седьмом ПХП функция mb_internal_encoding не работает (пик один).
В пятом ПХП уже не ругается и компилит, но только с латиницей (пик два).
С кириллицей выходит лажа (пик три).
#235 #1070551
Аноны, дайте пожалуйста ответ на задачу, где сравниваются телефоны согласно регулярному выражению:
http://archive-ipq-co.narod.ru/l1/regexp.html

Вот список номеров:

// Правильные:
$correctNumbers = [
'84951234567', '+74951234567', '8-495-1-234-567',
' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67',
'8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567',
'8 ( 999 ) 1234567', '8 999 123 4567'
];

// Неправильные:
$incorrectNumbers = [
'02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', / неверный код страны /
'+8 234 5678901', / либо 8 либо +7 /
'7 234 5678901' / нет + /
];



Какой смысл корячится и изголяться с учетом скобок/пробелов/минусов, если можно просто убрать эти символы из строки?
Опчик помогай #236 #1070552
Можно ли без своей реализации сделать на yii2 чтобы и httpBasicAuth работал и обычная браузерная аутентификация основанная на сессии? Мне надо чтобы сайт работал в двух режимах: и как обычный сайт и как API если передать определенный параметр, вот встал вопрос реализации аутентификации по токенам.
>>1070551

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


Но ведь юзер об этом не узнает, ввел он телефон в одном формате, а потом к примеру пытается восстановить пароль или залогиниться по номеру, а ты сохранил номер в другом виде. Вообще для этих целей используют masked input который не дает юзерам выстрелить себе в ногу неправильным вводом номера
#237 #1070555
>>1070544
Причем тут слим, читай мануал нгинкс для своего дистра. Если шперма то хз.
#238 #1070558
>>1070552

>Но ведь юзер об этом не узнает


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

$wwq = array("\"", "'", ";", ",", ":", "/", "\\", "=", ")", "(", "%", "*", "?");
$row['title'] = str_replace($wwq, "", $row['title']);

а потом уже совать в регулярку голые цифры?
Меня будет будущий тимлид ругать за то, что я сделаю проще, а не через регулярку?
#239 #1070564
>>1070558

>$wwq = array("\"", "'", ";", ",", ":", "/", "\\", "=", ")", "(", "%", "", "?");


>$row['title'] = str_replace($wwq, "", $row['title']);


Проще же
preg_replace('/(\\D)
/', '', $string) тогда.

>Меня будет будущий тимлид ругать за то, что я сделаю проще, а не через регулярку?


Редко приходится работать с регулярками, но ты должен иметь представление, что это и для чего их можно использовать
#240 #1070572
>>1070564
спасибо
#241 #1070573
>>1070555
Слим при том, что там есть простейший вариант конфига для фронт контроллера
#242 #1070590
>>1070544
>>1070573
Сделал, надо было вручную php-cgi включать
#243 #1070595
>>1070016

А что ты изучал до Юи?

>>1070501

Да

>>1070502

Ты сначала пройди задачу про Вектор, а потом посмотрим. Чтобы разобраться в MVC и вообще в приложениях с таблицами и формами, есть задача про студентов в ОП посте.

>>1070544

Gateway timeout значит что нгинкс отправил запрос на бекенд (например на php-fpm), но ответа не пришло. Тебе надо разобраться в своем конфиге, куда он отправляет запросы и почему на них не отвечают вовремя.

>>1070558

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

>>1070564

> preg_replace('/(\\D)/', '', $string)


Это вырежет буквы, а наличие букв должно делать номер неправильным.
#244 #1070596
>>1070595
Голый php/js. Ну, ещё краем аякс и jquery захватил.
#245 #1070597
>>1070595

>Ты наверно просто не знаешь, как это сделать регуляркой.


не знаю, поэтому и спрашиваю ответ. А ответа именно к этой задаче нету.
Кроме того, мне кажется, что убрать одной регуляркой всё кроме цифр намного проще, чем писать регулярку, которая будет учитывать:
1.Начало с +7, + 7, 8
2.Палочки, скобочки, пробелы
3.Все вышеперечисленное определенной длины
#246 #1070599
Сап, помогите с Laravel:
Есть роут Route::group(['domain' => 'admin.' . env('APP_DOMAIN') где APP_DOMAIN = sitename.dev. На сервере у меня нормально заходит по этому адресу, но на локалке получаю Server not found (ошибка как будто я захожу на несуществующий сайт). В route:list всё нормально. Как настроить правильно?
#247 #1070613
Знающие аноны, подскажите, пожалуйста, по регулярному выражению в задаче про телефоны. Я с подсказки доброго анона сделал ее через предварительную замену ненужных символов (в коде закомменчено), а сейчас пытаюсь сделать через одну регулярку онли

вот код:
https://ideone.com/e.js/ZCPtZ5

он вроде пропускает все хорошие номера, но и часть плохих тоже пропускает

вот сама регулярка:
$regexp = "/(\+7|8|\+ 7)+[0-9\-\(\)\s]{10}/ui";
как сделать чтобы {10} применялось ко всей строчке, а не только, как я понимаю, к последнему куску, и как обрезать "позвать люсю"?
#248 #1070615
>>1070613

Квантификатор {10} применяется к идущей перед ним конструкции [0-9\-\(\)\s]

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

(выражение){10}
#249 #1070616
>>1070613

> и как обрезать "позвать люсю"?



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

aaaaaa +70001234567 ааааааааа

Нужно использовать привязку к краям строки с помощью ^ и $.
#250 #1070617
>>1070551

Можно убрать, но сделать нужную регулярку проще, если ты хорошо в них разбираешься.
#251 #1070643
>>1070202

>- создает значение типа DATETIME, а не TIMESTAMP. Потому что DATETIME позволяет представить более широкий диапазон дат. Могут ли от этого быть проблемы? Для этого придется изучить в мануале отличия типов DATETIME и TIMESTAMP и сделать выводы.


Как тогда получить TIMESTAMP, если префикс TIMESTAMP означает DATETIME?
#252 #1070663
>>1070643

С помощью литералов - никак, но может быть там есть функция конвертации в TIMESTAMP?

Можно поискать по слову timestamp тут: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timestamp

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

А какой у тебя случай? Зачем тебе понадобилось именно значение типа TIMESTAMP, можно поинтересоваться? Что в нем есть такого, чего нет в DATETIME?

Если что, мануал по особенностям этих типов тут:

- https://dev.mysql.com/doc/refman/5.7/en/date-and-time-types.html
- https://dev.mysql.com/doc/refman/5.7/en/datetime.html
#253 #1070682
>>1070615
>>1070616
спасибо, няши, буду пробовать
#254 #1070761
>>1070663

>А какой у тебя случай?


Я решил прочитать документацию MySQL, вот какой у меня случай. :3 Терплю умеренные бомбардировки тылов в связи с тем, как она написана.
#255 #1070788
>>1070573
Нгинкс никак не соотносится с твоим фронт-контроллером, всё зависит от ос которую ты используешь, равно как и апач, это так сказать сфера системного администрирования уже. Там написано только то, что тебе нужно сделать на стороне приложения, конфиг самого сервера нужно курить дополнительно.
>>1070590
Молодца, ежели разобрался.
#256 #1070821
https://ideone.com/51rYLU

Чо я не так написал? Вроде всё норм, но припопытке нажатия на кнопку жалуется мол "Warning: implode(): Invalid arguments passed in ..\json_answer.php on line 4"

Код json_answer.php посередине.
#257 #1070829
>>1070821
Сердце аж схватило от велосипеда в Js. Почитай про .serialize()
#258 #1071006
>>1070829
Ладно, посиотрим. А можно чуть подробнее суть проблемы?
#259 #1071029
ОП, в общем я все переделал заново, код не смотрел прошлый, я его просто удалил, но судя по твоим замечаниям он был убог.
Я совершенно случайно додумался сделать динамичную адаптивную верстку, не знаю это ли ты имел ввиду когда говорил, чтобы я сделал не механическую верстку. Я проверил страницу на 3х устройствах, сбоев нет. Пока не знаю как включить виртуалку, чтобы проверить на IE-7-11, но представляю что там будет, браузерстак пока покупать не в состояний, будущем подпишусь.
Сделать мульти-страничный CSS не смог, осознание пришло под самый конец, поисправлял кучу классов и.т.д
Верстка заняла примерно 4 дня, не полных конечно же.
https://theknacker.github.io/Webpaint/webpaint.html
5 Кб, 826x361
#260 #1071067
Я снова с Yii2. И всё с тем же вопросом.
Может кто-нибудь подробно объяснить логику рботы фреймворка, когда на вью страницы есть несколько кнопок?

Без него всё было просто: для логина три инпута и кнопка. На кнопке висит onclick="register();", запускающий предачу данных через аякс php-скрипту. А таблица генерируется динамически через foreach, столько строк, сколько есть в базе юзеров. И кнопка удаления на каждой строке onclick='delete_line($user_id, $table_users);' При нажатии, js-скрипт передаёт данные аяксом php-скрипту и тот удаляет из указанной таблицы указанную строку.

Теперь с фреймворком.
Создал модель SignupForm с атрибутами и парой методов. Подключил в контроллере, создал public function actionSignup(). В неём загрузка и проверка данных:
$model = new SignupForm(); //создаём объект модели UsersForm
if($model->load(\Yii::$app->request->post()) && $model->validate()){}
$user = new User(); //создаём объект модели User (эта модель указана в качестве компонента идентификации в файле config\web.php)
$user->username = $model->username; //передаём атрибут модели UsersForm в атрибут модели User
$user->full_name = $model->full_name; //заполним его полученными из формы данными
$user->password = \Yii::$app->security->generatePasswordHash($model->password); //Аналогично, только ещё и шифруем
if($user->save()){
return $this->render('users', compact('model')); //рендерим вью users, передав в него модель model
}
А во вью прописываем $form = ActiveForm::begin(), затем поля для ввода $form->field($model, 'username', ['template' => '{label} <div class="row"><div class="col-sm-2">{input}{error}{hint}</div></div>']), кнопку Html::submitButton('Регистрация', ['class' => 'btn btn-success', 'id' => 'add1', 'name' => 'add2']) и в конце ActiveForm::end().

Это всё как-то даже работает. Но как правильно сгенерировать кнопки удаления и обрабатывать их нажатия?
1) Все поля и кнопки во вью должны быть между begin() - end(), или для каждого блока эта конструкция должна быть своя?
2) Обработка идёт в контроллере? В одном и том же акшене? Как проверить, от какой кнопки пришло нажатие?
3) Модель не трогаем?
4) Что за \ в акшене? Я переписал это из урока по Yii, но нагуглить, что это такое, не смог.
5) Я не понимаю конструкцию $model->load(\Yii::$app->request->post()) && $model->validate()
По сути, она загружает в модель полученные данные, если они получены и провалидированы. Но если разбираться, то получается, что сначала данные приходят постом, потом валидируется модель, в которой пока что нет новых данных (и непонятно, зачем вообще её проверять), а потом идёт load непонятно чего.
6) Как вообще вытащить из post данные в контроллере? Я делал
echo '<pre>'; print_r($model); //распечатка модели
и получал все данные, а вот получить конкретное значение поля, которое ввёл юзер, не могу.
5 Кб, 826x361
#260 #1071067
Я снова с Yii2. И всё с тем же вопросом.
Может кто-нибудь подробно объяснить логику рботы фреймворка, когда на вью страницы есть несколько кнопок?

Без него всё было просто: для логина три инпута и кнопка. На кнопке висит onclick="register();", запускающий предачу данных через аякс php-скрипту. А таблица генерируется динамически через foreach, столько строк, сколько есть в базе юзеров. И кнопка удаления на каждой строке onclick='delete_line($user_id, $table_users);' При нажатии, js-скрипт передаёт данные аяксом php-скрипту и тот удаляет из указанной таблицы указанную строку.

Теперь с фреймворком.
Создал модель SignupForm с атрибутами и парой методов. Подключил в контроллере, создал public function actionSignup(). В неём загрузка и проверка данных:
$model = new SignupForm(); //создаём объект модели UsersForm
if($model->load(\Yii::$app->request->post()) && $model->validate()){}
$user = new User(); //создаём объект модели User (эта модель указана в качестве компонента идентификации в файле config\web.php)
$user->username = $model->username; //передаём атрибут модели UsersForm в атрибут модели User
$user->full_name = $model->full_name; //заполним его полученными из формы данными
$user->password = \Yii::$app->security->generatePasswordHash($model->password); //Аналогично, только ещё и шифруем
if($user->save()){
return $this->render('users', compact('model')); //рендерим вью users, передав в него модель model
}
А во вью прописываем $form = ActiveForm::begin(), затем поля для ввода $form->field($model, 'username', ['template' => '{label} <div class="row"><div class="col-sm-2">{input}{error}{hint}</div></div>']), кнопку Html::submitButton('Регистрация', ['class' => 'btn btn-success', 'id' => 'add1', 'name' => 'add2']) и в конце ActiveForm::end().

Это всё как-то даже работает. Но как правильно сгенерировать кнопки удаления и обрабатывать их нажатия?
1) Все поля и кнопки во вью должны быть между begin() - end(), или для каждого блока эта конструкция должна быть своя?
2) Обработка идёт в контроллере? В одном и том же акшене? Как проверить, от какой кнопки пришло нажатие?
3) Модель не трогаем?
4) Что за \ в акшене? Я переписал это из урока по Yii, но нагуглить, что это такое, не смог.
5) Я не понимаю конструкцию $model->load(\Yii::$app->request->post()) && $model->validate()
По сути, она загружает в модель полученные данные, если они получены и провалидированы. Но если разбираться, то получается, что сначала данные приходят постом, потом валидируется модель, в которой пока что нет новых данных (и непонятно, зачем вообще её проверять), а потом идёт load непонятно чего.
6) Как вообще вытащить из post данные в контроллере? Я делал
echo '<pre>'; print_r($model); //распечатка модели
и получал все данные, а вот получить конкретное значение поля, которое ввёл юзер, не могу.
#261 #1071068
>>1071029
Я не ОП, но по-моему отлично вышло.
#262 #1071081
>>1071067
Могу предположить что бэкслеш это говорит о Неймспейсе
#263 #1071084
>>1071081

>говорит о Неймспейсе


Непонятно.
#264 #1071087
>>1071067
\Yii::$app->request->post()
вот это и есть твой $_POST
#265 #1071089
>>1071087
Ну, это-то понятно, но зачем "\"? Без него никак нельзя? Что-то же он делает.
#266 #1071092
>>1071089
напиши вначале скрипта use \Yii as Yii
и можешь убрать его.

Вот урок по теме от Опа
#268 #1071118
>>1070224
pdo объект лучше создавать в конструкторе объекта работы с базой данных?
#269 #1071148
>>1071068
Благодарю, добрый анон.
#270 #1071151
https://ideone.com/Qk2CzO
Не работает команда ORDER BY. Параметр проходит правильно, в консоли запрос отлаживал. ЧЯДНТ?
#271 #1071166
>>1071151

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

Имя поля нужно вставлять напрямую в запрос, предварительно проверив его по списку разрешенных значений.
#272 #1071170
>>1071166
Да, я уже разобрался. Интересно, почему PDO не предусматривает возможности подставлять имя поля или таблиц? Вроде же логично что бы была и такая фича.
#273 #1071174
>>1071170

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

Для запроса вроде такого:

SELECT x FROM t WHERE a = ?

Здесь СУБД может построить план запроса, не зная подставляемого значения.

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

Хотя я согласен, что есть смысл в том, что ты предлагаешь. Для этого можно написать библиотеку поверх PDO. Я такие возможности видел в одной старой библиотеке плейсхолдеров которую когда-то использовал (да, я почти с самого начала писал запросы с плейсхолдерами, хотя PDO тогда еще не было и в учебниках про них не писали): http://dklab.ru/lib/DbSimple/ (внимание! библиотека безнадежно устарела).

Вообще конечно, было бы хорошо, если бы какой-нибудь анон с запасом свободного времени сделал бы обзор разных библиотек для работы с БД.
#274 #1071177
>>1071151
Кстати там же у меня не работает WHERE LIKE, я так понимаю там тоже надо как-то хитро экранировать, не?
#275 #1071221
>>1071177

Нет, это не из-за плейсхолдеров.

Также, ORDER BY или WHERE правильнее будет назвать не "командой", а "конструкцией". По английски это называется clause (например, "This statement contains ORDER BY clause" - в этом запросе есть конструкция ORDER BY), а по-русски мне ничего, кроме "конструкция" в голову не приходит.

Вообще, clause переводится так: http://dictionary.cambridge.org/ru/словарь/англо-русский/clause

Основной смысл - статья (пункт) в договоре.

Тут https://postgrespro.ru/docs/postgresql/9.6/queries-table-expressions.html clause переводят как "предложение", но мне кажется, это неудачный перевод.

Если кто-нибудь из анонов видел другие переводы термина clause в книгах (желательно поофициальней), напишите пожалуйста.
#276 #1071223
>>1071221
Ну кусок "WHERE
name LIKE :search OR
secondName LIKE :search OR
groupNumber LIKE :search OR
summary LIKE :search "
У меня не работает, опять же если без плейсхолдеров то все норм.
#277 #1071261
>>1071089
Потому что, если у тебя в файле объявлен неймспейс, например
namespace frontend\controllers;
то Yii::$app->request->post() попытается обратиться к frontend\controllers\Yii::$app->request->post();
Чтобы этого избежать - как выше писал анон - можно сделать use Yii; либо указать \ (рут)
#278 #1071262
Аноны дайте совет битарду. Смогу запустить контекстную рекламу на сайт, который создан на конструкторе ukit.com? как данные сайты себя чувствуют в поисковых запросах? сфера моих услуг - юриспруденция. Или может лучше заказать сайт на битриксе у анонов?
#279 #1071264
>>1071262
Лучше и школьников каких-то закажи визитку на вордпрессе и отдельно ищи услуги по раскрутке. Битрикс нахуй не нужен.
#280 #1071266
>>1071264
думаешь так лучше будет?а шаблонный на конструкторе совсем дно?
#281 #1071269
>>1071264
еще вопрос, а без опыта, я сам не сделаю на вордпрессе?
#282 #1071271
>>1071269
Сделаешь
#283 #1071276
>>1071271
збс
#284 #1071295
>>1071276
Но вот что именно ты сделаешь - большой вопрос. Наверни The7, она ахуенна!
#285 #1071300
>>1070829
ААААААА! Сука, что за хуйня там. Целая страница ёбаного кода. Я нихуя понять не могу, что не так блять.
#286 #1071304
>>1071262
вордпресс или джумла, там без проблем разобраться. А битрикс скорее нужен для сайтов с каталогами товаров и выгрузкой/загрузкой в 1с.
#287 #1071307
>>1071304
У битрикса дохуя возможностей, но без опыта кодинга там особо делать нечего
#288 #1071325
Есть какой-нибудь гайд по деплою приложухи на хероку? А то на офиц сайте не очень понятно, интересует именно подключение к базе. + на хероку же постгрес, пытался сейчас создать таблицы в консоли, нихуя не получается, куча ошибок. Кое-как таки создал страницу с юзерами, инсертнул туда данные, пытаюсь войти на сайт - просто страница обновляется, и даже не ебу в чем проблема, ведь базу я не могу посмотреть, ошибок тоже никаких. Делал на PDO, если что.
#289 #1071330
>>1071118

Лучше использовать DI: https://github.com/codedokode/pasta/blob/master/arch/di.md

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

Там в статье есть часть кода простейшего контейнера, а можно в принципе сделать еще проще и использовать в качестве контейнера просто массив.
#290 #1071332
Анончес, как сделать из мухи слона на PHP?
240 Кб, 1920x1080
#291 #1071341
Блядь, я с этими регулярками ковыряюсь как обезъяна с астролябией. Но мозг работает, это хорошо.
Уже почти все правильные варианты могу отобрать, кроме одного, при всего лишь трех ложных срабатываниях. Идти дальше по упражнениям или продолжать задрачивать?
#292 #1071345
>>1071325

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

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

По поводу логов тут https://devcenter.heroku.com/articles/php-logging#logging-from-plain-php написано что ошибки должны идти в "heroku logs".

Соответственно тут дана команда просмотра логов: https://devcenter.heroku.com/articles/logging#view-logs

Попробуй с нее начать.

Также, можно получить доступ к консоли, если ты знаком с линуксовыми командами: https://devcenter.heroku.com/articles/getting-started-with-php#start-an-interactive-shell

Из консоли можно например попробовать соединиться с БД, выполнять какие-то SQL запросы.

Тут описано подключение к Postgres: https://devcenter.heroku.com/articles/getting-started-with-php#provision-a-database

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

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

Идея передавать конфигурацию в переменных окружения есть в сборнике статей 12 factor app: https://12factor.net/ru/config

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

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

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

По поводу логов тут https://devcenter.heroku.com/articles/php-logging#logging-from-plain-php написано что ошибки должны идти в "heroku logs".

Соответственно тут дана команда просмотра логов: https://devcenter.heroku.com/articles/logging#view-logs

Попробуй с нее начать.

Также, можно получить доступ к консоли, если ты знаком с линуксовыми командами: https://devcenter.heroku.com/articles/getting-started-with-php#start-an-interactive-shell

Из консоли можно например попробовать соединиться с БД, выполнять какие-то SQL запросы.

Тут описано подключение к Postgres: https://devcenter.heroku.com/articles/getting-started-with-php#provision-a-database

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

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

Идея передавать конфигурацию в переменных окружения есть в сборнике статей 12 factor app: https://12factor.net/ru/config

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

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

В твоем случае я вижу такие проблемы:

- никак не задано точное число цифр в регулярке. [\d\s]{7,14} - это значит от 7 до 14 цифр и других знаков, а должно быть 7 или +8, за ней ровно 10 цифр
- используются противоречащие друг другу квантификаторы. Например: (\s?|...)+ "?" обозначает 0 или 1 повторение, "+" - 1 или больше. Так что ты хотел написать в итоге?

Если ты хотел написать "любое число скобок, минусов, пробелов" то лучше сделать это так:

- написать выражение для "одна скобка, минус или пробел"
- добаивить к нему квантификатор "от 0 до любого числа повторов"

А вообще, тут подошла бы такая регулярка:

- вначале идет +7 или 8
- за ней ровно 10 раз такое выражение: 1 цифра, за ней любое число минусов, скобок пробелов

Разумеется, копипастить выражение 10 раз не нужно, используй квантификатор.
#294 #1071358
>>1071355

>Если ты хотел написать "любое число скобок, минусов, пробелов"


Это и хотел.

>1 цифра, за ней любое число минусов, скобок пробелов


Почему не наоборот - сначала любое количество скобок, минусов и пробелов, а потом цифра? После +7 или 8 цифрты-то может и не быть.
#295 #1071361
>>1071341

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

- привязка к краям строки ^ и $
- привязка к краю слова \b
- один конкретный символ (a)
- один любой символ (.)
- один символ из определенной группы: \s, \d, \w
- один любой символ из набора [1234a-f]
- один любой символ, кроме указанных [^abc]
- одно из выражений: (X|Y|Z)
- повторение выражения указанное число раз: вопрос, звездочка, плюс, {N,M} в сочетании с круглыми скобками

Разумеется, ты должен знать все указанные выше конструкции наизусть.

Там еще есть другие конструкции (подробности в мануале http://php.net/manual/ru/pcre.pattern.php ) но для наших задач хватит того, что я привел
#296 #1071362
>>1071358

> Почему не наоборот


Можно и так, не принципиально. Я общую идею только привел, как сделать, чтобы было ровно 10 цифр. Главное, чтобы ты умел с помощью простых условий строить сложные шаблоны осознанно, а не наугад переставлял символы.
248 Кб, 1920x1080
#297 #1071364
>>1071361
>>1071362
Блин, аноны, с вашей подсказкой слишком просто получилось.
Зато я понял свою ошибку. Квантификаторы внутри квантификаторов - это так просто но совершенно контринтуитивно.
#298 #1071371
>>1071364

Можно сделать лучше. Во-первых,у тебя 2 раза повторяется +7 с небольшими изменениями.

Во-вторых, для квантификатора "от 0 до бесконечности повторов" есть более короткая запись.
246 Кб, 1920x1080
#299 #1071372
>>1071371
Так лучше?
#300 #1071376
>>1071372
Во!

^([\s\+][78])([\s\(\)\-]\d){10}$
250 Кб, 1920x1080
#301 #1071378
>>1071376
Разметка схавала.
#302 #1071387
>>1071330
Спасибо большое!
#303 #1071398
>>1071372

Так пройдет номер +78 и 10 цифр

>>1071378

Так пройдет номер с +8 в начале или с 7 без +.

>>1071262

Если у твоего сайта есть URL то сможешь. Но не надо тут устраивать флуд из кучи коротких сообщений.

>>1071223

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

>>1071089

Трудно изучать Юи, если ты не изучил нормально объекты, классы и нейсмпейсы. Урок по основам ООП есть в учебнике в ОП посте, про неймспейсы доброанон тебе дал ссылку выше. И по хорошему, тебе бы не мешало решить задачку про студентов из ОП поста, чтобы освоиться с основами создания CRUD приложений. Тогда тебе многое было бы понятнее, мне кажется.

>>1071067

Вообще, тебе надо сначала прочесть документацию Юи по работе с формами. Я думаю, он умеет сам копировать данные из модели формы в модель сущности БД.

Разные кнопки можно различать, если дать им разные имена - нажатая кнопка передается в POST.

> Я не понимаю конструкцию $model->load(\Yii::$app->request->post()) && $model->validate()


Я тоже, по моему она неправильная

> Все поля и кнопки во вью должны быть между begin() - end(),


Ну ты изучи, что делают эти функции, какой HTML вставляют в шаблон.

> Как проверить, от какой кнопки пришло нажатие?


Ее имя будет содержаться в POST данных

> Как вообще вытащить из post данные в контроллере?


Они находятся в объекте request, изучи документацию по нему.
#303 #1071398
>>1071372

Так пройдет номер +78 и 10 цифр

>>1071378

Так пройдет номер с +8 в начале или с 7 без +.

>>1071262

Если у твоего сайта есть URL то сможешь. Но не надо тут устраивать флуд из кучи коротких сообщений.

>>1071223

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

>>1071089

Трудно изучать Юи, если ты не изучил нормально объекты, классы и нейсмпейсы. Урок по основам ООП есть в учебнике в ОП посте, про неймспейсы доброанон тебе дал ссылку выше. И по хорошему, тебе бы не мешало решить задачку про студентов из ОП поста, чтобы освоиться с основами создания CRUD приложений. Тогда тебе многое было бы понятнее, мне кажется.

>>1071067

Вообще, тебе надо сначала прочесть документацию Юи по работе с формами. Я думаю, он умеет сам копировать данные из модели формы в модель сущности БД.

Разные кнопки можно различать, если дать им разные имена - нажатая кнопка передается в POST.

> Я не понимаю конструкцию $model->load(\Yii::$app->request->post()) && $model->validate()


Я тоже, по моему она неправильная

> Все поля и кнопки во вью должны быть между begin() - end(),


Ну ты изучи, что делают эти функции, какой HTML вставляют в шаблон.

> Как проверить, от какой кнопки пришло нажатие?


Ее имя будет содержаться в POST данных

> Как вообще вытащить из post данные в контроллере?


Они находятся в объекте request, изучи документацию по нему.
https://theknacker.github.io/Webpaint/webpaint.html #304 #1071399
>>1071029

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


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

browserstack можно (вроде бы) пользоваться бесплатно несколько раз, если зарегистрироваться. И можно даже без регистрации, если отправлять запрос с сайта modern.ie. Найдешь ссылку сам? Я проверил, работает.

Далее, сделаем простой тест. Возьмем и добавим на твою страницу section с HTML-кодом взятым отсюда http://motherfuckingwebsite.com/ или отсюда http://www.blindtextgenerator.com/snippets?snipps=EN-snippets-kafka . Или вообще очищаем содержимое body и вставляем туда HTML код.

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

Что мы видим у тебя? https://pste.eu/p/HRFa.html - это явно нельзя назвать красиво выглядящим текстом в стиле сайта. Каша какая-то.

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

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

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

У тебя сейчас стили текста заданы только для абзаца внутри определенного блока: .service_item p { ... }. Это неправильно, нужно их задавать для html, чтобы они работали по умолчанию на всей странице.

Более того, ты исопльзуешь CSS reset, который обнуляет многие полезные стили. В итоге текст не выглядит как текст, а как нечитаемая каша. Если ты используешь CSS reset, ты обязан задать стили для всех элементов, для которых ты их сбросил тут в начале: https://theknacker.github.io/Webpaint/style.css (и если подумать, то окажется что выгоднее не использовать CSS reset вообще, чем сбрасывать стили и затем заново ставить им обратно те же значения).

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

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

Далее, у тебя там есть стили слишком широкого действия:

> a:not(.logo), label, img {


> transition: all 200ms linear


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

Или тут:

> li a{



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

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

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

Далее, ты там используешь width: fit-content, про который я первый раз слышу, и видимо не только я, так как он мало где поддерживается: https://developer.mozilla.org/ru/docs/Web/CSS/fit-content#Browser_compatibility и по моему ты даже используешь эту функцию неправильно.

Насчет тега cite я тоже не уверен - я тут почитал https://developer.mozilla.org/ru/docs/Web/HTML/Element/cite - можно ли его использовать для указания копирайта?

> input#graphic:checked ~ a:not([href="#graphic"]),


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

> <div class="service_image_android"></div>


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

Еще по моему на макете был курсив в шапке.

И вот тут вот проблема: безымянный див:

> <footer>


> <div>



div сам по себе не несет никакого смысла, он предназначен для нестандартных элементов, и смысл этих элементов задается id или классом. А ты не используешь тут класс и потом городишь какие-то трудные для понимания селекторы. Завтра кто-то добавит третий див, и все стили собъются потому что у тебя там используется :last-of-type.

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

Если тебе интересно, ты можешь еще почитать про методологию БЭМ, которая как раз придумана, чтобы упростить дальнейшую поддержку кода, чтобы верстку было как можно легче править в будущем: https://ru.bem.info/methodology/ У нас тут очень простая верстка, и БЭМ использовать не требуется, но если ты будешь верстать более сложные страницы, а тем более сайты с большим числом страниц, понимание БЭМ тебе пригодится. Прочитай, если есть время.

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

Также у тебя нет метатега viewport ( http://frontender.com.ua/mobile-web/wtf-viewport/ ).

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

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

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

Я бы конечно еще тебе хотел дать задачу исследовать варианты подключения SVG картинок, какие при этом возникают сложности, как они поддерживаются в разных браузерах, но не знаю, готов ли ты такую задачу сделать, есть ли время. Если есть, то потом я тебе объясню, что надо сделать и зачем.
https://theknacker.github.io/Webpaint/webpaint.html #304 #1071399
>>1071029

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


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

browserstack можно (вроде бы) пользоваться бесплатно несколько раз, если зарегистрироваться. И можно даже без регистрации, если отправлять запрос с сайта modern.ie. Найдешь ссылку сам? Я проверил, работает.

Далее, сделаем простой тест. Возьмем и добавим на твою страницу section с HTML-кодом взятым отсюда http://motherfuckingwebsite.com/ или отсюда http://www.blindtextgenerator.com/snippets?snipps=EN-snippets-kafka . Или вообще очищаем содержимое body и вставляем туда HTML код.

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

Что мы видим у тебя? https://pste.eu/p/HRFa.html - это явно нельзя назвать красиво выглядящим текстом в стиле сайта. Каша какая-то.

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

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

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

У тебя сейчас стили текста заданы только для абзаца внутри определенного блока: .service_item p { ... }. Это неправильно, нужно их задавать для html, чтобы они работали по умолчанию на всей странице.

Более того, ты исопльзуешь CSS reset, который обнуляет многие полезные стили. В итоге текст не выглядит как текст, а как нечитаемая каша. Если ты используешь CSS reset, ты обязан задать стили для всех элементов, для которых ты их сбросил тут в начале: https://theknacker.github.io/Webpaint/style.css (и если подумать, то окажется что выгоднее не использовать CSS reset вообще, чем сбрасывать стили и затем заново ставить им обратно те же значения).

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

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

Далее, у тебя там есть стили слишком широкого действия:

> a:not(.logo), label, img {


> transition: all 200ms linear


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

Или тут:

> li a{



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

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

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

Далее, ты там используешь width: fit-content, про который я первый раз слышу, и видимо не только я, так как он мало где поддерживается: https://developer.mozilla.org/ru/docs/Web/CSS/fit-content#Browser_compatibility и по моему ты даже используешь эту функцию неправильно.

Насчет тега cite я тоже не уверен - я тут почитал https://developer.mozilla.org/ru/docs/Web/HTML/Element/cite - можно ли его использовать для указания копирайта?

> input#graphic:checked ~ a:not([href="#graphic"]),


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

> <div class="service_image_android"></div>


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

Еще по моему на макете был курсив в шапке.

И вот тут вот проблема: безымянный див:

> <footer>


> <div>



div сам по себе не несет никакого смысла, он предназначен для нестандартных элементов, и смысл этих элементов задается id или классом. А ты не используешь тут класс и потом городишь какие-то трудные для понимания селекторы. Завтра кто-то добавит третий див, и все стили собъются потому что у тебя там используется :last-of-type.

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

Если тебе интересно, ты можешь еще почитать про методологию БЭМ, которая как раз придумана, чтобы упростить дальнейшую поддержку кода, чтобы верстку было как можно легче править в будущем: https://ru.bem.info/methodology/ У нас тут очень простая верстка, и БЭМ использовать не требуется, но если ты будешь верстать более сложные страницы, а тем более сайты с большим числом страниц, понимание БЭМ тебе пригодится. Прочитай, если есть время.

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

Также у тебя нет метатега viewport ( http://frontender.com.ua/mobile-web/wtf-viewport/ ).

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

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

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

Я бы конечно еще тебе хотел дать задачу исследовать варианты подключения SVG картинок, какие при этом возникают сложности, как они поддерживаются в разных браузерах, но не знаю, готов ли ты такую задачу сделать, есть ли время. Если есть, то потом я тебе объясню, что надо сделать и зачем.
#305 #1071401
>>1070821

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

Алсо тут ошибка:

> data: 'json =' + JSON.stringify(json)



Спецсимволы должны кодироваться процентным кодированием при использовании метода application/x-www-url-encoded или как-то так. У меня есть урок https://github.com/codedokode/pasta/blob/master/network/urls.md и там это мельком упомянуто (там про query string, но принцип тот же):

> параметры (строка запроса, query string) - может содержать дополнительные параметры, которые будут переданы на сервер. Обычно параметры пишутся через знак =, и разделяются символом &, например ?a=1&b=2&c=hello%20world. Спецсимволы в именах и значениях параметров надо кодировать процентным кодированием. В примере выше в фразе hello world пробел (который нельзя использовать в ссылке) закодирован кодом %20.



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

>>1070599

У тебя переменная окружения, которая указана в коде, задана? Видна ли она в PHP? Проверь через getenv или phpinfo() например.

>>1070597

Можно сделать так:

- в начале идет +7 или 8
- за ним ровно 10 раз повторяется такое выражение: "любое число минусов, скобок, пробелов в любом порядке, за ним ровно одна цифра". Повтор задается через квантификатор конечно.

>>1070552

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

> Можно ли без своей реализации сделать на yii2 чтобы и httpBasicAuth работал и обычная браузерная аутентификация основанная на сессии? Мне надо чтобы сайт работал в двух режимах: и как обычный сайт и как API если передать определенный параметр, вот встал вопрос реализации аутентификации по токенам.



Начать нужно с изучения документации по авторизации/аутентификации в Юи и затем смотреть, как это реализовать. Она там настраивается, можно писать свои классы, так что наверно это возможно.
#305 #1071401
>>1070821

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

Алсо тут ошибка:

> data: 'json =' + JSON.stringify(json)



Спецсимволы должны кодироваться процентным кодированием при использовании метода application/x-www-url-encoded или как-то так. У меня есть урок https://github.com/codedokode/pasta/blob/master/network/urls.md и там это мельком упомянуто (там про query string, но принцип тот же):

> параметры (строка запроса, query string) - может содержать дополнительные параметры, которые будут переданы на сервер. Обычно параметры пишутся через знак =, и разделяются символом &, например ?a=1&b=2&c=hello%20world. Спецсимволы в именах и значениях параметров надо кодировать процентным кодированием. В примере выше в фразе hello world пробел (который нельзя использовать в ссылке) закодирован кодом %20.



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

>>1070599

У тебя переменная окружения, которая указана в коде, задана? Видна ли она в PHP? Проверь через getenv или phpinfo() например.

>>1070597

Можно сделать так:

- в начале идет +7 или 8
- за ним ровно 10 раз повторяется такое выражение: "любое число минусов, скобок, пробелов в любом порядке, за ним ровно одна цифра". Повтор задается через квантификатор конечно.

>>1070552

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

> Можно ли без своей реализации сделать на yii2 чтобы и httpBasicAuth работал и обычная браузерная аутентификация основанная на сессии? Мне надо чтобы сайт работал в двух режимах: и как обычный сайт и как API если передать определенный параметр, вот встал вопрос реализации аутентификации по токенам.



Начать нужно с изучения документации по авторизации/аутентификации в Юи и затем смотреть, как это реализовать. Она там настраивается, можно писать свои классы, так что наверно это возможно.
#306 #1071402
>>1070548

Боюсь что это баги соответствюущих сервисов, где криво настроен PHP. Попробуй еще другие какие-нибудь. Ну вот например https://repl.it/languages/php - тут все работает или 3v4l.org.

Или установи себе PHP на компьютер, и запускай встроенный в PHP сервер, и смотри результат в браузере, инструкции где-то в ОП посте.
#307 #1071403
>>1071029

И еще, если я что-то непонятное написал или плохо сформулировал замечания, ты уточняй.
#308 #1071409
>>1071399
Благодарю ОП, именно это я и имел ввиду когда говорил про стиль который действует на всех страницах. Я только под конец понял что ошибся. Методологию я вот собирался на днях изучать, ровно как и поработать с селекторами, чтобы лучше их понять.

>Насчет тега cite я тоже не уверен


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

>нет метатега viewport


Я его хотел добавить, но подумал, что пользователь может увеличить страницу в случае чего. Судя по статье так делать нежелательно.
Еще проблема есть одна, во всех браузерах все отображается верно, но в Mozilla и ее мобильной версии один <div> элемент перед названием города съезжает вниз, т.е посередине, пока не знаю как фиксить.
Да ОП помоги чем сможешь. И еще хотел спросить, где все эти ресурсы искать? Я с книг беру всякие полезные сайты и т.д Бойлер плейты всякие итд. А у тебя прям набор какой то, опыт? Во всяком случае объясни, это все по мере работы находится?
#309 #1071410
>>1071401
спасибо
#310 #1071411
Привет!
Поясните почему форма работает некорректно, а именно почему постоянно срабатывает 7 строка? Вроде корректно ввожу данные, а проверка проходит не так как положено.
https://ideone.com/3rQ5Cn
#311 #1071413
>>1071409

Теги i и b поменяли свое значение в HTML5. В любом случае, они тут не подходят, используй просто div с классом.

meta viewport сам по себе не блокирует зум. Он говорит мобильному браузеру, что страница оптимизирована под мобильные устройства и задает настройки для ее отображения (если тега нет, браузер думает, что это страница, не знающая про мобильные браузеры). Без него мобильное устройство отобразит десктопную широкую версию сайта в уменьшенном масштабе. Ты можешь открыть свой сайт в Хроме или ФФ и включить там в отладчике режим отладки адаптивной версии и увидишь. Ну или на реальном устройстве.

> но в Mozilla и ее мобильной версии один <div> элемент перед названием города съезжает вниз, т.е посередине, пока не знаю как фиксить.


Что отладчик показывает? Какие стили применены? Где она съезжает?

> Да ОП помоги чем сможешь.


Ты задавай конкретные вопросы тогда.

> И еще хотел спросить, где все эти ресурсы искать?


Информацию по HTML/CSS свойствам я ищу со словом MDN. например "mdn flexbox"

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

Также есть дайджест новостей в таком формате https://habrahabr.ru/company/zfort/blog/331168/

Также есть caniuse для поиска информации о поддержке браузерами разных технологий.

Также, когда-то я читал еще блоги верстальщиков, но не уверен, что те статьи сейчас актуальны.

Если есть очень большое желание можно почитать спецификации по HTML/CSS (осторожно, много букв, но зато все очень подробно расписано). Я в них обычно ищу какие-то спорные вопросы, про которые нигде толком не написано. Ну вот к примеру, тут автоматическое определение размеров элементов в CSS очень подробно расписано: https://www.w3.org/TR/CSS2/visudet.html#q10.0

> Я с книг беру всякие полезные сайты и т.д Бойлер плейты всякие итд.


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

> набор какой то, опыт?


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

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

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

Теги i и b поменяли свое значение в HTML5. В любом случае, они тут не подходят, используй просто div с классом.

meta viewport сам по себе не блокирует зум. Он говорит мобильному браузеру, что страница оптимизирована под мобильные устройства и задает настройки для ее отображения (если тега нет, браузер думает, что это страница, не знающая про мобильные браузеры). Без него мобильное устройство отобразит десктопную широкую версию сайта в уменьшенном масштабе. Ты можешь открыть свой сайт в Хроме или ФФ и включить там в отладчике режим отладки адаптивной версии и увидишь. Ну или на реальном устройстве.

> но в Mozilla и ее мобильной версии один <div> элемент перед названием города съезжает вниз, т.е посередине, пока не знаю как фиксить.


Что отладчик показывает? Какие стили применены? Где она съезжает?

> Да ОП помоги чем сможешь.


Ты задавай конкретные вопросы тогда.

> И еще хотел спросить, где все эти ресурсы искать?


Информацию по HTML/CSS свойствам я ищу со словом MDN. например "mdn flexbox"

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

Также есть дайджест новостей в таком формате https://habrahabr.ru/company/zfort/blog/331168/

Также есть caniuse для поиска информации о поддержке браузерами разных технологий.

Также, когда-то я читал еще блоги верстальщиков, но не уверен, что те статьи сейчас актуальны.

Если есть очень большое желание можно почитать спецификации по HTML/CSS (осторожно, много букв, но зато все очень подробно расписано). Я в них обычно ищу какие-то спорные вопросы, про которые нигде толком не написано. Ну вот к примеру, тут автоматическое определение размеров элементов в CSS очень подробно расписано: https://www.w3.org/TR/CSS2/visudet.html#q10.0

> Я с книг беру всякие полезные сайты и т.д Бойлер плейты всякие итд.


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

> набор какой то, опыт?


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

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

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

Насчет тегов i и b, решил дополнить. В HTML4 это были презентационные теги, задававшие внешний вид элемента (курсив и жирный шрифт). В HTML5 наконец-то решили покончить с презентационными тегами (внешний вид задается в CSS, а не в HTML) и поменяли им смысл. А также ввели strong и em которые задают смысловое выделение текста.
#313 #1071415
>>1071409

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

Затем:

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

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

Тогда скорее всего все будет нормально.
#314 #1071422
>>1071415
ОП, а я правильно понял про механическую адаптацию, или у меня как раз она получилась? Не могу понять верно или нет.
#315 #1071423
>>1071411
Я дегенерат ^^
if ($_POST['city'] == NULL || $_POST['street'] == NULL || $_POST['house'] == NULL || $_POST['apartment'] == NULL || $_POST['size'] == NULL || $_POST['weight'] == NULL){
print "<br><b>Форма заполнена некорректно, попробуйте еще!</b>" . showForm();
#316 #1071434
>>1071413
Кстати я как раз изучение html и css со спецификации начинал, каждый день их вкладки открыты. Значит я в правильном направлений. ОП если сможешь ответь на мой вопрос выше.

З.Ы Отладчик посмотрю.
#317 #1071443
>>1071422

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

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

>>1071434

Ну вот и хорошо, это значит что технические вещи ты понимаешь, но теперь надо разобраться с вопросом удобства пользования, удобства поддержки программистами.
#318 #1071444
>>1071422

Или хабр например сравни, обычную версию с мобильной.
#319 #1071463
>>1071413
>>1071414
>>1071415
ОП я исправил версию на мозилле, там почему то адресный div элемент внутри ссылки ни в какую не хочет расширяться в fit-content, вот оно как раз твое замечание. В общем я так решил, пока буду пытаться максимально ужать классы и более логичней и удобней для всех. Методологию, почитать ресурсы, так же попробую поверстать еще странички и.т.д
Думаю не буду тебе надоедать своим тупоумием, если уж совсем сложно будет спрошу. И еще - Спасибо за то что ты делаешь.
#320 #1071465
Задам еще тут вопрос...
Есть JS скрипт с "отзывами": https://ideone.com/BWZEXS
Нужно его добавить на страничку с отзывами, к примеру http://www.site.ru/otzyvy/
А он добавляется на все страницы сразу, которые есть на этом сайте.
Добавляю в xml файлик который отвечает на верстку html, не пойму как сделать что бы этот скрипт был на определенной странице.
если это важно, то движок umi.cms
#321 #1071513
>>1071463
Апдейт по Moz:
В элементе adr::before когда я ставлю ему контент иконки, он перестает быть inline-block элементом, фиксится либо изменением ширины, в результате чего в IE11 SVG элемент сразу масштабируется до нее и становится больших размеров, но в мозилле и хроме все в порядке. Я пробовал переделать svg с ФШ, не помогло. В общем чтобы элемент не перескакивал на след. строчку, приходится ему ставить display:inline-block;
#322 #1071553
Регулешки, поясните пожалуйста вот какой момент:
заменяю начальные буквы в строке на заглавные:
$regexp = "/^([а-яёa-z])/u";
вопрос: я могу прямо в прегреплейсе сделать как-нибудь конструкцию вида:
$value = preg_replace($regexp, "strtoopper($1)", $textt);
или мне нужно выковыривать букву регуляркой, потом уже не регуряркой поднимать регистр, и обратно вставлять? Можно ли в одной строчке сделать автозамену?
#323 #1071560
>>1071553
Так ты в интерперетаторе запусти свой скрипт и узнаешь, можно или нет.
#324 #1071571
>>1071560
я запускаю, не работает. Мне нужно понять, не работает потому что ЭТО В ПРИНЦИПЕ НЕЛЬЗЯ И ТАК НЕ ДЕЛАЕТСЯ, или не работает потому что МЕТОД ВЕРНЫЙ, НО СЕЙЧАС ЕСТЬ ОШИБКА В СИНТАКСИСЕ, И ЕСЛИ ЕЕ ИСПРАВИТЬ, ТО ВСЕ ЗАРАБОТАЕТ.
Можно же мне сейчас сказать, что это невозможно, чтобы я не тратил время зря и использовал другой метод
#325 #1071575
Есть одна задача: заполнить магазин А товаром из магазина Б потом и В,Г....
Как это реализовать без регистрации и смс человеку с опытом в полтора часа?
В гугле советуют писать свой парсер из говна и палок.
Занимался ли кто такими хитрыми делами товары, мейлы, телефоны, небо, Аллах? Мб есть чего готового для этих целей?
#326 #1071582
>>1071571
То есть посидеть, поковыряться и разобраться у тебя времени нет, а сидеть тут и ждать, пока ответят - есть? Ну ок.

Я не спец в ПХП, но если strtoupper() возвращает строку, а $0 ждет строку, то никаких препятствий я не вижу.

>я запускаю, не работает


У тебя в примере минимум две опечатки. Может, поэтому и не работает? Опять же, интерпретатор тебе ошибки писать должен, не бывает так, что "просто не работает".
#327 #1071584
>>1071553

Тебе нужен preg_replace_callback.

То, что ты хочешь сделать, раньше делалось специальным флагом, но позже это было признано опасным способом, вызывающим уязвимости.
#328 #1071586
>>1071553

Алсо strtoupper не работает корректно с utf-8, имей в виду.
#329 #1071587
>>1071553
Зачем strtoupper($1) в кавычках? У тебя сейчас буквально первая буква строки заменяется на подстроку "strtoopper($1)", я сомневаюсь, что ты именно этого добивался.
#330 #1071591
>>1071582
Как же я умиляюсь с таких мудаков как ты.
Во-первых, я спрашивал совета у знающего анона, а не у мимокрокодила, который никак в сабже не разбирается, но лезет учить.
Во-вторых, не смешивай понятия "просиди и подумай" с "трать все время на заведомо неправильное решение просто потому что снобам от программирования, сидящим в треде помощи, лень написать да или нет"
А вообще ты напоминаешь мне дяденьку-председателя колхоза из старого баяна, где солдаты-срочники строили гараж для сельхоз-техники, затаскивали огромную плиту на опорные балки вручную, как рабы, рискуя быть придавленными, а он каждый день приходил и сидел - смотрел на них. И под конец, когда балку затащили, председатель подошел и сказал "ребят, очень низко сделали, трактор не проедет". И на все вопросы "а что же ты, дядя, до этого момента молчал?", он отвечал "так я в отпуске был"
Так что будь добр, просто не лезь в то, в чем не разбираешься
#331 #1071592
>>1071587

>Зачем strtoupper($1) в кавычках?


ты у мамы не очень умный, да? Потому что без кавычек ideone выдает ПУСТУЮ ошибку без ничего, по которой ничего не понять. Или ты думаешь ты единственный, который подумал убрать ковычки, дыа?
#332 #1071597
>>1071592

>взял функцию в кавычки


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


>мааам ну он дурак ну скажи ему мааам



>>1071591

>ну ка все метнулись резко и читнули за меня мануалы а то я слишком занятой чтобы васякой хуйней заниматься


Найс подрыв.
#333 #1071599
>>1071584
Вот тебе спасибо, помогло
#334 #1071600
>>1071597

>>взял функцию в кавычки


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


>>мааам ну он дурак ну скажи ему мааам



Ты идиот?
#335 #1071601
>>1071600
Нет нужды быть агрессивным.
#336 #1071602
>>1071601
дажи ни знаю, кто хуже, агрессивный мимокрокодил или дурачок, который считает себя невозмутимым Буддой, надрачивая тем самым свое чсв и самоутверждаясь засчет новичков
#337 #1071604
>>1071602
Имеешь право думать так, как умеешь. Пока я говорю, что твоя агрессия бесполезна.
#338 #1071608

>На вход скрипта дан введенный пользователем номер телефона в виде 8-911-404-44-11 или +7(812)6786767 (в начале 8 или +7, потом идут 10 цифр и, возможно, какие-то символы). То есть, как и в прошлой задаче, человек вводит номер как хочет. Надо проверить номер на правильность и привести любой номер к единому формату 89114044411 (то есть, заменить +7 на 8 и выкинуть весь мусор вроде пробелов, скобок и минусов, кроме цифр)



А эта задача вообще решаема в один проход? То есть в два прохода я ее решить могу - заменить сначала +7 на 8, а потом вырезать все не-цифры. Но как это сделать в один проход - ума не приложу.
#339 #1071612
>>1071608
вот вчера аношка в одну регулярку решил
>>1071378
#341 #1071615
Можно ли вкатиться в пхп-разработку с крайне скудными уменями верстки, в т.ч. и яваскрипта? Мне вот нравится кодить движок сайта, а верстка ну совсем не вдохновляет.
#342 #1071617
>>1071612
Не, это другое. Распарсить номер и заменить символы - разные вещи.
#343 #1071620
>>1071614
Ну так это тоже в два прохода - ты же дважды preg_replace вызываешь. Так я тоже могу. Ты за один вызов реши.
#344 #1071621
Чому на https://ideone.com/
строка mb_internal_encoding('utf-8'); выдает
ошибку? И прочие mb_
#345 #1071622
>>1071465
Отвечайте на мой ответ!
#346 #1071625
>>1071622
Прости, няша, я не знаю. Подожди опа, он вечером вроде приходит. После двеннадцати.
89 Кб, 836x376
#348 #1071654
Начал изучать регулярные. Пытаюсь понять зачем тут [0-9]. Может кто-нибудь объяснить, пожалуйста? Спасибо.
#349 #1071658
>>1071654
Это значит "тут должна быть любая цифра от 0 до 9 ровно один раз". В двадцатичетырехчасовом формате времени на этом месте может быть любая цифра от 0 до 9.
19 Кб, 785x319
#350 #1071660
Застрял в третей задаче на массивы, что дальше то писать?
Как вывести именно значение массива?
#351 #1071662
>>1071658
Хорошо. А зачем тогда число 12 стоит до этого ?

Получается ведь что-то типо 121:34
#352 #1071663
>>1071660
массив[$random]
#353 #1071668
>>1071663
>>1071660
в array_rand надо массив сам вставить
$random = array_rand($answers)
#354 #1071670
>>1071662

>зачем тогда число 12 стоит до этого ?


По аналогии с 0-9 - это будет любая цифра в диапазоне от 1 до 2.
мимо опыт пхп 14 минут
#355 #1071671
>>1071670
Там нету никаких знаков. Не 1-2, а просто 12.
Ладно. Позже попробую понять снова. Всем спасибо за отклик.
#356 #1071672
>>1071670
>>1071662
Не совсем. Это будет 1 или 2. "Любая цифра в диапазоне от 1 до двух" - это [1-2]. Я понимаю, что это ожно и то же по сути, но с точки зрения записи это разные вещи.
#357 #1071677
>>1071663
>>1071668
Ок, а как вывести значение по индексу?
#358 #1071678
>>1071677
$random = array_rand($answers);
$answer = $answers[$random];
echo $answer;
#359 #1071679
Благодарствую
#360 #1071686
>>1071654

Квадратные скобки значат "один любой из указанных символов". Ну например [123456] значит одна цифра от 1 до 6.

При этом можно использовать минус для указания диапазона и [1-6] это то же самое, что [123456].

Если первый символ это ^ то смысл меняется на противоположный и скобки значат "один любой символ кроме указанных", например [^1-9ab] значит любой символ, кроме цифр 1-9 и букв a, b.

Мануал http://php.net/manual/ru/regexp.reference.character-classes.php
#361 #1071695
>>1071633
спс
#362 #1071706
>>1071686
Понял, спасибо ольшое
180 Кб, 500x494
#363 #1071796
>>1067944 (OP)
Немного знаю пхп, но никогда не работал с API социальных сетей, и всякие "токены для идентификации", "асинхронный обмен данными" внушают мне неподдельный ужас. Официальные гайды не объясняют, "куда вообще всё это вбивать и что нахуй делать шоб стало заебись", примеров мало, практики, скорее справочники какие-то, а не гайды. Ютуб наоборот заполнен всяким бредом вроде "поклацай клавишами в МэниБот или Снапчат, станет охуительно". Интересующие платформы: ФБ, ВК, Телеграм, Твиттер. Хочется поделать ботов-автоответчиков, реагрирующих на присылаемый текст и нетекст (схоронял присылаемые пикчи, например, или присылал обратно черно-белую версию, или конвертировал форматы), мб автопостеры какие-то или парсеры. Как, имея хостинг с пыхом, все это делать, есть какие-то Quick Startы?
#364 #1071803
>>1071796
нужно реальное знание РНР -- и тогда все официальные гайды соц.сетей внезапно просто и понятно предоставляют всё что нужно.

А для дураков -- бесконечно-бесполезные тренинги, курсы и видосики.
#365 #1071805
>>1071803

>дураков


вкатывальщиков, если точнее
20 Кб, 300x300
#366 #1071835
Как в ларе передать параметр во все вьюхи?
Предлагали в конструкторе основного контроллера (Controller.php) - не подходит ибо некоторые унаследованные контроллеры перегружают конструктор (и лезть туда не нужно)
#367 #1071836
>>1071796

Во-первых, API соцсетей основаны на HTTP, потому стоит в общем прочитать про этот протокол, чтобы знать его особенности и может тогда документация будет понятнее. Вот урок (если что-то там непонятно или плохо объяснено, напиши): https://github.com/codedokode/pasta/blob/master/network/http.md

Заодно прочитай на всякий случай урок про URL : https://github.com/codedokode/pasta/blob/master/network/urls.md

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

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

- curl - для командной строки
- программы с графическим интерфейсом ищутся по словам "http gui client"

Отправляя запросы вручную, ты можешь проверить как работает API. Но разумеется, дальше тебе нужно будет отправлять запросы автоматически из программы. Для этого тебе нужна будет библиотека-HTTp-клиент.

В PHP есть расширение curl, но оно довольно неудобное для использования. Гораздо удобнее использовать ООП-библиотеки вроде Guzzle. есть и другие библиотеки, они ищутся по словам "php http client library", еще можно поискать

- на phptrends: https://phptrends.com/search?q=http+client
- в packagist: https://packagist.org/?q=http client&p=0

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

АПИ с авторизацией могут быть сложными для новичка, потому потренироваться можно на более простом АПИ, не требующем авторизации, например на АПИ геокодера из яндекс-карт: https://tech.yandex.ru/maps/doc/geocoder/desc/concepts/About-docpage/

Также, есть специальный сайт, который отдает заранее известные HTTP ответы который можно использовать для тренировки: http://httpbin.org/
#367 #1071836
>>1071796

Во-первых, API соцсетей основаны на HTTP, потому стоит в общем прочитать про этот протокол, чтобы знать его особенности и может тогда документация будет понятнее. Вот урок (если что-то там непонятно или плохо объяснено, напиши): https://github.com/codedokode/pasta/blob/master/network/http.md

Заодно прочитай на всякий случай урок про URL : https://github.com/codedokode/pasta/blob/master/network/urls.md

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

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

- curl - для командной строки
- программы с графическим интерфейсом ищутся по словам "http gui client"

Отправляя запросы вручную, ты можешь проверить как работает API. Но разумеется, дальше тебе нужно будет отправлять запросы автоматически из программы. Для этого тебе нужна будет библиотека-HTTp-клиент.

В PHP есть расширение curl, но оно довольно неудобное для использования. Гораздо удобнее использовать ООП-библиотеки вроде Guzzle. есть и другие библиотеки, они ищутся по словам "php http client library", еще можно поискать

- на phptrends: https://phptrends.com/search?q=http+client
- в packagist: https://packagist.org/?q=http client&p=0

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

АПИ с авторизацией могут быть сложными для новичка, потому потренироваться можно на более простом АПИ, не требующем авторизации, например на АПИ геокодера из яндекс-карт: https://tech.yandex.ru/maps/doc/geocoder/desc/concepts/About-docpage/

Также, есть специальный сайт, который отдает заранее известные HTTP ответы который можно использовать для тренировки: http://httpbin.org/
#368 #1071838
ОП, скажи мне, вот какая у тебя мотивация сидеть здесь годами и строчить длинные пасты за бесплатно?
ты одинок?
#369 #1071840
>>1071838
Всё просто
тортик - ложь
Оп - няша[/spoil
er]
#370 #1071842
>>1071836
Погоди-погоди, это все примерно понятно, спасибо, анон, но мне нужен именно кьюик старт по конкретному апи соцсетки, пусть даже и не сложному для начала. В теории я понимаю и про заголовки http, и даже курлом когда-то пользовался, из пыха header'ы и setcookie вызывал, но читаю про АПИ и охуеваю. И даже не только про апи, а хотя бы про

>такие программы-клиенты


https://habrahabr.ru/post/271687/
Например в этой статье мне по-отдельности все более-менее понятно, если посимвольно буквально разбираться, но в сумме "блядь блядь как сложно нахуй вообще так сделано блядь что зачем это господи что за хуйня вообще ааааа". А в случае, когда я заделал, например, в

>в МэниБот или Снапчат


основу и теперь хочу добавить кастомные команды, выводящие ответы из моих скриптов (в зависимости от посланных командой этим скриптам данных), тут я вообще не понимаю даже, в какую сторону копать.
#371 #1071844
>>1071842

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

> нужен именно кьюик старт


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

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



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

В статье нет конкретики, но если перейти по ссылкам, почитать документацию этого стандарта (?), то думаю станет понятно.

Там еще упоминается PSR-7, это интерфейсы дял объектов, представляющих HTTP запрос или ответ. Если ты знаком с ООП и если ты почитаешь документацию, то тебе все станет понятно, я думаю.

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

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

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

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



Для этого тебе сначала полностью разобраться как работает существующий код.
#371 #1071844
>>1071842

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

> нужен именно кьюик старт


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

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



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

В статье нет конкретики, но если перейти по ссылкам, почитать документацию этого стандарта (?), то думаю станет понятно.

Там еще упоминается PSR-7, это интерфейсы дял объектов, представляющих HTTP запрос или ответ. Если ты знаком с ООП и если ты почитаешь документацию, то тебе все станет понятно, я думаю.

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

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

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

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



Для этого тебе сначала полностью разобраться как работает существующий код.
#372 #1071847
>>1071844

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


Да, это-то понятно. Я про код. Сейчас объясню на живом примере. Я хочу гайды типа таких
https://pikabu.ru/story/api_vkontakte_dlya_python_3961240
https://tproger.ru/translations/telegram-bot-create-and-deploy/
или хотя бы типа таких
https://habrahabr.ru/post/281559/
https://habrahabr.ru/post/316666/
https://habrahabr.ru/post/278847/
https://habrahabr.ru/post/127237/
Но для пхп находится какое-то говно + все юзают разные библиотеки и я ебал так жить.

>В статье нет конкретики


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


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

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


Если ты пилишь бот каким-то конструктором, там и нет кода, вернее, ты его не видишь, он от тебя скрыт, перед тобой только кнопочки админки сервиса (в случае снапчата) для создания ботов или (в случае телеграма) само окошко той штуки, для которой ты делаешь бота (клиент телеграма с диалогом бот-криейтора или созданным ботом, в данном случае). Как к имеющейся хуйне добавить команду, которая не только ответ заготовленный возвращает, а хотя бы результат скрипта <? return random(); ?> не въезжаю :с
#373 #1071873
>>1071575
Если магазин маленький (до пары тысяч товаров) и пирсинг одноразовый -можно парсить скриптом написанным на коленке за час, если магазин большой и нужны актуальные данные всегда - готовься придумывать архитектуру, проектировать хранение, использовать абстракции над курлом типа angrycurl/rollingcurl с коллбеками. Алсо будь готов что тебя будут постоянно банить, сперва автобаны будешь ловить, потом по IP руками.
В любом случае опыт нужен не только с пхп, но и курлом, xpath или с другой либой которая работает с дом-деревом, знание MySQL
#374 #1071901
>>1071465
Бiмб
Ещё немного задачек #375 #1071905
ОП, проверь задания, пожалуйста.

Сдача https://3v4l.org/LHVOQ
Лиличка https://3v4l.org/jc4PN
Считалка https://3v4l.org/dDAaI
Алфавит https://3v4l.org/d5PAs
Навигатор https://3v4l.org/75dUN
#376 #1072015
>>1067949
https://github.com/vadimyen/students – напомню о своих студентах
#377 #1072070
Сделал задачу на генератор стиха вот таким способом:
https://ideone.com/OTtUP3
Такой вариант имеет право на жизнь? Алсо, если объявить переменную шаблона стихотворения до массива с рандомными словами, то не работает. Подскажите, почему.
#378 #1072147
Анончики, разбираюсь с ларой.
Назрел вопрос. Вот в юии есть виджеты, которые могут генерировать готовую html разметку из входящих данных и т.д.
Как это в ларе лучше сделать?
Хочу я, например, сделать метод, который получает массив, которым он заполнит value и name, после чего генерирует выпадающий селект из всего этого.
Вынести в отдельный класс для работы с массивами и выдающий html?
Если да, то как правильно?
#379 #1072179
>>1072147
Правильно - погуглить готовые виджеты и использовать их. Судя по тому, что ты просишь, достаточно будет этого пакета для генерации HTML:
https://laravelcollective.com/docs/5.2/html
https://laravelcollective.com/docs/5.2/html#drop-down-lists
Кстати раньше он был частью фреймворка. Есть ещё такой пакет: https://github.com/adamwathan/bootforms - по сути тоже самое, но с использованием Twitter Bootstrap.
#380 #1072182
>>1072179
От души, братишка.
Там и гляну как правильно делается.
#381 #1072357
>>1071835
Ну раз ты гугл не хочешь использовать, то давай немного подумаем и пройдёмся по исходникам. Тебе нужны глобальные переменные в шаблонах, это значит (как мне кажется), что при каждом создании рендерера вьюшек эти переменные должны туда передаваться, может в конструктор, может в метод какой, неважно. Открываем исходники компонента View:
https://github.com/laravel/framework/tree/5.5/src/Illuminate/View
видим так какой-то класс View:
https://github.com/laravel/framework/blob/5.5/src/Illuminate/View/View.php
Помню, что в контроллере мы используем метод render, находим его в этом классе, углубляемся по цепочке protected методов к методу gatherData и видим строчку:
$data = array_merge($this->factory->getShared(), $this->data);
Выглядит как то, что нам нужно - $this->data это массив, который передаётся через $this->render('template.name', ['key' => 'value']) и есть ещё какие-то shared переменные у фабрики. Смотрим её исходники и находим там массив с комментарием "Data that should be available to all templates.": https://github.com/laravel/framework/blob/5.5/src/Illuminate/View/Factory.php#L52
И тут же метод для добавления глобальных переменных:
https://github.com/laravel/framework/blob/5.5/src/Illuminate/View/Factory.php#L309

Итого тебе нужно получить доступ к фабрике View и добавить туда через share свою переменную. Самый простой способ - в AppServiceProvider в методе boot вызвать View::share('key', 'value')
Здесь View - это фасад. Если непонятно почему это работает, то почитай о service provider'ах в ларавеле и изучи как фреймворк резолвит такие статические вызовы (на самом деле он достаёт фабрику из DI-контейнера).
#382 #1072366
>>1072357
В провайдерах нельзя использовать фасад Auth, а мне он нужен. Но проблема решилась банальным мидлвером примененным ко всем роутам
жаль что программисты не умеют отвечать на вопрос парой строк
#383 #1072407
Анон, который умеет в твиг, подскажи как в самом шаблоне "template.twig" выполнить подключение файла по аналогии с require_once('path/to/file.php'); С гуглом пытаюсь наладить отношения, но пока он мне сильно не помог
#385 #1072429
>>1072425
Это видел, но он подключает лишь шаблоны, а php файлы судя по всему нет
#386 #1072433
>>1072429
Он и не должен PHP файлы подключать, ты хочешь одновременно использовать 2 шаблонизатора (Twig и PHP)? Объясни зачем, может ты слишком много логики в шаблон пихаешь. Ты знаком с макросами твига и кастомными функциями?
#387 #1072443
>>1072433
я с твигом можно сказать только начинаю знакомство, поэтому вряд ли, есть задание по работе под твиг переписать существующий tpl шаблон, в нём было подключение класса, которое я уже вынес в контроллер и вроде как получил желаемый результат, плюс в этом tpl шаблоне было создание экземпляра класса, который через twig тоже не получилось присвоить, и сделал это через контроллер, ну а с выводом в twig уже вроде как проблем не составило, так что хоть как задумал изначально - не сделал, т.к. тупо нет такой возможности, но обходным путём воспользовался, посмотрим что скажут
#388 #1072485
2017ый на дворе, а я вкатился к вам.

Фига у вас всё расписано сначала то, потом это, даже сайтик свой, ни в одном треде на дваче нет такого продвинутого комьюнити
#389 #1072489
Курсы специалиста по похапе стоит рассматривать или уг?
#390 #1072493
>>1072485
>>1072489
У нас тут есть свой уютный учебник к официальный мануал.
#391 #1072502
Пацаны почему вот так работает:
$stmt = $this->dbn->prepare("SELECT FROM student ORDER BY :sort DESC LIMIT 10 OFFSET :offset");
А вот так нет:
$stmt = $this->dbn->prepare("SELECT
FROM student ORDER BY :sort :order LIMIT 10 OFFSET :offset");
$stmt->bindValue(':order','DESC');

постгресиквел
#392 #1072504
Объясните дауну как в хпх склеивать в строке переменную и текст, и как это всё нормально переносить на следующую строку с помощью \n.
#393 #1072512
>>1072504
$строка = 'строка'.$переменная.'еще строка'.'\n';
27 Кб, 778x484
#394 #1072532
2 дабла это типо большая редкость или наоборот рядовой случай, но приятно?
23 Кб, 774x447
#395 #1072537
Почему цикл ни разу не выполняется ??
https://ideone.com/LhFRkC
#396 #1072539
>>1072537
ой, я чет не подумал, что надо новую пасту было создать
#397 #1072577
>>1072537
Потому что $credit больше нуля 3 строка
а у тебя условие: $credit <= 0 9 строка
#398 #1072610
>>1072532
в суть не всматривался особо, но на 16й строке скрина в первом условии должно идти сравнение ==, вместо присвоения =
#399 #1072614
>>1072577
>>1072610
увидел, спасибо,
#400 #1072620
А правда, что в php меньше всего вкатывальщиков?
#401 #1072621
>>1072620
Наоборот. В js и php много вкатывальщиков.
447 Кб, 720x590
#402 #1072635
Пыханы, поясните за неймспейсы. Суть в том, что есть обьявленый класс в одном неймспейсе, но доступ к его методам нужен из другого неймспейса. Есть такая возможность на 5.3 пыхе?
#404 #1072637
>>1072636
Сори, я упорол косяка впринципе с видимостью классов, дело не в неймспейсе.
https://ideone.com/xqMIVT
Межушный ганглий уже не соображает, пойду спать.
#405 #1072638
>>1072366
А лень твоя тут причем?
3 Кб, 339x138
Хелп ретарду vandarkholme #406 #1072648
суп,антоны. абсолютно не разбираюсь в теме и буду рад пояснениям или если ты такой щедрый,то решение пикрила

Найти значение переменной z, заданной суммой функций. Для нахождения значения функции f(u,t) написать пользовательскую функцию. Числа a и b – случайные.
#407 #1072661
>>1072532

Давай посчитаем. На 2 костях может выпасть 6 x 6 = 36 разных комбинаций. Из них 6 комбинаций - это даблы (1 и 1, 2 и 2 итд). Следовательно, вероятонсть выпадения дабла на 2 костях = 6 / 36 = 1 / 6. Если бросать 2 кубика, дабл выпадает в среднем раз в 6 случаев (у кого есть кубики, можете попробовать проверить).

А что насчет выпадения даблов у 2 игроков? Очень просто, чтобы найти вероятность того, что произойдет 2 независимых события, надо перемножить их вероятности. Вероятность выпадения даблов у первого игрока = 1/6, у второго = 1/6, вероятность выпадения даблов у 2 игроков одновременно = 1/6 x 1|6 = 1/36 или чуть менее 3%.

Часто это или редко, думай сам.

математическая статистика всегда мне казалась сложной и непонятной
#408 #1072685
>>1071873

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


Это и есть моя задача. Сделать один раз - залить в мой магаз и продавать. Аритектуру и абстракции буду допиливать как разберусь.

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


Знаю MySQL более-менее и с пхп разбираюсь. Можешь подкинуть чего по курлу?

>Алсо будь готов что тебя будут постоянно банить, сперва автобаны будешь ловить, потом по IP руками.


С этим проблем быть не должно.
В идеале я хотел найти готовый говноскрипт - пропарсить им 1 раз, залить товары и продавать, пока я допиливаю все к толковому виду.
#409 #1072690
>>1072648

>sin f(,a) - что это?


мимонесилачвматематике
#410 #1072692
>>1072648

>Для нахождения значения функции f(u,t) написать пользовательскую функцию.


Вот тебе функция:
функция малафья (говно, моча)
{
if говно>2 return 1 строчка
elseif говно <=2 return 2 строчка
esle return гроб, гроб, кладбище, пидор
}

Дальше сам
#411 #1072762
Часто вижу в резюме всяких васянов такую фразу: "делаю сайты под ключ". Под какой еще ключ? Что они имеют ввиду?
#412 #1072791
>>1072502
Короче в препаре нельзя пихать все подряд. Сначала нужно составить строку запроса в которой явно заданы названия полей и уже потом ее препарить.
485 Кб, 730x720
#413 #1072797
Анонасы спасайте.
Дело обстоит так, вкатился в пхп и все сопутствующее уже как 4 года.
За плечами создания анонимного чатика, форума, работа с неким неадекватным куном над браузеркой в качестве фронд-ендщика(рисовал анимацию к файтингу), все в порядке унубления( от более качественной к менее качественной реализации).
Пока я все это пилил, то не юзал ни фреймворков, ни ооп, ни мвц, ничегошечки их этого.
И вот ананасы, наступил мой 5 курс универа, мне уже надоело глять во всякую хню, с друзьями и т.д. Да и тян уже есть, и я подумал, - "а хуль бы мне не вкатиться прохрамистом?". В среде программистов со своего универа имею кое-какое уважения в качестве задрота(сам учусь на факультете не имеющим ничего общего с программированием), да и думал до этого что нет нерешаемых для меня задач.
Так вот, решил я вкатиться и начал смотреть вакансии, и тут мой взор упал на обилие всяких непонятных мне технологий (jqeury, фреймворки, git... ). Ну накатал я резюме которое затрагивает хоть немного из этого, хотя сам прочитал сугубо теорию о многом. Невероятно, но меня позвали на собеседование.
Собеседование прошло довольно радужно, два прогера меня интервьюировали около часа, правда один свалил на половине, болтали о всякой поеботе типа отличия js от php, всяком практическом и т.д.
В итоге дали некое проверочное задание, связанное с разработкой блога.
Вкратце используя php7, mysql DB не используя сторонних библиотек (я решил на этом задании надрочить знание jQuery а его использовать нельзя было, олололо, надо было внимательней читать, хотя рааньше его совсем не юзал)
Итог что написали, далее приведу жирным цветом что ответил HR и прокомментирую в скобках:
Здравствуйте, пока, к сожалению не можем вам ничего предложить, так как тестовое задание выполнено слабо(ну ок, слабо, но ведь все же работает)

Выполнено с использованием сторонних библиотек (jQuery)(как ни странно но эта технология мне понравилась, ибо действительно сокращает js код), отсутствует разделение логики и представления(это как их разделять, что такое мвц вообще? в задании не было сказано его использовать), ООП не использовано( зачем его юзать если есть процедурное программирование, и в задании не было сказано использовать ООП), множественное дублирование кода(один раз дублировал аякс запрос из-за пока что плохого понимания jquery, потому что не смог обратиться к ему же, а время поджимало разбираться), непродуманная организация базы данных(а вот тут вообще обидно, ибо использовал БД которая была приведена в задании).


Так вот ананасы, как смыть с себя этот позор(нет), ну допустим задрочу я эти все технологии, буду делать все используя мвц и паттерны, как искать вакансии в своем городе-то, если уже облажался с одной конторкой а другие не ищут пхп манагеров или я из задинамил?(
Соре за сумбурность и ашипке(
485 Кб, 730x720
#413 #1072797
Анонасы спасайте.
Дело обстоит так, вкатился в пхп и все сопутствующее уже как 4 года.
За плечами создания анонимного чатика, форума, работа с неким неадекватным куном над браузеркой в качестве фронд-ендщика(рисовал анимацию к файтингу), все в порядке унубления( от более качественной к менее качественной реализации).
Пока я все это пилил, то не юзал ни фреймворков, ни ооп, ни мвц, ничегошечки их этого.
И вот ананасы, наступил мой 5 курс универа, мне уже надоело глять во всякую хню, с друзьями и т.д. Да и тян уже есть, и я подумал, - "а хуль бы мне не вкатиться прохрамистом?". В среде программистов со своего универа имею кое-какое уважения в качестве задрота(сам учусь на факультете не имеющим ничего общего с программированием), да и думал до этого что нет нерешаемых для меня задач.
Так вот, решил я вкатиться и начал смотреть вакансии, и тут мой взор упал на обилие всяких непонятных мне технологий (jqeury, фреймворки, git... ). Ну накатал я резюме которое затрагивает хоть немного из этого, хотя сам прочитал сугубо теорию о многом. Невероятно, но меня позвали на собеседование.
Собеседование прошло довольно радужно, два прогера меня интервьюировали около часа, правда один свалил на половине, болтали о всякой поеботе типа отличия js от php, всяком практическом и т.д.
В итоге дали некое проверочное задание, связанное с разработкой блога.
Вкратце используя php7, mysql DB не используя сторонних библиотек (я решил на этом задании надрочить знание jQuery а его использовать нельзя было, олололо, надо было внимательней читать, хотя рааньше его совсем не юзал)
Итог что написали, далее приведу жирным цветом что ответил HR и прокомментирую в скобках:
Здравствуйте, пока, к сожалению не можем вам ничего предложить, так как тестовое задание выполнено слабо(ну ок, слабо, но ведь все же работает)

Выполнено с использованием сторонних библиотек (jQuery)(как ни странно но эта технология мне понравилась, ибо действительно сокращает js код), отсутствует разделение логики и представления(это как их разделять, что такое мвц вообще? в задании не было сказано его использовать), ООП не использовано( зачем его юзать если есть процедурное программирование, и в задании не было сказано использовать ООП), множественное дублирование кода(один раз дублировал аякс запрос из-за пока что плохого понимания jquery, потому что не смог обратиться к ему же, а время поджимало разбираться), непродуманная организация базы данных(а вот тут вообще обидно, ибо использовал БД которая была приведена в задании).


Так вот ананасы, как смыть с себя этот позор(нет), ну допустим задрочу я эти все технологии, буду делать все используя мвц и паттерны, как искать вакансии в своем городе-то, если уже облажался с одной конторкой а другие не ищут пхп манагеров или я из задинамил?(
Соре за сумбурность и ашипке(
#414 #1072803
>>1072502

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

Если нужно вставлять имя поля, то его надо проверить по списку разрешенных значений и после этого вставить напрямую в запрос.
#415 #1072861
Сап парни, нужен человек, который сделает сайт для игрового сервера (в перспективе для нескольких игр сразу).
Писать в телегу - @aleksShinobi1
#416 #1072952
>>1067944 (OP)
php не нужен
#417 #1072955
Господа, что такое => ? Нигде не могу найти определения. Примерно понимаю, как оно работает, но хочу знать определенно.
#418 #1072958
>>1072955

>=>


http://archive-ipq-co.narod.ru/l1/arrays.html

Создает массив с вручную заданными ключами.
#419 #1072962
Как в Yii 1.0 сделать поиск по БД?

Есть 3 таблицы, через yiic сделал их ActiveRecord, CRUD скрипты сгенерировал, вьюхи для круда есть.

Теперь надо сделать поиск по БД через sql запросы, но я нихуя не вдупляю MVC, теория с практикой не сходится. Знаю, что такое м-в-к, а как их правильно самому сделать, и наладить взаимодействие- хз.
#420 #1072989
>>1072962
Зачем ты первую версию изучаешь?
#421 #1073070
>>1067944 (OP)
Прошу проверить, правильно ли я понял регулярки. Так как на специальном сайте из-за моей косожопости ничего не находило, я решил сделать в ideone.
Номер машины: https://ideone.com/7uAo3W
#422 #1073113
>>1073070
А вот с телефонными номерами пока не понимаю. Как сделать, чтобы игнорировало и пробелы, и другие символы?
#423 #1073163
>>1072989
тестовое задание
#424 #1073183
>>1073070
Как сделать, чтобы искало плюс семь или восемь. У меня на плюс выдает ошибку, как я понял.
10 Кб, 184x187
#425 #1073184
Парни, можете по полочкам раскидать - как написать спам-бота для чатика на пхп?
1. Парсер
2. Хуярсер
3...
А ещё там гугловская каптча.
#426 #1073187
>>1073183
>>1073113
>>1073070
Сделал задание без семерки с плюсом, потому что глупенький. https://ideone.com/kAfpHf
Боже мой, какой же я все-таки глупенький, потому что я допустил, что пропущенные символы могут быть цифрой.
#427 #1073188
Делаю селект к таблицам(5, 2, 12 записей), а на выводе от 64 до 144 строк, шо це за дела?
#428 #1073189
>>1073184
Для этого взять язык Python, в нем есть многопоточность , и необходимые библиотеки. Этой штуки тебе за глаза хватит

https://github.com/lorien/grab
#429 #1073197
>>1073189
Не хочу и не могу в питон.
#430 #1073202
>>1073197
Молодец.
#431 #1073325
>>1072638
зануда, плз
#432 #1073327
#433 #1073389
>>1073188
Покажи запрос хотя бы
#434 #1073418
Поясните за ООП в пхп. Я пару месяцев смотрел на джаву, там на любой пук нужно создавать объект, но в целом мне понравилась вся эта хуйня с абстрактными классами и полиморфизмом. Я смогу делать так же в пхп?
#435 #1073453
>>1073163
Если ты его сделаешь успешно - они копипастнут его в проект, а на тебя положат хуй. Если не сделаешь - то просто положат хуй. Энджой.
#436 #1073543
Ребятки, а почему код такого вида не работает:

[CODE]

$text = "жы шы";

$patterns = array();
$patterns[0] = "/(ж|ш)ы/ui";

$replacements = array();
$replacements[0] = preg_replace("/ы/ui", "и", $0);

echo preg_replace($petterns, $replacements, $text);

[/CODE]

Это потому, что там $0 в качестве аргумента на функцию подано? Так нельзя разве?
То есть меня не запарит сделать паттерн и реплейсер для каждого кейса, но хотелось покомпактнее как-то.
#437 #1073557
>>1073543
Потому что $0 в кавычки не взял, вот я тупой-то.
Сам спросил, сам ответил.
#438 #1073566
Yii2
Допустим, есть таблица в БД. И данные из неё выводятся на страницу (тоже в виде таблицы). И есть кнопка "добавить ещё строку в таблицу".
Я правильно понимаю, что по нажатию на неё мы пинаем контроллер, тот добавляет строку, а затем заново рендерит страницу?

Я так сделал (и оно работает), но как-то медленно. Если обойтись без Yii, то по нажатии на кнопку данные улетают аяксом в пхп-скрипт, который добавляет их в таблицу, а потом возрващает success жс-скрипту. И тот добавляет новую строку на страницу через dom.

Протестировал оба вариата - dom работает раз в шесть быстрее yii и обходится без рефреша страницы. Как такое же сделать в Yii?
#439 #1073573
>>1073566
Сам ответил на свой вопрос- проблема в коде контроллера.
Один хуй и контроллер, и пхп скрипт у тебя выполняют одну и ту же операцию - insert в таблицу.
#440 #1073581
>>1073573
Нет, это понятно, что код так сделан, что получается оно это самое, етить его через коромысло.
Мне интересно, можно ли сделать так, чтобы нажатие на кнопку обрабатывал контроллер Yii, а дабавление строки далалось без рефреша страницы?
#441 #1073587
Так, ладно, я тупой, но код все равно работает странно. Вот этот пример работает, как надо, заменяет точки без пробелов на точки с пробелами:

[CODE]

$text = "aaaaa.ffffff";
$regexp = "/\\w\\.\\S/ui";
$matches = array();

preg_match_all($regexp, $text, $matches);
var_dump($matches);

echo preg_replace('/\\./', '. ', $matches[0][0]);

[/CODE]

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

[CODE]

mb_internal_encoding('UTF-8');

$text = "вышел сдесь координально жы есть aaaa.fffff";

$patterns = array();
$patterns[0] = "/(ж|ш)ы/ui";
$patterns[1] = "/сдесь/ui";
$patterns[2] = "/здел(ал|ан|аю)/ui";
$patterns[3] = "/координально/ui";
$patterns[4] = "/\\w\\.\\S/ui";

$replacements = array();
$replacements[0] = preg_replace("/ы/ui", "и", "$0");
$replacements[1] = "здесь";
$replacements[2] = preg_replace("/з/ui", "с", "$0");
$replacements[3] = "кардинально";
$replacements[4] = preg_replace("/\\./", ". ", "$0");

echo preg_replace($patterns, $replacements, $text);

[/CODE]
#441 #1073587
Так, ладно, я тупой, но код все равно работает странно. Вот этот пример работает, как надо, заменяет точки без пробелов на точки с пробелами:

[CODE]

$text = "aaaaa.ffffff";
$regexp = "/\\w\\.\\S/ui";
$matches = array();

preg_match_all($regexp, $text, $matches);
var_dump($matches);

echo preg_replace('/\\./', '. ', $matches[0][0]);

[/CODE]

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

[CODE]

mb_internal_encoding('UTF-8');

$text = "вышел сдесь координально жы есть aaaa.fffff";

$patterns = array();
$patterns[0] = "/(ж|ш)ы/ui";
$patterns[1] = "/сдесь/ui";
$patterns[2] = "/здел(ал|ан|аю)/ui";
$patterns[3] = "/координально/ui";
$patterns[4] = "/\\w\\.\\S/ui";

$replacements = array();
$replacements[0] = preg_replace("/ы/ui", "и", "$0");
$replacements[1] = "здесь";
$replacements[2] = preg_replace("/з/ui", "с", "$0");
$replacements[3] = "кардинально";
$replacements[4] = preg_replace("/\\./", ". ", "$0");

echo preg_replace($patterns, $replacements, $text);

[/CODE]
#442 #1073636
>>1073581
Можно. Если контрол умеет обрабатывать JSON.
Контроллер выполняет задачу, отдает JSON. AJAXовый контрол парсит данные и рефрешит элементы.
#443 #1073649
>>1073587
Бляя почитай какие символы можно использовать в регулярных
#444 #1073651
>>1073587
Алсо foreach'ем пройтись надо по массивам, откуда вы берётесь такие
#445 #1073660
>>1073566
А в чем проблема сделать аякс запрос в нужный route на сервер? Какая аяксу разница делаешь ты аякс-запрос в пхп-скрипт или в контроллер?
Контроллер делает то, что ты ему скажешь. Скажешь рендерить страницу, он будет рендерить страницу. Скажешь выплюнуть json-код - он его выплюнет. Скажешь ничего не делать и кинуть 500 эррор, он его кинет. Контроллер это тот же пхп скрипт, просто с кучей подтянутого на фоне бэкенда.
#446 #1073663
Пояните нубу, зачем нужна возмозможность объявлять функции в переменной, вот так: $pizda = function ($huy) и в каких ситуациях это используется?
#447 #1073664
>>1073566
Командуешь аяксу кинуть запрос на нужный адрес - myfacebook.com/controller/method
Командуешь методу контроллера принять данные из запроса и return new Response(200) или че там в йии.
#448 #1073665
>>1073418
Нет. Что такое классы?
#451 #1073694
>>1073670
Добра тебе анон.
#452 #1073765
Подскажите как лучше всего конвертировать min.js в js и обратно? Можно ли это сделать средствами netbeans 8.2?
#453 #1073781
>>1073670
Прочел все по ссылкам про замыкания, колбек и анонимные функции. Вроде все понял, но я бы еще задачи порешал. Может у кого-то есть на эту тему? У ОПа только задача про айпад в уроках, которую я давно решил.
#454 #1073789
>>1073663

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

Зачем они нужны? Разберем пример.

Представь, что у тебя есть склад. На складе лежат товары, у каждого товара есть вес (в кг), цена и название.

Склад можно описать с помощью массива товаров (попробуй). У меня получилось так:

$warehouse = [
['name' => 'картошка', 'weight' => 100, 'price' => 100500],
['name' => 'морковка', 'weight' => 50, 'price' => 5000],
...
];

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

function findByName($warehouse, $name) { ... }

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

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

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

- товары с названием на букву "А"
- товары легче 100 кг
- товары, у которых цена за килограмм меньше 10

Как представить в коде и как передать в функцию эти критерии поиска? Как передать условие "легче 100 кг"? Тут-то и приходят на помощь анонимные функции. Мы можем выразить критерий поиска в виде анонимной функции, которая получает на вход товар и возвращает true или false в зависимости от того, соответствует товар условию поиска или нет.

Вот пример функции, которая получает на вход товар (массив с информацией об одном товаре) и проверяет, что он весит меньше 100 кг:

$checkWeightIsLessThan100 = function ($item) {
return $item['weight'] < 100;
};

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

$items = findItems($warehouse, $checkWeightLessThan100);

Задание:

1) допиши код, чтобы все это работало
2) прочитай в мануале про array_map и array_filter
3) прочитай в мануале про usort. Эта функция позволяет отсортировать (упорядочить) элементы массива по произвольному критерию. Напиши функцию, которая отсортирует товары на складе, чтобы они шли в таком порядке:

а) сначала группа товаров с ценой менее 1000
б) за ними группа товаров с ценой менее 5000
в) за ними оставшиеся товары

Внутри групп а, б, в товары сортируются по названию (по алфавиту).

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

function createCounter() { ... }

$c1 = createCounter(); // создаем первый счетчик. в $c1 должна записаться анонимная функция, которая при каждом вызове будет возвращать числа, начиная с 1

echo $с1(); // выводит 1
echo $c1(); // выводит 2
echo $c1(); // выводит 3

$c2 = createCounter(); // создаем вторую независимую функцию-счетчик

echo $c2(); // 1
echo $c2(); // 2

// при этом первая функция-счетчик тоже работает:

echo $c1(); // 4
echo $c1(); // 5

Думаю, этого хватит, чтобы получить общее представление об анонимных функциях. Спрашивай, если что-то непонятно.
#454 #1073789
>>1073663

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

Зачем они нужны? Разберем пример.

Представь, что у тебя есть склад. На складе лежат товары, у каждого товара есть вес (в кг), цена и название.

Склад можно описать с помощью массива товаров (попробуй). У меня получилось так:

$warehouse = [
['name' => 'картошка', 'weight' => 100, 'price' => 100500],
['name' => 'морковка', 'weight' => 50, 'price' => 5000],
...
];

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

function findByName($warehouse, $name) { ... }

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

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

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

- товары с названием на букву "А"
- товары легче 100 кг
- товары, у которых цена за килограмм меньше 10

Как представить в коде и как передать в функцию эти критерии поиска? Как передать условие "легче 100 кг"? Тут-то и приходят на помощь анонимные функции. Мы можем выразить критерий поиска в виде анонимной функции, которая получает на вход товар и возвращает true или false в зависимости от того, соответствует товар условию поиска или нет.

Вот пример функции, которая получает на вход товар (массив с информацией об одном товаре) и проверяет, что он весит меньше 100 кг:

$checkWeightIsLessThan100 = function ($item) {
return $item['weight'] < 100;
};

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

$items = findItems($warehouse, $checkWeightLessThan100);

Задание:

1) допиши код, чтобы все это работало
2) прочитай в мануале про array_map и array_filter
3) прочитай в мануале про usort. Эта функция позволяет отсортировать (упорядочить) элементы массива по произвольному критерию. Напиши функцию, которая отсортирует товары на складе, чтобы они шли в таком порядке:

а) сначала группа товаров с ценой менее 1000
б) за ними группа товаров с ценой менее 5000
в) за ними оставшиеся товары

Внутри групп а, б, в товары сортируются по названию (по алфавиту).

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

function createCounter() { ... }

$c1 = createCounter(); // создаем первый счетчик. в $c1 должна записаться анонимная функция, которая при каждом вызове будет возвращать числа, начиная с 1

echo $с1(); // выводит 1
echo $c1(); // выводит 2
echo $c1(); // выводит 3

$c2 = createCounter(); // создаем вторую независимую функцию-счетчик

echo $c2(); // 1
echo $c2(); // 2

// при этом первая функция-счетчик тоже работает:

echo $c1(); // 4
echo $c1(); // 5

Думаю, этого хватит, чтобы получить общее представление об анонимных функциях. Спрашивай, если что-то непонятно.
#455 #1073798
>>1067944 (OP)
пишу скриптик по работе, как отправить смс в скрипте через свою мобилу? Есть ли какие то програмки с API на Android или IOS?
#456 #1073806
Разница между php 5 и php 7 большая?
#457 #1073811
А php версии откатывать можно?
#458 #1073813
>>1067945
Есть ли выравнивание кода в атоме? По дефолту или же с помощью доп пакета?
#459 #1073971
Здарова, натуралы.

Ищем себе человечка. Джуна/Мидла.
Локация: Москва.
Нужно знание PHP7, Symfony 3 и MySQL/PostgresSQL (вообще похуй, т.к. есть DoctrineORM же).

Вообще у нас дают тестовое , после собеседования, но его (естесно)
никто не делает.
Так вот, анон, я предлагаю тебе запилить его! Я его проверю, помогу тебе в тихаря "причесать" и оформить так, чтобы тимлиду понравилось.
Если все будет ОК, то тебя пригласят на собес. Собес == взять на работу. Т.к. он больше будет нужен провети тебя на имбецильность и шизу (80% кандидатов такие).

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

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

http://rgho.st/6Sw48CLfT - само задание

С вопросами и выполненным заданием пишите в телегу: @spudro или в треде.
8 Кб, 531x170
#460 #1073979
Какая наилучшая последовательность изучения?
В сети предлагают разные
Занимаясь 3 месяца по 18 часов в день хватит освоить эти азы?
#462 #1073984
>>1073983
Вай?
Я так диплом писал по радиотехнике
параллельно ебашил чертежы и паял схему
#463 #1073989
>>1073984

>чертежы


Это немного сложнее чем кописатить совковое говно.

Еще бля понабрал говна разного, ты вообще что хочешь?
#464 #1073990
>>1073989
Ебать ты даун братишка
#465 #1073992
>>1073989
вебмакака горит лол.
схемотехника для него это изи.
иди выпились еблан.
#466 #1073998
>>1073992
Ты че так порвался-то? Опять зарплату канифолью выдали?
#467 #1074008
>>1073813
вроде бы есть, по поиску расширений поищи.
20 Кб, 1105x217
#468 #1074022
Что это? Пытался с пеки запустить регулярное выражение, которое было в примере с котом, выдало это.
#469 #1074032
>>1074022
Кодировка строки не та.
#470 #1074036
>>1073636

>Контроллер выполняет задачу, отдает JSON.


Это можно. Но как организовать приём? То есть, вот эту штуку:

>AJAXовый контрол парсит данные и рефрешит элементы.



>>1073660

>А в чем проблема сделать аякс запрос в нужный route на сервер? Какая аяксу разница делаешь ты аякс-запрос в пхп-скрипт или в контроллер?


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

>>1073664
То есть, всё же, считывать нажатие на кнопку не контроллером, а js-скриптом - это правильно? Но я тогда не понимаю, как это согласуется с моделью MVC. Не претендует ли скрипт на роль второго контроллера?
#471 #1074039
>>1073971

> и MySQL/PostgresSQL (вообще похуй, т.к. есть DoctrineORM же).


Это типичное заблуждение, что можно не знать SQL если ты используешь ORM. Это не так. SQL знать все равно надо (а в случае с доктриной еще и DQL).
#472 #1074041
>>1073971

Также, где гарантия что ты именно работодатель, а не соискатель, желающий, чтобы ему кто-нибудь сделал тестовое задание?
#473 #1074042
>>1074022

Программу в utf-8 сохранил на диск?
#474 #1074047
>>1074039
Все тонкости типа работы с jsonb или встроенным полнотекстовым поиском есть в доках, а основы работы с базой это матчасть. А больше джуну и не надо.

>>1074041

>где гарантия


За щекой у тебя.
#475 #1074070
Можно ли через Html::activeTextInput не рендерить в имя название модели?
#476 #1074154
>>1073453
Щас бы тестовуху джуна на ебаном yii 1.0.0 положить в проект. Энджою.
#477 #1074158
Как правильно реализовать метод, общий для трёх контроллеров?
#478 #1074200
>>1074158
Сделать общего родителя и реализовать там?
#479 #1074201
>>1074200
Родитель фреймворковский, его вроде зашкварно изменять. Или норм?
#480 #1074204
>>1074200
>>1074158
Если есть возможность - вынести логику в отдельный сервис/хелпер, который потом можно будет вызывать из любого контроллера, из консоли, в юнит-тестах. Да кого я обманываю - какие юнит-тесты у похапешников?
Метод попроще и похуже - вынести в трейт.
Самый плохой - наследование. Завтра у него появится другая функция, которую нужно переиспользовать в разных контроллерах, а множественного наследования в PHP, к счастью, нет.

>>1074201
Это вообще не норм.

>>1073798
sms.ru

И какое отношение "Android или IOS?" имеют к треду?
#481 #1074209
>>1074204

>вынести логику в отдельный сервис/хелпер


Как об этом нагуглить чтиво?
#482 #1074228
>>1074209
https://github.com/codedokode/pasta/blob/master/arch/di.md
https://github.com/jupeter/clean-code-php
http://blog.byndyu.ru/2009/10/solid.html (если не знаешь C#, то читни туториал на learnxinyminutes, там очень сжато про синтаксис)

Советую изучать ООП в целом. Так как на классах вполне себе можно писать процедурный сложно читаемый код. Я вот сейчас работаю с проектом, в котором люди лепят наследование вместо DI, по ходу выполнения программы создают у объекта свойства (почему это вообще не запретят в PHP?), а потом повсюду проверяют if (isset($obj->property1) && isset($obj->property2))
Читать такой код очень тяжело, вместо того, чтобы доверять объектам с инкапсуляцией приходится держать в голове кучу внутренностей класса. Ну а вообще вот слова для гугления:
- Dependency Injection (контейнер тебе пока не нужен)
- SOLID/GRASP
- Composition over inheritance
- Law of Demeter
- Cohesion/Coupling

В ссылках выше всё это есть. И самое главное - практикуйся. В ОП-посте есть хорошие задачи, ты можешь написать игру консольную (например шахматы, без ИИ). Недавно наткнулся на такую задачу: https://gist.github.com/wbars/2c3590206ee4a590eca5
#483 #1074284
Анон, с задачей на гитхабе, подожди еще чуть-чуть.

>>1074158

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

Лучше бы ты конечно привел конкретную ситуацию, а то так абстрактно трудно комемнтировать.

Алсо почитай мой урок про MVC https://github.com/codedokode/pasta/blob/master/arch/mvc.md

>>1074070

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

>>1074036

> считывать нажатие на кнопку не контроллером, а js-скриптом - это правильно?


А как PHP-код, который выполняется на сервере, может "считать" (обработать) нажатие на кнопку в браузере? По моему кроме JS, это никак не сделать (если только через отправку формы, но это тебе не подходит).

> Получится лишняя прослойка. На вью кнопка, при нажатии срабатывает js (а не контроллер)


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

Соответственно, будешь ты использовать аякс или нет - с MVC никак не связано, так как MVC применяется в данном случае для описания только кода на сервере. Формально можно сказать, что JS скрипт является частью вью, но ведь он не выполняется на сервере и он для сервера ничем не отличается от HTML-разметки - это просто какие-то текстовые данные, которые надо отдать в HTTP-ответе.

Потому MVC никак не запрещает использовать аякс. Аякс-запросы в MVC стоит обрабатывать так же, как и обычные, пропуская их через тот же самый фронт-контроллер или роутер, а затем вызывая контроллер.

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

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


Нет, так как он не на PHP и не выполняется на сервере.

> Мне интересно, можно ли сделать так, чтобы нажатие на кнопку обрабатывал контроллер Yii, а дабавление строки далалось без рефреша страницы?


Код на сервере не может добавить строку в DOM. Это может сделать только JS-код.
#483 #1074284
Анон, с задачей на гитхабе, подожди еще чуть-чуть.

>>1074158

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

Лучше бы ты конечно привел конкретную ситуацию, а то так абстрактно трудно комемнтировать.

Алсо почитай мой урок про MVC https://github.com/codedokode/pasta/blob/master/arch/mvc.md

>>1074070

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

>>1074036

> считывать нажатие на кнопку не контроллером, а js-скриптом - это правильно?


А как PHP-код, который выполняется на сервере, может "считать" (обработать) нажатие на кнопку в браузере? По моему кроме JS, это никак не сделать (если только через отправку формы, но это тебе не подходит).

> Получится лишняя прослойка. На вью кнопка, при нажатии срабатывает js (а не контроллер)


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

Соответственно, будешь ты использовать аякс или нет - с MVC никак не связано, так как MVC применяется в данном случае для описания только кода на сервере. Формально можно сказать, что JS скрипт является частью вью, но ведь он не выполняется на сервере и он для сервера ничем не отличается от HTML-разметки - это просто какие-то текстовые данные, которые надо отдать в HTTP-ответе.

Потому MVC никак не запрещает использовать аякс. Аякс-запросы в MVC стоит обрабатывать так же, как и обычные, пропуская их через тот же самый фронт-контроллер или роутер, а затем вызывая контроллер.

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

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


Нет, так как он не на PHP и не выполняется на сервере.

> Мне интересно, можно ли сделать так, чтобы нажатие на кнопку обрабатывал контроллер Yii, а дабавление строки далалось без рефреша страницы?


Код на сервере не может добавить строку в DOM. Это может сделать только JS-код.
#484 #1074285
>>1073811

Это зависит от того, какая у тебя ОС и как ты устанавливал PHP. В Windows точно можно удалить одну версию PHP и установить другую, в Дебиане, я думаю тоже, хотя там могут быть подвохи (например, старая версия PHP требует старую библиотеку, которая не совместима с другими программами). Для линукса также есть скрипт phpenv, который умеет по команде скачивать и компилировать любую версию PHP, а также делать другие интересные вещи.

>>1073806

Не очень, но в PHP7 есть полезные улучшения, о которых надо знать. Погугли статьи "что нового в PHP7".

>>073798



С андроида СМС можно отправить через встроенный в смартфон модем.

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

>>1073765

Гугли JS beautify. Код правда может быть обфусцирован (запутан) и ты все равно его не разберешь. Если это библиотека то лучше найти исходники.

> и обратно?


Гугли "минификация JS"

>>1073418

Да, и тебе не придется долго учиться так как ООП в PHP очень похож на ООП в Java.
#485 #1074286
>>1073587

> $replacements[0] = preg_replace("/ы/ui", "и", "$0");


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

А выполняется код (если нет if, циклов и тд) сверху вниз. Соответственно, эта строчка выполнится так:

PHP вызовет функцию preg_replace("/ы/ui", "и", "$0"), которая ищет в строке "$0" соответствие шаблону "/ы/ui". Соответствия нет, потому функция вернет просто строку "$0", которая и запишется в массив.

Вот пример, как правильно использовать $0-$9 при замене текста:

echo preg_replace("/(\S+)@(\S+)/", '$1 [at] $2', "Напишите мне на aa6aZaANUSex#1}amplePUNCTUMco;[#m");
// Напишите мне на aaa [at] example.com

Если тебе нужно, чтобы при нахождении совпадения с регуляркой вызывался твой код, то тебе нужна функция preg_replace_callback и анонимные функции (с помощью анонимной функции ты описываешь, что делать при нахождении совпадения с шаблоном). Прочесть при них можно в мануале, а я дам пример их использования: https://repl.it/M3uo/1

mb_internal_encoding('utf-8');

$text = "здравствуйте. до свидания.";

echo preg_replace_callback("/(\A|\.\s*)\w/u", function ($m) {
return mb_strtoupper($m[0]);
}, $text);
echo "\n";

// Здравствуйте. До свидания.

\A значит "начало текста".

>>1073188

С джойнами? Джойн без ограничений дает присоединение каждой строки к каждой и в твоем случае выдаст таблицу с 5 * 2 * 12 = 120 строками.

>>1073187

Твое выражение, к сожалению, не годится, так как .* значит "любое число любых символов, кроме \n". Очевидно, что оно будет соответствовать вообще любым текстовым строкам, где есть цифры.

Ты тестировал свою регулярку на https://regex101.com/r/qF7vT8/3 ?

Вот, как надо ее решать:

Сначала надо внимательно изучить примитивные конструкции, из которых составляются шаблоны: точка, квантифкаторы (звездочки, плюсы, фигурные скобки), вертикальная черта, круглые скобки, квадратные скобки, условия вроде ^ или \b.

Потом мы пишем такое выражение:

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

Мануал в помощь: http://php.net/manual/ru/pcre.pattern.php
#485 #1074286
>>1073587

> $replacements[0] = preg_replace("/ы/ui", "и", "$0");


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

А выполняется код (если нет if, циклов и тд) сверху вниз. Соответственно, эта строчка выполнится так:

PHP вызовет функцию preg_replace("/ы/ui", "и", "$0"), которая ищет в строке "$0" соответствие шаблону "/ы/ui". Соответствия нет, потому функция вернет просто строку "$0", которая и запишется в массив.

Вот пример, как правильно использовать $0-$9 при замене текста:

echo preg_replace("/(\S+)@(\S+)/", '$1 [at] $2', "Напишите мне на aa6aZaANUSex#1}amplePUNCTUMco;[#m");
// Напишите мне на aaa [at] example.com

Если тебе нужно, чтобы при нахождении совпадения с регуляркой вызывался твой код, то тебе нужна функция preg_replace_callback и анонимные функции (с помощью анонимной функции ты описываешь, что делать при нахождении совпадения с шаблоном). Прочесть при них можно в мануале, а я дам пример их использования: https://repl.it/M3uo/1

mb_internal_encoding('utf-8');

$text = "здравствуйте. до свидания.";

echo preg_replace_callback("/(\A|\.\s*)\w/u", function ($m) {
return mb_strtoupper($m[0]);
}, $text);
echo "\n";

// Здравствуйте. До свидания.

\A значит "начало текста".

>>1073188

С джойнами? Джойн без ограничений дает присоединение каждой строки к каждой и в твоем случае выдаст таблицу с 5 * 2 * 12 = 120 строками.

>>1073187

Твое выражение, к сожалению, не годится, так как .* значит "любое число любых символов, кроме \n". Очевидно, что оно будет соответствовать вообще любым текстовым строкам, где есть цифры.

Ты тестировал свою регулярку на https://regex101.com/r/qF7vT8/3 ?

Вот, как надо ее решать:

Сначала надо внимательно изучить примитивные конструкции, из которых составляются шаблоны: точка, квантифкаторы (звездочки, плюсы, фигурные скобки), вертикальная черта, круглые скобки, квадратные скобки, условия вроде ^ или \b.

Потом мы пишем такое выражение:

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

Мануал в помощь: http://php.net/manual/ru/pcre.pattern.php
#486 #1074287
>>1073184

Спамботы не нужны.

>>1073183

Плюс - это спецсимвол, который обозначает повторение предыдущего символа от 1 до ∞ раз. Чтобы написать в шаблоне просто "ищи символ плюс", его надо экранировать бекслешем: \+ и он потеряет свое специальное значение.

Спецсимволы в регулярках надо выучить наизусть ( http://php.net/manual/ru/regexp.reference.meta.php ).

Бекслеш также можно писать 2 раза, так как бекслеш имеет специальное значение при записи строк ( http://php.net/manual/ru/language.types.string.php ) и когда мы пишем \\+, то \\ интерпретируется как \ и в строку попадает просто \+.

>>1073113

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

>>1073070

Правильно.

>>1072962

Читал мой урок? Там и пример MVC кода есть https://github.com/codedokode/pasta/blob/master/arch/mvc.md

>>1072955

Это символы, которые используются при описании массивов и в конструкции foreach:

$a = [1 => 100, 2 => 50];
foreach ($a as $k => $v) { ... }

Стрелка является частью этих конструкций и отдельно от них не несет никакого смысла.
#486 #1074287
>>1073184

Спамботы не нужны.

>>1073183

Плюс - это спецсимвол, который обозначает повторение предыдущего символа от 1 до ∞ раз. Чтобы написать в шаблоне просто "ищи символ плюс", его надо экранировать бекслешем: \+ и он потеряет свое специальное значение.

Спецсимволы в регулярках надо выучить наизусть ( http://php.net/manual/ru/regexp.reference.meta.php ).

Бекслеш также можно писать 2 раза, так как бекслеш имеет специальное значение при записи строк ( http://php.net/manual/ru/language.types.string.php ) и когда мы пишем \\+, то \\ интерпретируется как \ и в строку попадает просто \+.

>>1073113

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

>>1073070

Правильно.

>>1072962

Читал мой урок? Там и пример MVC кода есть https://github.com/codedokode/pasta/blob/master/arch/mvc.md

>>1072955

Это символы, которые используются при описании массивов и в конструкции foreach:

$a = [1 => 100, 2 => 50];
foreach ($a as $k => $v) { ... }

Стрелка является частью этих конструкций и отдельно от них не несет никакого смысла.
#487 #1074289
>>1072797

> ни ооп, ни мвц, ничегошечки их этого


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

> это как их разделять, что такое мвц вообще? в задании не было сказано его использовать


Есть урок https://github.com/codedokode/pasta/blob/master/arch/mvc.md

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


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

Алсо, в ОП посте в учебнике написано про ООП. Также, там есть задача про студентов, которая поможет изучить MVC.

>>1072762

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

Смысл выражения "под ключ" описан тут: https://ru.wiktionary.org/wiki/под_ключ

> не требующий доделки, доводки, настройки; в полностью готовом к немедленной эксплуатации состоянии



>>1072407

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

>>1072366

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

>>1072070

Решено верно.

>>1071905

> Сдача https://3v4l.org/LHVOQ



> foreach ($bills as $key => $value) {


Лучше было дать переменным key/value более осмысленные имена (номинал и число купюр).

> while ($key <= $amount){


> $billsForDelivery[$key]++;


Используй деление вместо цикла.

Также, не проверяется наличие нужного набора купюр. Вот например, купюр номиналом 200 нет, а он пишет, что выдать сумму возможно: https://3v4l.org/JX2Hd

Пока что неправильно.

> Лиличка https://3v4l.org/jc4PN



Тут важно предупредить, что в Windows некоторые программы кодируют новую строку как \r\n ( ). Этот символ может испортить расчет длин строк и вывод текста, потому для надежности можно его удалять, или делать разбиение по выражению \r?\n

> preg_split('/\n/',


Можно было просто explode использовать

Найти макс. длину строки может быть удобнее через max() и array_map(), сможешь?

А так, работает верно.

> Считалка https://3v4l.org/dDAaI



> for($j = $numberLeft; $j < $total; $j++){


> $positions[$j] = $positions[$j+1];


Удаление элемента удобнее делать через array_slice.

> if ($total - $numberLeft < $skip - 1){


> $numberLeft = $skip - ($total - $numberLeft) - 1;


> } else {


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

> $total--;


Вместо этой переменной можно было использовать count().

Так, работает верно.

> Алфавит https://3v4l.org/d5PAs



> $letters = preg_split("//u", $phrase);


там надо добавлять флаг PREG_SPLIT_NO_EMPTY, а то в массив добавляются 2 пустых элемента с краев. Видимо по этой причине тебе пришлось в $i <= $phraseLength; написать <= вместо <.

> for ($y = 0; $y < $height; $y++){


> $screen[$y] = array_fill(0, 150, ' ');


Можно было 2 раза использовать array_fill вместо цикла.

> $coordinateYOfLetter


Лучше $letterX

> foreach ($value as $a) {


> echo $a;


Можно было использовать implode.

Так, работает верно.

> Навигатор https://3v4l.org/75dUN



> $paths[$startPoint][1][0] = 0;


А что значит [1][0] ? Что-то я не очень понимаю. Ты зря в справочник расстояний добавляешь какие-то странные элементы, лучше было сделать отдельный массив для хранения времени до точки.

> foreach ($paths as $key => &$value) {


Тут надо помнить, что после окончания цикла переменная $value продолжает указывать на последний элемент массива и команда $value = 1 запишет туда единицу например. И цикл foreach ($x as $value) тоже запишет значение по ссылке.

Это вроде бы описано в мануале.

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

> if ($value2 == $key){


> continue 2;


А тут не просто continue должно быть?

Вместо key и value лучше было выбрать более понятные имена.

Часть кода можно было вынести в функции, например, поиск ближайшей к текущей точки, ради повышения читабельности кода.
#487 #1074289
>>1072797

> ни ооп, ни мвц, ничегошечки их этого


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

> это как их разделять, что такое мвц вообще? в задании не было сказано его использовать


Есть урок https://github.com/codedokode/pasta/blob/master/arch/mvc.md

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


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

Алсо, в ОП посте в учебнике написано про ООП. Также, там есть задача про студентов, которая поможет изучить MVC.

>>1072762

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

Смысл выражения "под ключ" описан тут: https://ru.wiktionary.org/wiki/под_ключ

> не требующий доделки, доводки, настройки; в полностью готовом к немедленной эксплуатации состоянии



>>1072407

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

>>1072366

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

>>1072070

Решено верно.

>>1071905

> Сдача https://3v4l.org/LHVOQ



> foreach ($bills as $key => $value) {


Лучше было дать переменным key/value более осмысленные имена (номинал и число купюр).

> while ($key <= $amount){


> $billsForDelivery[$key]++;


Используй деление вместо цикла.

Также, не проверяется наличие нужного набора купюр. Вот например, купюр номиналом 200 нет, а он пишет, что выдать сумму возможно: https://3v4l.org/JX2Hd

Пока что неправильно.

> Лиличка https://3v4l.org/jc4PN



Тут важно предупредить, что в Windows некоторые программы кодируют новую строку как \r\n ( ). Этот символ может испортить расчет длин строк и вывод текста, потому для надежности можно его удалять, или делать разбиение по выражению \r?\n

> preg_split('/\n/',


Можно было просто explode использовать

Найти макс. длину строки может быть удобнее через max() и array_map(), сможешь?

А так, работает верно.

> Считалка https://3v4l.org/dDAaI



> for($j = $numberLeft; $j < $total; $j++){


> $positions[$j] = $positions[$j+1];


Удаление элемента удобнее делать через array_slice.

> if ($total - $numberLeft < $skip - 1){


> $numberLeft = $skip - ($total - $numberLeft) - 1;


> } else {


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

> $total--;


Вместо этой переменной можно было использовать count().

Так, работает верно.

> Алфавит https://3v4l.org/d5PAs



> $letters = preg_split("//u", $phrase);


там надо добавлять флаг PREG_SPLIT_NO_EMPTY, а то в массив добавляются 2 пустых элемента с краев. Видимо по этой причине тебе пришлось в $i <= $phraseLength; написать <= вместо <.

> for ($y = 0; $y < $height; $y++){


> $screen[$y] = array_fill(0, 150, ' ');


Можно было 2 раза использовать array_fill вместо цикла.

> $coordinateYOfLetter


Лучше $letterX

> foreach ($value as $a) {


> echo $a;


Можно было использовать implode.

Так, работает верно.

> Навигатор https://3v4l.org/75dUN



> $paths[$startPoint][1][0] = 0;


А что значит [1][0] ? Что-то я не очень понимаю. Ты зря в справочник расстояний добавляешь какие-то странные элементы, лучше было сделать отдельный массив для хранения времени до точки.

> foreach ($paths as $key => &$value) {


Тут надо помнить, что после окончания цикла переменная $value продолжает указывать на последний элемент массива и команда $value = 1 запишет туда единицу например. И цикл foreach ($x as $value) тоже запишет значение по ссылке.

Это вроде бы описано в мануале.

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

> if ($value2 == $key){


> continue 2;


А тут не просто continue должно быть?

Вместо key и value лучше было выбрать более понятные имена.

Часть кода можно было вынести в функции, например, поиск ближайшей к текущей точки, ради повышения читабельности кода.
#488 #1074291
>>1071465

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

>>1071847

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

>>1071671

[abc] - один любой символ из набора a, b, c
[a-d] - любой символ от a до d
[a-fmn] - любой символ от a до f, или m или n

>>1071608

В один проход наверно никак.

>>1071615

Основы то изучить нетрудно, и learn.javascript.ru пройти. не будешь же за каждой правкой бегать к верстальщику.

>>1071513

> В элементе adr::before когда я ставлю ему контент иконки, он перестает быть inline-block элементом,


Лучше сделать ::before просто блоком или абсолютно позиционированным относительно колонки блоком. В контент поставить пустую строку. Задать размеры. Поставить картинку как фоновую.

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

>>1071463

> ни в какую не хочет расширяться в fit-content,


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

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

>>1074209

Просто сделать отдельный класс, который делает что нужно, и использовать его в твоих 3 контроллерах.
#488 #1074291
>>1071465

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

>>1071847

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

>>1071671

[abc] - один любой символ из набора a, b, c
[a-d] - любой символ от a до d
[a-fmn] - любой символ от a до f, или m или n

>>1071608

В один проход наверно никак.

>>1071615

Основы то изучить нетрудно, и learn.javascript.ru пройти. не будешь же за каждой правкой бегать к верстальщику.

>>1071513

> В элементе adr::before когда я ставлю ему контент иконки, он перестает быть inline-block элементом,


Лучше сделать ::before просто блоком или абсолютно позиционированным относительно колонки блоком. В контент поставить пустую строку. Задать размеры. Поставить картинку как фоновую.

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

>>1071463

> ни в какую не хочет расширяться в fit-content,


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

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

>>1074209

Просто сделать отдельный класс, который делает что нужно, и использовать его в твоих 3 контроллерах.
#489 #1074307
>>1074042
Нет. Я даже не знаю о такой.
#490 #1074308
>>1074307

Кодировка выбирается в настройках редактора или при сохранении. Нужно выбирать utf-8 without BOM.
#491 #1074310
А важны ли знания о основах информатики, её истории, меры Шеннона всякие, архитектура ЭВМ и так далее для?
#492 #1074329
>>1073789
Сделал задачу на функцию счетчик:
https://ideone.com/ADY3k4
Правильно? Алсо, лучей добра за объяснение.
#493 #1074332
>>1074329

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

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

$c1 = createCounter(3);
echo $c1(); // 3

если значение не передано, то оно равняется 1.
#494 #1074333
#495 #1074361
>>1074284

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


Спасибо, стало понятнее.
#496 #1074425
Делал раньше файлообменник на слиме, но потом в силу обстоятельств забил на полгода и вот теперь опять возвращаюсь, но теперь решил писать его на Йии. Пока читаю документацию, полет нормальный. Только подскажите, на какие классы стоит обратить внимание для решения задачки? Их дохуя чет, а я пока знаю только стандартные фичи с контроллерами, ну там построение форм и валидацию, этив реворд, ну ты понел.
18 Кб, 300x260
#497 #1074436
Привет, котоны. У меня печаль. Пишу на Laravel 5.5 и использую валидатор для проверки ввода. Валидатор отрабатывает, но сообщений об ошибках нет. Переменная $errors всегда пустая. Почему так происходит?
#498 #1074464
Не знаю где спросить кроме вас. В оьбщем нужен дешовый хостинг с PHP7.0 или 7.1, хостился на Godaddy но они за следующий год запросили аж 20 тыщь. Хотя у меня весь сайт это 500 посетителей и метров 50 сам сай с БД. Денег сайт не приносит, а вот вваливать в него так много я не собираюсь. Может знает кто что?
#499 #1074468
Laravel: Up and Running: A Framework for Building Modern PHP Apps от O'Reilly где можно скачать бесплатно и без смс?
#500 #1074474
>>1074289

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


ох уж эти программисты, так заботятся обо мне, вместо того, чтобы просто ответить
#501 #1074476
>>1074464
Виртуальный хостинг
#502 #1074487
>>1074468

>где можно скачать бесплатно и без смс?


Мы в этом итт треде против пиратства и за интеллектуальную собственность. Лучше конечно купить. Но вдруг ты гол как сокол в жерновах вечного постсовкового кризиса? Что ж тебе теперь книжек не читать?
gen.lib.rus.ec
10 Кб, 353x166
#503 #1074513
Yii2
Как регистрировать пользователей через бд я осилил. И они даже потом могут залогиниться. Но стоит нажать на любую другую ссылку, логин пропадает.

Возможно это от того, что при логине меняется PHPSESSID. До логина там одно значение, а после - другое. Нагуглил только, что Yii::$app->user->login($this->getUser() изменяет куку и это нормально. Но в дефолтном примере всё то же самое и работает нормально. Юзер один раз логинится и его логин весит, не отваливаясь.
#504 #1074518
>>1074436
Попробуй один из костылей отсюда: https://github.com/laravel/framework/issues/6028
#505 #1074580
Решаю задачки опа на ЖС и проблема! Помогите разобраться.
Вот собственно задача http://dkab.github.io/jasmine-tests/?spec=4
А вот мое неправильное решение:

function fmap(a, gen) {
return function b() {
c = a(gen(arguments[0],arguments[1]));
return c;
}
}
В задании говорится чтобы нужно чтобы gen принимала любое количество аргументов. А я вот не знаю как это сделать. Конечно можно туда тупо передавать массив со всеми аргументами. Но дело в том что функция ген принимает в качестве аргументов два числа. Я конечно бы мог просто переписать этот ген. Но вроде как нужно написать все в этой функции.
#506 #1074589
>>1074580

Погугли Function.prototype.call и Function.prototype.apply.

Функции в JS это объекты и у них есть прототип с несколькими полезными методами.
#507 #1074645
>>1074589
что-то я не понимаю как это работает совсем. Прочитал несколько статей и все равно. Какая-то каша фаршу. Может есть какое-то более доступное объяснение?
#508 #1074647
>>1074645

А тут читал?

- https://learn.javascript.ru/call-apply
- https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

Вот пример:

function f(a, b) { ... }
var context = {};

f.call(context, 100, 200); // вызывает f, передавая ей this = context, a = 100, b = 200

f.apply(context, [100, 200]); // вызывает f, передавая ей this = context, a = 100, b = 200

Вместо context можно передавать null, тогда this будет указывать на глобальный объект (window в браузере, global в Node.JS).

Что именно непонятно? Или тебе непонятны объекты, методы и прототипы?
#509 #1074659
>>1074647
Непонятно например как функции это объекты.
Да я понял уже что рано залез в задачи. Пошел читать learn.javascript.ru. Просто я не думал что настолько все сложно для меня будет.
#510 #1074661
>>1074659

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

> например как функции это объекты.



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

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

Когда ты разберешься, ты увидишь, что это само по себе очень разумно и удобно сделано.
#511 #1074669
>>1074661
Спасибо за поддержку друг!
#512 #1074689
>>1074332

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


$c1 = createCounter(3);
echo $c1(); // 3
если значение не передано, то оно равняется 1.
Переделал с новым условием:
https://ideone.com/rATnXa
#513 #1074692
>>1074689

Решено верно. Надеюсь, ты теперь лучше понимаешь анонимные функции.
https://github.com/vadimyen/students #514 #1074717

>>1066512


>>1072015

> `gender` tinyint(1) NOT NULL COMMENT '0 - male, 1 - female',


Тут можно было использовать ENUM 'male', 'female', а в коде для пола прописать константы.

> ADD KEY `gender` (`gender`),


Индексы ускоряют поиск по значению поля, но на поля вроде gender, где по одному значению выбирается полтаблицы или больше, их ставить особого смысла нет (это мельком упомянуто например тут https://ruhighload.com/post/Работа+с+индексами+в+MySQL в пункте про селективность).

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

> extract ($router->getController());


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

list($controller, $method) = someFunc();

либо так:

$result = someFunc();
echo $result['controller'];

либо может так:

$result = someFunc();
echo $result->controller;

Я бы не советовал по этой причине использовать тут extract. В других языках вроде Go, есть специальный синтаксис для возврата нескольких значений.

> echo "<b>Искоючение:</b> ", $exception->__toString();


Это хорошо бы отключать на продакшене - например, используя ini-параметр display_errors.

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

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

Что касается констант, удобнее не использовать глобальные константы, а отнести их к какому-то классу. Хотя в общем-то ничего против глобальных констант не имею. Ну и если что, их можно тоже в неймспейсы класть \PageType\HOME или добавить префикс: PAGE_TYPE_HOME. А то не очень понятно, что они обозначают.

> https://github.com/vadimyen/students/blob/master/app/Router.php


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

Также, твой роутер имеет недостатки, что одному действию может соответствовать несколько URL:

/, /Index, /Index/, /Index/index

Это плохо для поисковой оптимизации да и не очень логично.

В этом файле съехали отступы https://github.com/vadimyen/students/blob/master/app/Router.php из-за смешивания табов и пробелов. В PSR рекомендуют использовать 4 пробела для отступа, настрой свой редактор.

Далее, ты используешь PHP7, значит используй его возможности и ставь тайп-хинты на string/int/bool, а также тайп-хинты для возвращаемых значений. Это документирует твой код и защищает от ошибок.

В контейнер обычно кладут объекты без состояния, которые можно смело выдать нескольким потребителям и с которыми ничего не случится. Объект Security у тебя имеет состояние, а значит, он должен каждый раз создаваться заново через new либо при выдаче из контейнера (в Pimple такое возможно, смотри factory). Вообще, к сожалению, даже в Симфони можно увидеть несоблюдение этого приципа - они там кладут в контейнер объекты вроде Request, User, итд. Но это плохо по нескольким причинам:

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

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

> } catch (SException $e) {


> die("<b>There's some trouble with your cookie: </b>" . $e->__toString());


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

https://github.com/vadimyen/students/blob/master/app/Helper/Pager.php
Валидацию параметров лучше наверно делать в контроллере, а не в пагинаторе.

> public function renderPaginator()


Это наверно лучше было бы сделать отдельным шаблоном, а не тащить HTML код в PHP-код.

> private function generateURL($params) {


Функция называется generateUrl, но на деле генерирует только query string.

> public function logIn(Student $student)


> {


> $student->setCookie($this->generateHash(32));


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

Я бы советовал тогда сделать по-другому, например:

- генерировать хеш при вставке в БД
- или вообще сделать метод регистрации, который и хеш с генерирует, и куки выставит

> public function logout(Student $student)


Справедливости ради, для разлогинивания студент в принципе не нужен

Проверку CSRF наверно стоило отделить от авторизации в отдельный класс. У них ведь ничего общего нет, и твой класс Security выглядит как 2 склеенных вместе класса.

> PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, Student::class, array_fill(0, 8, null)


Ага, вот ты и понял, что PDO не очень удобен для заполнения объектов.

https://github.com/vadimyen/students/blob/master/app/Mapper/StudentMapper.php#L70
Тут нет проверки переменных $field, $direction, получается SQL инъекция

> if (isset($pattern)) {


isset проверяет переменную на существование, лучше писать !is_null или !== null, чтобы яснее были видны намерения.

> public function getStudentsWithPagination(


> public function getStudents


Их можно было бы объединить в одну функцию, добавив для $limit значение 0 или \INF

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

https://github.com/vadimyen/students/blob/master/app/Entity/Student.php#L24
конструктор с таким числом аргументов неудобен: легко перепутать их порядок, и неудобно создавать объекты. Лучше либо убрать их вообще, либо предусмотреть возможность передачи массива.

> public function __toString ()


Хочу предупредить, что из-за неявного преобразования в строку можно сразу не заметить ошибку. Ну например, ты думаешь, что в $student лежит id, а там лежит объект. И пытаешься использовать его так:

$query .= " WHERE id = $student ";

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

> if (filter_var($student->getGender(), FILTER_VALIDATE_INT, ["options" => ["min_range" => 0, "max_range" => 1]]) === false) {


Тут по моему проще in_array было использовать.

Также, в мануале по filter_var написано:

> Возвращает отфильтрованные данные или FALSE, если фильтрация завершилась неудачей.



Это ничего, что ты не используешь возвращаемое значение кроме как для проверки на false?
https://github.com/vadimyen/students #514 #1074717

>>1066512


>>1072015

> `gender` tinyint(1) NOT NULL COMMENT '0 - male, 1 - female',


Тут можно было использовать ENUM 'male', 'female', а в коде для пола прописать константы.

> ADD KEY `gender` (`gender`),


Индексы ускоряют поиск по значению поля, но на поля вроде gender, где по одному значению выбирается полтаблицы или больше, их ставить особого смысла нет (это мельком упомянуто например тут https://ruhighload.com/post/Работа+с+индексами+в+MySQL в пункте про селективность).

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

> extract ($router->getController());


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

list($controller, $method) = someFunc();

либо так:

$result = someFunc();
echo $result['controller'];

либо может так:

$result = someFunc();
echo $result->controller;

Я бы не советовал по этой причине использовать тут extract. В других языках вроде Go, есть специальный синтаксис для возврата нескольких значений.

> echo "<b>Искоючение:</b> ", $exception->__toString();


Это хорошо бы отключать на продакшене - например, используя ini-параметр display_errors.

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

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

Что касается констант, удобнее не использовать глобальные константы, а отнести их к какому-то классу. Хотя в общем-то ничего против глобальных констант не имею. Ну и если что, их можно тоже в неймспейсы класть \PageType\HOME или добавить префикс: PAGE_TYPE_HOME. А то не очень понятно, что они обозначают.

> https://github.com/vadimyen/students/blob/master/app/Router.php


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

Также, твой роутер имеет недостатки, что одному действию может соответствовать несколько URL:

/, /Index, /Index/, /Index/index

Это плохо для поисковой оптимизации да и не очень логично.

В этом файле съехали отступы https://github.com/vadimyen/students/blob/master/app/Router.php из-за смешивания табов и пробелов. В PSR рекомендуют использовать 4 пробела для отступа, настрой свой редактор.

Далее, ты используешь PHP7, значит используй его возможности и ставь тайп-хинты на string/int/bool, а также тайп-хинты для возвращаемых значений. Это документирует твой код и защищает от ошибок.

В контейнер обычно кладут объекты без состояния, которые можно смело выдать нескольким потребителям и с которыми ничего не случится. Объект Security у тебя имеет состояние, а значит, он должен каждый раз создаваться заново через new либо при выдаче из контейнера (в Pimple такое возможно, смотри factory). Вообще, к сожалению, даже в Симфони можно увидеть несоблюдение этого приципа - они там кладут в контейнер объекты вроде Request, User, итд. Но это плохо по нескольким причинам:

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

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

> } catch (SException $e) {


> die("<b>There's some trouble with your cookie: </b>" . $e->__toString());


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

https://github.com/vadimyen/students/blob/master/app/Helper/Pager.php
Валидацию параметров лучше наверно делать в контроллере, а не в пагинаторе.

> public function renderPaginator()


Это наверно лучше было бы сделать отдельным шаблоном, а не тащить HTML код в PHP-код.

> private function generateURL($params) {


Функция называется generateUrl, но на деле генерирует только query string.

> public function logIn(Student $student)


> {


> $student->setCookie($this->generateHash(32));


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

Я бы советовал тогда сделать по-другому, например:

- генерировать хеш при вставке в БД
- или вообще сделать метод регистрации, который и хеш с генерирует, и куки выставит

> public function logout(Student $student)


Справедливости ради, для разлогинивания студент в принципе не нужен

Проверку CSRF наверно стоило отделить от авторизации в отдельный класс. У них ведь ничего общего нет, и твой класс Security выглядит как 2 склеенных вместе класса.

> PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, Student::class, array_fill(0, 8, null)


Ага, вот ты и понял, что PDO не очень удобен для заполнения объектов.

https://github.com/vadimyen/students/blob/master/app/Mapper/StudentMapper.php#L70
Тут нет проверки переменных $field, $direction, получается SQL инъекция

> if (isset($pattern)) {


isset проверяет переменную на существование, лучше писать !is_null или !== null, чтобы яснее были видны намерения.

> public function getStudentsWithPagination(


> public function getStudents


Их можно было бы объединить в одну функцию, добавив для $limit значение 0 или \INF

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

https://github.com/vadimyen/students/blob/master/app/Entity/Student.php#L24
конструктор с таким числом аргументов неудобен: легко перепутать их порядок, и неудобно создавать объекты. Лучше либо убрать их вообще, либо предусмотреть возможность передачи массива.

> public function __toString ()


Хочу предупредить, что из-за неявного преобразования в строку можно сразу не заметить ошибку. Ну например, ты думаешь, что в $student лежит id, а там лежит объект. И пытаешься использовать его так:

$query .= " WHERE id = $student ";

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

> if (filter_var($student->getGender(), FILTER_VALIDATE_INT, ["options" => ["min_range" => 0, "max_range" => 1]]) === false) {


Тут по моему проще in_array было использовать.

Также, в мануале по filter_var написано:

> Возвращает отфильтрованные данные или FALSE, если фильтрация завершилась неудачей.



Это ничего, что ты не используешь возвращаемое значение кроме как для проверки на false?
https://github.com/vadimyen/students #515 #1074718

>>1066512


>>1072015

https://github.com/vadimyen/students/blob/master/app/View/index/index.php#L1

> <?php extract($params); ?>


Это лучше наверно было сделать в методе render()

> <a href="/?<?=$pager->getSortingLink('firstName')?>">


Если строго говорить, то тут данные должны тоже экранироваться. Что, если там кавычка или знак &?

https://github.com/vadimyen/students/blob/master/app/View/index/index.php#L31

> <?php if(isset($students)) :


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

https://github.com/vadimyen/students/blob/master/app/View/profile/index.php#L4
Вот этот use тут - плохо. Надо хотя бы переместить его в самый верх файла.

> echo "<li>{$value}</li>";


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

> required=""


Можно просто required

> value="<?=isset($user) ? html($user->getFirstName()) : ""?>


Вот опять же, isset тут плохо. Лучше создать пустой объект.

https://github.com/vadimyen/students/blob/master/app/Controller/ProfileController.php#L30

> try {


> $this->isSubmitted();


> } catch(SException $e) {


> header('Location: /profile');


> exit();


> }


Вот это странно смотрится, почему метод с названием isSubmitted выбрасывает исключение? Не лучше ли было бы сделать if (!$this->isSubmitAllowed()) ... ? Ну и редиректить молча тоже нехорошо, надо хотя бы в URL код ошибки добавить или страницу ошибки показать.

https://github.com/vadimyen/students/blob/master/app/Controller/ProfileController.php#L61

> private function getProcessedData() {


Не лучше сразу заполнить объект Student вместо передачи туда-сюда массивов?

> if ($isNew) {


> $student = new Student(...$args);


Очень неудачно так как этот код полагается на то, что переменные в getProcessedData() идут в том де порядке, что и в конструкторе, это нигде не документировано и сломается при первой же правке.

Лучше сделать так:

- обработку GET и POST сделать в одном методе
- алгоритм примерно такой:

Если (юзер залогинен) {
$user = загрузить данные из БД ;
} иначе {
$user = пустой объект;
}

Если (форма отправлена) {
обновить $user значениями из POST;
}

...

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

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

Так, в общем сделано неплохо. Подправить код и будет совсем хорошо.

Не знаю, думал еще предложить тебе сделать тесты, но наверно это будет рановато и может быть их лучше сделать к следующей задаче.
https://github.com/vadimyen/students #515 #1074718

>>1066512


>>1072015

https://github.com/vadimyen/students/blob/master/app/View/index/index.php#L1

> <?php extract($params); ?>


Это лучше наверно было сделать в методе render()

> <a href="/?<?=$pager->getSortingLink('firstName')?>">


Если строго говорить, то тут данные должны тоже экранироваться. Что, если там кавычка или знак &?

https://github.com/vadimyen/students/blob/master/app/View/index/index.php#L31

> <?php if(isset($students)) :


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

https://github.com/vadimyen/students/blob/master/app/View/profile/index.php#L4
Вот этот use тут - плохо. Надо хотя бы переместить его в самый верх файла.

> echo "<li>{$value}</li>";


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

> required=""


Можно просто required

> value="<?=isset($user) ? html($user->getFirstName()) : ""?>


Вот опять же, isset тут плохо. Лучше создать пустой объект.

https://github.com/vadimyen/students/blob/master/app/Controller/ProfileController.php#L30

> try {


> $this->isSubmitted();


> } catch(SException $e) {


> header('Location: /profile');


> exit();


> }


Вот это странно смотрится, почему метод с названием isSubmitted выбрасывает исключение? Не лучше ли было бы сделать if (!$this->isSubmitAllowed()) ... ? Ну и редиректить молча тоже нехорошо, надо хотя бы в URL код ошибки добавить или страницу ошибки показать.

https://github.com/vadimyen/students/blob/master/app/Controller/ProfileController.php#L61

> private function getProcessedData() {


Не лучше сразу заполнить объект Student вместо передачи туда-сюда массивов?

> if ($isNew) {


> $student = new Student(...$args);


Очень неудачно так как этот код полагается на то, что переменные в getProcessedData() идут в том де порядке, что и в конструкторе, это нигде не документировано и сломается при первой же правке.

Лучше сделать так:

- обработку GET и POST сделать в одном методе
- алгоритм примерно такой:

Если (юзер залогинен) {
$user = загрузить данные из БД ;
} иначе {
$user = пустой объект;
}

Если (форма отправлена) {
обновить $user значениями из POST;
}

...

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

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

Так, в общем сделано неплохо. Подправить код и будет совсем хорошо.

Не знаю, думал еще предложить тебе сделать тесты, но наверно это будет рановато и может быть их лучше сделать к следующей задаче.
#516 #1074848
>>1067944 (OP)
ОП проверь студентов пожалуйста https://github.com/Qevg/Student-list
67 Кб, 800x515
#517 #1074880
>>1067944 (OP)
Привет.
Сверстал макет, понимаю html+css, основы php, отличу get от post, базовые знания ООП, что делать дальше не знаю, в интернетах нет толковых книг по php+sql с хорошими практическими задачками вроде тех которые в ОП посте. Вот по блядскому питону миллиарды книг на торрентах, по парсингу, хуярсингу, графике и проч.
Просмотрел курс Русакова, вполне сносно, вкратце поясняет и дает задачки, в отличии от СПЕЦЫАЛИСТА где за 15 часов поясняют что такое условия иф елсе и циклы.
Вроде как пхп один из самых "хайповых" языков, а путных книг вовсе нет, книг которые дали бы сильную базу от А до Я.
Короче хуй знает что со всеми этими знаниями делать, база есть, идей нет.
Чем занимаюсь сейчас? Читаю книжку по ООП и учу SQL, нахуя? Сам не знаю.
#518 #1074933
>>1074036
То есть, всё же, считывать нажатие на кнопку не контроллером, а js-скриптом - это правильно? Но я тогда не понимаю, как это согласуется с моделью MVC. Не претендует ли скрипт на роль второго контроллера?
ОМГ, что у тебя за каша в голове? Тебе надо подучить матчасть. Контроллер ничего не считывает, он принимает запрос от клиента и ему пофиг каким образом этот запрос на стороне клиента был сформирован, через жс, напрямую формой в браузере отправлено либо через какой-нибудь Postman вручную созданный запрос. Его задача принять запрос и обработать его - все. Бэкенд никак твой фронтэнд не считывает и ему по большому счету плевать, что у тебя на фронте (ну, если только это не какой-нибудь говно-мутант типа C# WebForm, но оно тебе не надо). Модель MVC это вообще про другое. Скрипт может быть контроллером, т.к. во фронтенде тоже можно реализовать тот же MVC - гугли про фронт энд фреймворки.
Но перед этим сначала возьми и перечитай книги по пыхе заново, чтобы базовые знания в мозгах появились. Пока их там нет, отсюда и все твои проблемы с непониманием того как надо и как не надо.
#519 #1075042
>>1074880
На кодеварс есть сложные задачи по всем языкам.
#520 #1075151
[a-z](0-9){3}[a-z]

Рег. выражение на проверку авт. номеров верное?
На regex101 оно никак не выделяет примеры.
#521 #1075159
https://ideone.com/55JMiq

Чего неверно?
#522 #1075168
>>1075159
как-то много условий есть же if-elseif-elseif....else
#523 #1075173
>>1075159
пофиксил скобочку на квадратную у тебя в регулярках и все сработало
https://ideone.com/I7zfCZ

мимо>>1075168 который сам в регулярках запутался немного
#524 #1075174
Пацаны расскажите про функции в ЖС, которые используют в сортировке.
Типа arr = ["хуе","моё","залупа","якорь"];
function fn(a,b){
return a-b;
}
arr.sort(fn());
залупа,моё,хуе, якорь
Как оно сортирует? Расскажите пожалуйста.
#525 #1075185
>>1075173
Спасибо.

Однако на https://regex101.com/ всё ранво не выделяет.
#526 #1075192
Кто-то пользовался amazon s3? Расценки я видел, но не особо представляю сколько денег за месяц может уйти. Расскажите про подводные камни тоже. К примеру если мне надо будет сменить IP - будут ли сложности?
#527 #1075195
>>1075185
посмотрел твои ифы. это можно сделать через подборку элементов массива с помощью команды foreach. Быстренько написал, но должно быть понятно. https://ideone.com/NIcPaE.

>не выделяет


Вроде работает, но я сам этим сайтом не пользуюсь пока поэтому весь функционал не знаю: https://regex101.com/r/oHw9aW/1
#528 #1075197
>>1075195

>https://ideone.com/NIcPaE


Там точка лишняя в конце.
#529 #1075214
Не могу понять как задать регулярку выбора или +7 ( и семь и плюс идут вместе) или только 8. Может кто-то подсказать? Спасибо!
111 Кб, 648x864
#530 #1075232
ОП! Хочу выразить огромную благодарность тебе за старания, железную выдержку и терпеливое отношение к новичкам! Устроился без опыта работы с дропнутой вышкой джуном на 700$ в мухосрани, сейчас 20 лет, помню как начинал в 18 знакомиться с программированием по твоим анимешным урокам, помню радость от первого работающего скрипта с "искусcтвенным интеллектом", бросающим кубик (отсюда и ник на гитхабе), помню как несколько дней ломал голову над циклами и задачей про рост анона. С тех пор прорешал кучу задачек в треде, сейчас работаю с Symfony/Laravel (уже третий месяц).
Самыми полезными я считаю ревью ООП задач. Интересно, что тут много анонов несправедливо считают все эти задачи абстрактными и оторванными от реальности. А я решал их все + скидки и калькулятор с поддержкой чисел произвольной длины и скажу следующее: советы ОПа научили меня прагматичному и осторожному подходу к выделению абстракций, избавили от догматизма в отношении паттернов (теперь для меня паттерн - это прежде всего идея, а не диаграмма классов). Юнит-тесты помогли лучше понять DI и инкапсуляцию. Думаю, эти концепции более масштабируемы и универсальны, чем любые фреймворки. Этот фундамент позволяет сейчас без особого труда читать исходники фреймворков. Очень жизненными оказались задачи на SQL и JS.
Так что ОП учит правильными вещам за что ему ещё раз большое спасибо!
#531 #1075251
>>1075232
Я думаю если ты будешь сюда заходить и помогать начинающим это будет лучшим спасибом.
#532 #1075260
>>1075174

Функция-компаратор передается для того, чтобы делать сортировку по произвольным правилам. эта функция получает на вход 2 каких-то элемента из массива и должна решить, какой из них "больше" (должен быть в конце), а какой "меньше" (должен идти в начале). Она должна вернуть 0, если элементы равны, отрицательное число если a < b (a идет раньше b) и положительное, если наоборот.

function (a, b) { return a - b; } сравнивает 2 числа. Твой пример неправльный так как у тебя строки и их нельзя вычитать (точнее нет смысла). То есть исправь код для начала.

https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
#533 #1075262
>>1075174

Ну и ты написал sort(fn()) то есть в sort передается не функция, а undefined и соответственно идет обычная сортировка без функции-компаратора. У тебя там в каждой строчке ошибка. Надо не бездумно копировать код, или писать "по интуиции" а читать мануал и понимать что каждый символ значит.

Я бы очень хотел, чтобы тех, кто пишет "по интуиции" даже на собеседование не звали. Такие в отрасли нам не нужны.
#534 #1075270
Привет анон, нужна помощь с библиотекой PHPExcel, а именно сохранение xlsx файла с активированным параметром R1C1, который цифровой формат столбцов A, B, C, D... преобразует в числовой 1, 2, 3, 4...
Беда в том что необходимо включать опцию R1C1 в настройках Excel
https://i.gyazo.com/7c14ef13405d8a56a5337a72fafd630b.png
https://i.gyazo.com/30b8c8f94e101c7d04f9da59b744437e.png
Есть ли вариант сделать для совсем отсталых пользователей сохранение excel файла с уже активным данным параметром и представления столбцов в числовом виде?
#535 #1075272
>>1075270

А зачем требуется сохранять именно в таком формате? Не понимаю.
#536 #1075277
>>1075272
Потому что клиент использует модуль импорта excel файла и он настроен так что числовой формат столбцов считывает, а с буквами - нет... В общем нужно как то настроить выгрузку без указаний лишних указаний типа - а сделайте так, а включите это...
#537 #1075284
>>1075277

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

Может конечно ссылки и можно конвертировать в PHP, но это будет сложно, нужно анализировать формулы...
#538 #1075369
>>1075262
Я не заметил просто что скобочки указал в передаваемом аргументе-функции, я просто хотел, чтобы мне объяснили как оно работает. Просто такая функция указывается для сортировки числовых значений например. Я понимаю если бы в функции возвращался один из входящих аргументов после сравнения. Я не понимаю как возвращаемая разность может сортировать.
#539 #1075378
>>1075369
https://learn.javascript.ru/array-methods#сортировка-метод-sort-fn

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

>>1075214
\+7|8

Тут нужно экранировать +, так как это спецсимвол: https://regex101.com/r/1hHXt8/1
#540 #1075384
Есть ли смысл дрочить хтмл и цсс до уровня "перерисовать сайт с пдс/картинки"?
#541 #1075428
>>1070462
Микрофреймворк - у ОПа есть задачка для него на файлообменник. Когда с ним разберешься - тебе многое станет более ясным когда начнешь с какими-то жирными фреймворками разбираться, как раз познакомишься с psr
#542 #1075446
>>1075378
Спасибо огромное!
#543 #1075450
В Юи можно как-то без обмаза расширениями по быстрому сделать превьюшки для изображений?
#544 #1075570
>>1075369

a - b возвращает:

число < 0 если a < b
0 если a = b
число > 0 если a > b

То есть a - b по сути сравнивает, какое число больше.
#545 #1075571
>>1075369

Функция не должна возвращать аргуименты, а должна их сравнивать и вернуть, какой из них должен идти раньше. Она возвращает не аргумент, а ноль, отрицательное или положительное число.
someApprentice #546 #1075611
Сегодня у меня была целая головная боль с получением доступа к mysql без sudo в Debian stretch.

Мне снова повезло, и я решил проблему выполнив:

UPDATE mysql.user SET plugin='' WHERE User='root';
FLUSH PRIVILEGES;

https://zalinux.ru/?p=1135

Но что за плагин(ы) я, так бездумно, отключил?

И как бы было "правильнее" решить эту проблему?
#547 #1075612
>>1075571
Ого вот она как все просто оказалось! Почему-то в мануале про это не пишут. Спасибо анон! Наконец-то понятно стало.
someApprentice #548 #1075613
Лучше мне следует перестать бездумно задавать вопросы, которые я должен решить сам.
#549 #1075614
>>1075571
Хотя пишут. Просто я думал это частный случай.
#550 #1075747
Есть тут кто с ДС2? Предлагаю сегодня (воскресение) в 18:00 сходку. Я приду. Цели: поболтать, обменяться опытом, может даже покодить вместе. Я буду раду любому, кто придет. Информация о месте встречи в телеграм канале: https://t.me/phpspb
Добавляйтесь!
#551 #1075843
>>1075747
Я бы пошел, но ни опыта, ни знаний нету. Идея хорошая, но думаю нужно писать о ней за пару дней до. Удачи!
#552 #1075880
>>1075843
Это нормально. У меня тоже нет опыта и знаний почти нет. Но я предлагаю встретиться всем, независимо от уровня знаний. Приходи, не сегодня, так в следующий раз.
#553 #1075976
>>1075880
Тебе в сюда https://2ch.hk/soc/ (М)
#554 #1076081
Заметил одну странность в пхп. Вот есть функции is_dir и mkdir - почему они названы в разных стилях? Логичней вообще делать или с подчеркиванием, или кеймел кейс вроде как. Чисто интересно откуда такая странность на уроне стандартных функций.
#555 #1076179
>>1076081
Это одна из самых больших проблем PHP, потому что язык изначально предназначался для простых задач и писали его как попало. Были предложения привести стандартные функции к единому виду, но сейчас всё глухо: https://wiki.php.net/rfc/consistent_function_names

Но проблема исправляется сторонними пакетами. Советую для простых задач использовать symfony/filesystem, который не умалчивает ошибки, а бросает исключения: https://github.com/symfony/filesystem/blob/master/Filesystem.php#L92+L110
#556 #1076235
Поясните за предопределенный stdClass. Понятно, что его объект возникает, когда массив в объект переводят, но зачем и при каких ситуация это нужно?
#557 #1076286
>>1076235

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

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

В stdClass нет ни полей, ни методов, и на мой взгляд, это больше похоже на массив, чем на объект. Только на неполноценный массив, так как функции вроде array_keys с ним не работают.
#558 #1076338
>>1074717

>Тут можно было использовать ENUM 'male', 'female', а в коде для пола прописать константы.


>Сначала так и хотел, но почитав всякие stackoverflow отчего-то передумал (точно не помню, так как начал делать очень давно, но всякие сессии, дипломы, военкоматы оторвали меня от пыхи)



>echo "<b>Искоючение:</b> ", $exception->__toString();


>Это хорошо бы отключать на продакшене - например, используя ini-параметр display_errors.


То есть тут лучше вообще эту строку убрать и сделать заголовки на ошибку сервера, помимо display_erorrs?

>Далее, ты используешь PHP7, значит используй его возможности и ставь тайп-хинты на string/int/bool, а также тайп-хинты для возвращаемых значений. Это документирует твой код и защищает от ошибок.


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



>https://github.com/vadimyen/students/blob/master/app/Mapper/StudentMapper.php#L70


>Тут нет проверки переменных $field, $direction, получается SQL инъекция.


bindValue для 'order by :field :direction' не работает. У меня это проверяется в Pagere'е, хотя, согласен, странно это, лучше в контроллере валидацию делать, у тебя это справедливо замечено. С другой стороны, если пагинатор нужен на нескольких страницах, то неудобно каждый раз валидацию в контроллерах дублировать (хоть и мало кода там), а в классе самого пагинатора очень даже удобно (можно просто передать нужные моля и все-такое), но опять-таки потом обратно для маппера вытаскивать отвалидированные значения – что-то не то.

>В контейнер обычно кладут объекты без состояния, которые можно смело выдать нескольким потребителям и с которыми ничего не случится. Объект Security у тебя имеет состояние, а значит, он должен каждый раз создаваться заново через new либо при выдаче из контейнера (в Pimple такое возможно, смотри factory).


Состояние в данном случае – это имитация stateful за счет куки и объект будто бы живет на протяжении многих запросов или имеется в виду наличие важных полей?

>public function logout(Student $student)


>Справедливости ради, для разлогинивания студент в принципе не нужен


>А разве в бд не надо очищать поле с кукой. Насчет куки еще: ее не надо как-то хешировать? Просто если взломать бд, то там будет кука лежать, любую вставляй себе в браузер да используй, в отличие от ситуации с password_hash/password_verify.



>PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, Student::class, array_fill(0, 8, null)


>Ага, вот ты и понял, что PDO не очень удобен для заполнения объектов.


А какая есть альтернатива, ну кроме Doctrine и других библиотек (они же вроде тоже поверх PDO)?

>https://github.com/vadimyen/students/blob/master/app/Entity/Student.php#L24


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


Согласен (благо phpstorm помогает с параметрами), а какая альтернатива, сеттеры в отдельности? А с массивом как, передать ассоциативный массив и в конструкторе его проитерировать и присвоить каждому свойству класса значения соответствующего ключа?

>>1074718

>https://github.com/vadimyen/students/blob/master/app/View/index/index.php#L31


<?php if(isset($students)) :

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


То есть тут по смыслу не подходит? Лучше !is_null? Я это писал в расчетом на то, если еще ни один студент не зарегистрировался

>Вот этот use тут - плохо. Надо хотя бы переместить его в самый верх файла.


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

>Вот опять же, isset тут плохо. Лучше создать пустой объект.


Как создать пустой объект? Убрать все тот же конструктор, ну или значение дефолтные null прописать (не особо надежно и удобно).

>Вот это странно смотрится, почему метод с названием isSubmitted выбрасывает исключение? Не лучше ли было бы сделать if (!$this->isSubmitAllowed()) ... ? Ну и редиректить молча тоже нехорошо, надо хотя бы в URL код ошибки добавить или страницу ошибки показать.


Согласен, но а если метод переименовать, ну типа checkForm. Просто я думал, что подделка формы – это исключительная ситуация, а так да по названию не подходит, с редиректом тоже согласен, то есть шлю заголовок с кодом 500?

С остальным согласен вроде без вопросов.

Спасибо большое, многое уже переделал после твоего обзора. Спрашиваю, чтобы лучше понять и больше уяснить. Зандстру пока только половину осилил, к сожалению, очень скучно идет, хоть всё и толково, в отличие от серии You Don't Know JS, даже на английском, ее тут всем рекомендую.
#558 #1076338
>>1074717

>Тут можно было использовать ENUM 'male', 'female', а в коде для пола прописать константы.


>Сначала так и хотел, но почитав всякие stackoverflow отчего-то передумал (точно не помню, так как начал делать очень давно, но всякие сессии, дипломы, военкоматы оторвали меня от пыхи)



>echo "<b>Искоючение:</b> ", $exception->__toString();


>Это хорошо бы отключать на продакшене - например, используя ini-параметр display_errors.


То есть тут лучше вообще эту строку убрать и сделать заголовки на ошибку сервера, помимо display_erorrs?

>Далее, ты используешь PHP7, значит используй его возможности и ставь тайп-хинты на string/int/bool, а также тайп-хинты для возвращаемых значений. Это документирует твой код и защищает от ошибок.


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



>https://github.com/vadimyen/students/blob/master/app/Mapper/StudentMapper.php#L70


>Тут нет проверки переменных $field, $direction, получается SQL инъекция.


bindValue для 'order by :field :direction' не работает. У меня это проверяется в Pagere'е, хотя, согласен, странно это, лучше в контроллере валидацию делать, у тебя это справедливо замечено. С другой стороны, если пагинатор нужен на нескольких страницах, то неудобно каждый раз валидацию в контроллерах дублировать (хоть и мало кода там), а в классе самого пагинатора очень даже удобно (можно просто передать нужные моля и все-такое), но опять-таки потом обратно для маппера вытаскивать отвалидированные значения – что-то не то.

>В контейнер обычно кладут объекты без состояния, которые можно смело выдать нескольким потребителям и с которыми ничего не случится. Объект Security у тебя имеет состояние, а значит, он должен каждый раз создаваться заново через new либо при выдаче из контейнера (в Pimple такое возможно, смотри factory).


Состояние в данном случае – это имитация stateful за счет куки и объект будто бы живет на протяжении многих запросов или имеется в виду наличие важных полей?

>public function logout(Student $student)


>Справедливости ради, для разлогинивания студент в принципе не нужен


>А разве в бд не надо очищать поле с кукой. Насчет куки еще: ее не надо как-то хешировать? Просто если взломать бд, то там будет кука лежать, любую вставляй себе в браузер да используй, в отличие от ситуации с password_hash/password_verify.



>PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, Student::class, array_fill(0, 8, null)


>Ага, вот ты и понял, что PDO не очень удобен для заполнения объектов.


А какая есть альтернатива, ну кроме Doctrine и других библиотек (они же вроде тоже поверх PDO)?

>https://github.com/vadimyen/students/blob/master/app/Entity/Student.php#L24


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


Согласен (благо phpstorm помогает с параметрами), а какая альтернатива, сеттеры в отдельности? А с массивом как, передать ассоциативный массив и в конструкторе его проитерировать и присвоить каждому свойству класса значения соответствующего ключа?

>>1074718

>https://github.com/vadimyen/students/blob/master/app/View/index/index.php#L31


<?php if(isset($students)) :

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


То есть тут по смыслу не подходит? Лучше !is_null? Я это писал в расчетом на то, если еще ни один студент не зарегистрировался

>Вот этот use тут - плохо. Надо хотя бы переместить его в самый верх файла.


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

>Вот опять же, isset тут плохо. Лучше создать пустой объект.


Как создать пустой объект? Убрать все тот же конструктор, ну или значение дефолтные null прописать (не особо надежно и удобно).

>Вот это странно смотрится, почему метод с названием isSubmitted выбрасывает исключение? Не лучше ли было бы сделать if (!$this->isSubmitAllowed()) ... ? Ну и редиректить молча тоже нехорошо, надо хотя бы в URL код ошибки добавить или страницу ошибки показать.


Согласен, но а если метод переименовать, ну типа checkForm. Просто я думал, что подделка формы – это исключительная ситуация, а так да по названию не подходит, с редиректом тоже согласен, то есть шлю заголовок с кодом 500?

С остальным согласен вроде без вопросов.

Спасибо большое, многое уже переделал после твоего обзора. Спрашиваю, чтобы лучше понять и больше уяснить. Зандстру пока только половину осилил, к сожалению, очень скучно идет, хоть всё и толково, в отличие от серии You Don't Know JS, даже на английском, ее тут всем рекомендую.
#559 #1076340
>>1076338
С разметкой облажался чуток
#560 #1076473
>>1067944 (OP)
ОП еще тут? Что скажешь об этом треде:
>>1075881 (OP)
Пхп может как-то объективно заменить баш/питон/Windows Script Host в качестве основного языка написания сценариев автоматизации, задачек для крона по обслуживанию системы (например, синхронизации, бэкапы, рассылки, скачивание всяких обнов), задания для пакетной обработки (имейджмэджиком или ффмпегом, например)? Как у пхп с многопоточностью, распараллеливанием выполнения, обменом данными между потоками, объединением, как с интерактивом...?
Джунам #561 #1076476
Хочу предупредить об одном небольшом заблуждений (Если у кого они есть по этому поводу) на счет спецификацииCSS 2.1 ее читать не стоит, там куча ошибок которые могут отразиться на вашей работе, да там много поддерживаемых до сих пор элементов, но это версия 2011 года.
Для нас существует CSS3 версия, но она на бета-тесте, хоть и многие браузеры постепенно поддерживают ее характеристики, она не идеальна для обычного использования.
Читайте вот это - https://www.w3.org/TR/CSS22/
Это версия CSS 2.2, можно сказать текущий стандарт (Т.е поддерживается она даже на IE6-9)
Однако чтобы не путаться читаем это: https://www.w3.org/TR/css-2017/ тут описана последняя принятая версия и все все все.

Это относится к новичкам, я так сказать предотвращаю заблуждения.
#562 #1076484
>>1076476

Тебе стоило бы еще дополнить, что формально стандарт CSS3 - это набор дополнений (модулей) к CSS2.2 (раньше было к CSS2.1). Ну например, там есть Selectors Level 3, CSS Color Level 3 и так далее.

Но CSS2 все равно остается как основа.

Также, тебе стоило бы дать ссылку на список изменений в CSS2.2 относительно CSS2.1 - https://www.w3.org/TR/CSS22/changes.html

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

> Это версия CSS 2.2, можно сказать текущий стандарт (Т.е поддерживается она даже на IE6-9)



Ну это уже неправда. Как она может поддерживаться на ИЕ6 если он выпущен много лет назад? Не вводи людей в заблуждение, старые браузеры поддерживают CSS2.1 (точнее должны поддерживать).
#563 #1076487
>>1076484
Я ниже написал:

>Однако чтобы не путаться читаем это: https://www.w3.org/TR/css-2017/ тут описана последняя принятая версия и все все все.


Я думаю человек пройдя к снэпшоту (В котором с нуля написано обо всем и даются источники) все это поймет и увидит.
По идее 2.2 > 2.1 > 2 > 1 т.е спецификация включает в себя предупреждения в которых описано где этот стандарт имеет свое начало(Т.е ссылки там дают) и я думаю каждый с этим ознакомится когда дойдет дело. В модуле 2.2 есть все принятые положения с прошлых уровней, только исправленные или дополненные, либо же переформулированные положения элементов. Так же уровень 3 содержит в себе источник на 2.2. Сложно назвать CSS2 основой, т.к не зря же создается 2.2 ? Эти принципы действуют в старых версиях к которым не прикасались.
Но да с IE6 я погорячился
#564 #1076488
>>1076484
А да, при открытий страницы вот что происходит - This specification defines Cascading Style Sheets level 2.
Т.е как бы понятно, что 2 это 2.2, только "Revision" т.е пересмотренная версия.
#565 #1076492
>>1076487

Насчет версий:

CSS2.0 - это устаревшая версия, которая была актуальна еще до IE6 (то есть ранее 2000-2002 года). Она неактуальна. Если интересно, IE6 и IE7, которые должны бы были использовать CSS2.1, местами используют CSS2.0, но это уже неактуальная информация, так как никто под эти браузеры не верстает.

CSS2.1 - эта версия использовалась где-то с 2003 года.

CSS2.2 - это современная немного доработанная CSS2.1. Отличия очень небольшие и перечислены тут https://www.w3.org/TR/CSS22/changes.html .

CSS3, 4 - он сделан в виде отдельных модулей, которые работают поверх CSS2.2.

В Вики даже есть картинка: https://en.wikipedia.org/wiki/File:CSS3_taxonomy_and_status-v2.png
#566 #1076495
>>1076492

>CSS2.1 - эта версия использовалась где-то с 2003 года.


"Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification", B. Bos, T. Çelik, I. Hickson, H. W. Lie, 7 June 2011
Т.е 2.1 версия разрабатывалась давно еще с 2003 года по 2011?
В спецификации говорят, что мол, никаких 3, 4, 5, 6 уровней не существует, мол это как ты сказал модули.
#567 #1076498
>>1076495

В википедии написано: https://en.wikipedia.org/wiki/Cascading_Style_Sheets#CSS_2.1

> To comply with the W3C Process for standardizing technical specifications, CSS 2.1 went back and forth between Working Draft status and Candidate Recommendation status for many years. CSS 2.1 first became a Candidate Recommendation on February 25, 2004, but it was reverted to a Working Draft on June 13, 2005 for further review. It returned to Candidate Recommendation on 19 July 2007 and then updated twice in 2009. However, because changes and clarifications were made, it again went back to Last Call Working Draft on 7 December 2010.



> CSS 2.1 went to Proposed Recommendation on 12 April 2011.[40] After being reviewed by the W3C Advisory Committee, it was finally published as a W3C Recommendation on 7 June 2011



Вот так вот, ее окончательно приняли как рекомендацию уже когда начал появляться CSS3. Веб, он такой, фичи реализуют не дожидаясь стандартов.
#568 #1076501
>>1076498
Все же я думаю нужно отталкиваться от 2.2 держа в уме основу.
253 Кб, 630x386
#569 #1076541
А мы напоминаем, что Оп и все помогаторы - няши, добра им
#570 #1076548
Интересная статья на Хабре про управление UI тестированием в tutu.ru: https://m.habrahabr.ru/company/tuturu/blog/339882/
#571 #1076569
>>1076541
Чот подумал и проиграл, мол если бы ОП это постил.
#572 #1076641
>>1076541
>>1076569
Я подумал, что неплохо было бы запихивать в эту штуку члены вместе с двумя друзьями, касаясь ими изнутри (не друзьями). Жалко, у меня нет таких друзей (и вообще никаких друзей).
#573 #1076716
>>1076641

>Жалко, у меня нет таких друзей


ну и правильно, вдруг среди них будут геи какие-нибудь?
#574 #1076901
>>1076716
Кошмар какой! Даже подумать о таком страшно. Ты прав.
#575 #1077020
>>1067944 (OP)
Няша, еще один вопрос, если позволишь. У тебя случайно нет урока или какого-нибудь чужого гайда под рукой по интенсивному изучению (#quick_start, #обучение_через_использование) imagemagick (imagick) и ffmpeg? Особенно в связке с PHP. Официальная документация очень большая, написана сложным техническим английским, слишком много теории, слишком мало примеров и практики, воды много, при этом ненаглядно и слишком много говна приходится гуглить, а хочется наоборот (что-то вроде howtogit только howtoimagick и howtoffmpeg ну или ffmpegtherightway, если хотите).
https://theknacker.github.io/Webpaint/webpaint.html #576 #1077031
Оп проверь. Я пока другим занят, но там переделал как ты сказал.
Занимаюсь пока выучкой CSS, ну там практикую элементы, проверяю свойства.
#577 #1077033
>>1077031
Кстати ОП, даже на IE6 отображается годно, не думал что форматирование так может улучшить. Но конечно же критика на тебе.
#578 #1077065
>>1076548
Хотел спросить зачем делать тесты - прочитал урок codedokode, и сразу все вопросы отпали.
#579 #1077066
Программошки, тупой вопрос, понимаю, просто никогда не озадумывался, а тут вдруг прокрутил в головушке и замер:
как можно проверить чисто на компьютере мобильную верстку? Уменьшать окно браузера до нужных величин? Но метатеги сайта все равно будут знать что это компьютер, правильно? Может, есть какой-нибудь ресурс, куда урл сайта грузишь, а он тебе предлагает три кнопки: показать на таком мобильном разрешении, на таком или на айподе? Или может в браузере есть такой функционал?
#580 #1077069
>>1077066
Когда уменьшаешь ширину окна эффект одинаков.
#581 #1077070
>>1077066

>как можно проверить чисто на компьютере мобильную верстку?


В хроме и мозилле открыть Инструменты разработчика (Ctrl + Shift + I / F12) и Режим адаптивного дизайна (Ctrl + Shift + M).

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


О каких метатегах ты говоришь, напомни?
#582 #1077072
>>1077070
>>1077069
Спасибо, няши. Я говорю про что-нибудь типа viewport, ему есть разница от того, с какого устройства его запустили, или он просто с размерами окна работает, независимо от устройства?
#583 #1077074
>>1077066

>чисто на компьютере мобильную верстку?


Если прям на серьёзных щах, то только через виртуальную машину, на которой будет эмулятор этого устройства. Что-то вроде того, как мобильные разрабы свои программы для андроидов/айфонов пишут. Написали, скомпилировали - и в эмулятор и сидят ждут, пока прогрузится.
#584 #1077075
>>1077072

>Я говорю про что-нибудь типа viewport, ему есть разница от того, с какого устройства его запустили, или он просто с размерами окна работает, независимо от устройства?


Конкретно у viewport похоже что - да.

Сравни в режиме адаптивного дизайна примеры на w3c: https://www.w3schools.com/css/css_rwd_viewport.asp
#585 #1077077
>>1077075
w3schoold не является конгрессом или частью W3C, не путай людей.
#586 #1077080
>>1077072
Чтобы больше вопросов не было читай: https://www.w3.org/TR/CSS22/visuren.html
Если не умеешь в англ. то вот суть: viewport это окно агента пользователя (Браузера) и работает относительно любого типа экрана, либо того, который тип это правило определит. Ширина браузера + высота (Окна) и есть viewport.
#587 #1077082
>>1077066
>>1077074

>Может, есть какой-нибудь ресурс, куда урл сайта грузишь, а он тебе предлагает три кнопки: показать на таком мобильном разрешении, на таком или на айподе?


Да, есть такой сервис https://www.browserstack.com/screenshots
Только долго им не попользуешься, он становиться платным
#588 #1077085
>>1077074
>>1077075
>>1077077
>>1077080
>>1077082
Спасибо, добра вам
#589 #1077140
Посоны, как запустить в PHP подпрограмму в отдельном потоке, который бы не блокировал работу основной программы? Результат из этой подпрограммы возвращать не нужно. Просто запускаем, а на результат тащемта похуй (там обращение к стороннему api, куда нужно записать некоторые некритичные данные). Возможности установить экстеншены php на этом сервере у меня нет. Также не хотелось бы тянуть для этого большие библиотеки, типа Guzzle. Есть предустановленный curl. Но хотелось бы как можно проще и нативней.
75 Кб, 1440x900
#590 #1077196
Пытаюсь настроит роутинг в yii2. Пишу вот такой код в config/web.php:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
'test' => 'site/test',
],
Проблема в том, что если я что-о добавляю в rules - всегда вылазит пикрилейтед, если не пишу то все работает. Что вообще происходит? Я так понял он какой-то файл найти не может, как пофиксить эту ошибку?
#591 #1077209
Хелперы могут к супер глобальным переменным обращаться в MVC?
#592 #1077241
>>1077196
Кэш почисти
#593 #1077242
>>1077209
Типа $_SERVER?
Они доступны из любого места в пхп.
#594 #1077249
>>1077242

Ты имеешь ввиду технически или именно в рамках парадигмы MVC?
#595 #1077250
>>1077209
Суперглобалы это специфичное для PHP штуки, а MVC это универсальная концепция, которая не привязана к какому-то конкретному языку и его особенностям. Даже консольное приложение может быть в MVC. View отрисовывается с помощью ASCII, Controller работает с пользовательским вводом в консоль, а модель остаётся неизменной как для консольного приложения, так и для веб-приложения.

> Хелперы могут к супер глобальным переменным обращаться в MVC?


Обращение к глобальным переменным это всегда плохо: https://github.com/codedokode/pasta/blob/master/arch/di.md#Чем-плохи-глобальные-переменные/

Фреймворки предоставляют готовые абстракции для суперглобалов: https://symfony.com/doc/current/components/http_foundation.html и лучше передавать эти объекты как зависимости хелперу. Пример:
class DownloadHelper
{
public function addDownloadHeaders(Request $request): void
{
if (сервер === апач) {
выставить одни заголовки;
} else if (сервер === nginx) {
выставить другие заголовки;
}
...
}
}

>>1077140
Гугли "очереди сообщений php".

>>1077249
Он имеет в виду технически.
#596 #1077257
>>1077241 Кэш Юи? Но там пусто. Кэш хрома почистил, все тоже самое.
#597 #1077263
>>1077140

> Также не хотелось бы тянуть для этого большие библиотеки, типа Guzzle. Есть предустановленный curl. Но хотелось бы как можно проще и нативней.



Нативней != проще, а скорее наоборот. Проще использовать готовую абстракцию с объектным интерфейсом, умеющую бросать исключения, а не запоминать кучу флагов для curl_ функций. И ты сравнивал Guzzle и curl-функции по скорости? Я сравнивал и Guzzle не уступал голому curl'у. Ещё Guzzle следует PSR7, а это стандарт, к которому постепенно переходят все популярные фреймворки:
http://symfony.com/blog/psr-7-support-in-symfony-is-here
https://habrahabr.ru/post/304584/
#598 #1077530
>>1075384

>до уровня


Это же единственный уровень какие еще есть?
12 Кб, 236x236
#599 #1077533
Короче. Завел телеграмм и был бы не против иметь в контакт листе друзей по теме. Что-то обсудить/помочь/спросить и т.д.

Если кто заинтересован, стучите: adikalon

О себе: 27 лвл. Сейчас разбираю laravel, пытаюсь во фриланс, также знаком с JS и версткой. Если кто-то батрачит на фрилансе, хотел бы услышать советов и напутствий от бывалых
#600 #1077721
Сука, как же меня злит этот Yii2. Вот что я такого мог с ним сделать, что у меня не работают примеры из документации? Вот буквально, пытаюсь вставить картинку, даже копипащу код:
<?= Html::img('@web/images/logo.png', ['alt' => 'My logo']) ?>
В документации пишется, что должно быть <img src="http://example.com/images/logo.png" alt="My logo" />, у мня выходит <img src="images/logo.png" alt="My logo" /> - какого хуя?
#601 #1077754
ОП сдох? :с
#603 #1077876
>>1077721
У тебя алиас для @web скорее всего не задан. И я не уверен, что @web в методе img должен парситься, для получения алиаса есть специальный геттер, загугли.

Но зачем тебе вообще часть с http://example.com? Задай относительную ссылку, /images/logo.png
#604 #1077903
Что такое current и зачем он нужен? В мануале про какой-то "внутренний указатель" пишется.
#605 #1077933
Что лучше использовать, while или for?
#606 #1077953
Блэд, у меня из-за нехватки знаний бомбит от пхп. Ну вот создал я класс например, ебанул туда переменных и методов функций методов под ключевым словом функция. Но это неважно. У меня первый принт печатается, а второй принт не печатается, как я понял то в методе принтСтудент не находит или заданный индекс или еще какую-то поеботу, но я ведь специально создал объект студент, который по идее должен хранить измененный после первого метода массив, и печатать его во втором методе. ухх сука пошел я спать короче
#607 #1077959
#608 #1077977
>>1077953

Чтобы обращаться к полям объекта, нужно использовать this, например

$this->x = 100;

Также, у тебя не ООП, а массиво-ориентированное программирование. Чтобы был ООП, нужно сделать класс Student представляющий 1 студента с полями вроде name, lastName, и тд. А затем уже класс StudentList который хранит список объектов Student внутри.

Если что, все это описано у меня в учебнике (в ОП посте) в главе по ООП. Попробуй ее прочесть, если не читал.

И писать нужно public function, а не function.
#609 #1077993
>>1077754
Занят, перезвони попозже.
#610 #1078010
Анон, подскажи, функция readfile("text.txt") возвращает знаки вопроса вместо русских букв. Другой текст или переменные выводятся нормально. В чем может быть косяк?
#611 #1078085
>>1078010
В кодировке. Файл с данными в одной кодировке, файл со скриптом в другой. Браузер - или куда ты там выводишь текст - неверно определяет кодировку.
3 Кб, 404x154
#612 #1078087
>>1077250

>Гугли "очереди сообщений php".


Ну как-то негусто. Ничего подходящего моей просьбе там нет.
#613 #1078095
>>1077903

>Что такое current и зачем он нужен? В мануале про какой-то "внутренний указатель" пишется.


Там пример есть. Если кратко ответить, то это текущий элемент итерации в цикле.

>>1077933
while нужен чтобы выполнять цикл, когда передаваемый аргумент истинен, а for чтобы выполнить цикл определённое количество раз. Более или менее.

Ознакомься с мануалом и сравни эти функции:
https://secure.php.net/manual/ru/control-structures.for.php
https://secure.php.net/manual/ru/control-structures.while.php
#614 #1078108
>>1078085
Точно, поменял кодировку в txt-шнике и все заработало, спасибо!
#615 #1078205
>>1078087
Кавычки убери, дебил.
#616 #1078464
Может у кого-то есть задачки на рекурсию, обход дерева? Только не совсем сложные, я только начинаю эту тему разбирать.
#617 #1078636
>>1078464

1) Дан список категорий товаров в виде такого массива:

$categories = [
// id, название, parentId, кол-во товаров
[1, 'Бытовая техника', null, 0],
[2, 'Телевизоры', 1, 0],
[3, 'LCD-телевизоры', 2, 20],
[4, 'Телевизоры с газоразрядным дисплеем', 16],
[5, 'Стиральные машины', 1, 0],
[6, 'Холодильники', 1, 0],
...
];

Для каждого товара указан уникальный id категории, название, id родительской категории или null, если ее нет, количество товаров в этой категории без учета категорий-детей. Используя эти данные:

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

Например, для категории 3 вернет массив [1, 2, 3] (Бытовая техника -> Телевизоры -> LCD-телевизоры). А для 1 - массив [1].

б) Напиши функцию, которая для любой категории вернет массив id ее потомков. Например для id = 2 функция должна вернуть массив [3, 4]

в) Напиши функцию, которая вернет массив категорий-сестер (то есть категорий, имеющих того же родителя). Для id = 2 функция должна вернуть массив [5, 6]

г) Напиши функцию, которая выведет список категорий в виде дерева "лесенкой", с указанием числа товаров с учетом дочерних категорий:

Бытовая техника (36)
- Телевизоры (36)
-- LCD-телевизоры (20)
-- Телевизоры с газоразрядным дисплеем (16)
Стиральные машины
Холодильники

2) Дан текст с разметкой, который состоит из "обычного текста" (любые символы, кроме знаков < и >) и "тегов" (конструкций вида <name> или </name>). "Тег" состоит из знака "<", необязательного символа "/", имени из латинских букв и знака ">". Тег со слешем называется "закрывающим", а без слеша - "открывающим". Каждому "открывающему" тегу должен соответствовать "закрывающий", при этом между ними может быть "обычный текст" и/или вложенные внутри пары "тегов".

Примеры пар тегов:

<x></x>
<y>Текст</y>
<a>текст<b>текст</b>текст<c>текст</c>текст</a>

Пример текста с разметкой:

<books>
<book>
<title>80 000 миль вокруг света</title>
<author>Жюль Верн</author>
</book>
<book>
<title>Базы данных на языке SQL</title>
<author>Дж. Д. Джонсон</author>
</book>
</books>

Напиши код, который принимает на вход текст с разметкой и преобразует его в дерево из элементов 2 видов:

- "текстовый блок" - соответствует тексту
- "теги". У тега есть имя. Теги внутри могут содержать блоки текста и другие теги

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

Затем напиши код, который выведет это дерево в таком виде:

- books
-- book
--- title
---- Text: 80 000 миль вокруг света
--- author
---- Text: Жюль Верн
--book
--- title
---- Text: Базы данных на языке SQL
--- author
---- Text: Дж. Д. Джонсон

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

/ обозначает корень дерева (не соответствует какому-то элементу)
/books - обозначает элемент с названием books в корне дерева
/books/book - обозначает элемент с названием book, родителем которого является books в корне
/books/book/title - думаю, понятно, ищет элементы title

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

/books/book/title/text() - ищет текстовые блоки внутри элемента title

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

/* - ищет теги с любым именем в корне дерева (в примере выше найдет только books)
/*/* - ищет теги с любым именем, и затем всех их детей (в примере выше найдет все элементы book)

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

Затем язык выражений можно усовершенствовать. Ну например, введем такой синтаксис, как a//b - он будет обозначать, что b является потомком элеимента a, при этом между ними может быть любое число элементов. Например:

/books//title - ищет элементы books в корне дерева, а затем ищет элементы title внутри них на любой глубине вложенности
//title - ищет элементы title в любом месте дерева
//text() - ищет все текстовые блоки в любом месте дерева
//* - ищет все теги на любой глубине (в примере выше найдет все books, book, title, author)
//*/*/* - ищет все теги, на любой глубине, у которых есть родитель и прародитель (в примере выше найдет все title и author)

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

(да, конечно, "текст с разметкой" это упрощенная версия XML, а выражение для поиска - упрощенная версия XPath).
#617 #1078636
>>1078464

1) Дан список категорий товаров в виде такого массива:

$categories = [
// id, название, parentId, кол-во товаров
[1, 'Бытовая техника', null, 0],
[2, 'Телевизоры', 1, 0],
[3, 'LCD-телевизоры', 2, 20],
[4, 'Телевизоры с газоразрядным дисплеем', 16],
[5, 'Стиральные машины', 1, 0],
[6, 'Холодильники', 1, 0],
...
];

Для каждого товара указан уникальный id категории, название, id родительской категории или null, если ее нет, количество товаров в этой категории без учета категорий-детей. Используя эти данные:

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

Например, для категории 3 вернет массив [1, 2, 3] (Бытовая техника -> Телевизоры -> LCD-телевизоры). А для 1 - массив [1].

б) Напиши функцию, которая для любой категории вернет массив id ее потомков. Например для id = 2 функция должна вернуть массив [3, 4]

в) Напиши функцию, которая вернет массив категорий-сестер (то есть категорий, имеющих того же родителя). Для id = 2 функция должна вернуть массив [5, 6]

г) Напиши функцию, которая выведет список категорий в виде дерева "лесенкой", с указанием числа товаров с учетом дочерних категорий:

Бытовая техника (36)
- Телевизоры (36)
-- LCD-телевизоры (20)
-- Телевизоры с газоразрядным дисплеем (16)
Стиральные машины
Холодильники

2) Дан текст с разметкой, который состоит из "обычного текста" (любые символы, кроме знаков < и >) и "тегов" (конструкций вида <name> или </name>). "Тег" состоит из знака "<", необязательного символа "/", имени из латинских букв и знака ">". Тег со слешем называется "закрывающим", а без слеша - "открывающим". Каждому "открывающему" тегу должен соответствовать "закрывающий", при этом между ними может быть "обычный текст" и/или вложенные внутри пары "тегов".

Примеры пар тегов:

<x></x>
<y>Текст</y>
<a>текст<b>текст</b>текст<c>текст</c>текст</a>

Пример текста с разметкой:

<books>
<book>
<title>80 000 миль вокруг света</title>
<author>Жюль Верн</author>
</book>
<book>
<title>Базы данных на языке SQL</title>
<author>Дж. Д. Джонсон</author>
</book>
</books>

Напиши код, который принимает на вход текст с разметкой и преобразует его в дерево из элементов 2 видов:

- "текстовый блок" - соответствует тексту
- "теги". У тега есть имя. Теги внутри могут содержать блоки текста и другие теги

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

Затем напиши код, который выведет это дерево в таком виде:

- books
-- book
--- title
---- Text: 80 000 миль вокруг света
--- author
---- Text: Жюль Верн
--book
--- title
---- Text: Базы данных на языке SQL
--- author
---- Text: Дж. Д. Джонсон

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

/ обозначает корень дерева (не соответствует какому-то элементу)
/books - обозначает элемент с названием books в корне дерева
/books/book - обозначает элемент с названием book, родителем которого является books в корне
/books/book/title - думаю, понятно, ищет элементы title

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

/books/book/title/text() - ищет текстовые блоки внутри элемента title

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

/* - ищет теги с любым именем в корне дерева (в примере выше найдет только books)
/*/* - ищет теги с любым именем, и затем всех их детей (в примере выше найдет все элементы book)

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

Затем язык выражений можно усовершенствовать. Ну например, введем такой синтаксис, как a//b - он будет обозначать, что b является потомком элеимента a, при этом между ними может быть любое число элементов. Например:

/books//title - ищет элементы books в корне дерева, а затем ищет элементы title внутри них на любой глубине вложенности
//title - ищет элементы title в любом месте дерева
//text() - ищет все текстовые блоки в любом месте дерева
//* - ищет все теги на любой глубине (в примере выше найдет все books, book, title, author)
//*/*/* - ищет все теги, на любой глубине, у которых есть родитель и прародитель (в примере выше найдет все title и author)

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

(да, конечно, "текст с разметкой" это упрощенная версия XML, а выражение для поиска - упрощенная версия XPath).
#618 #1078639
>>1077903

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

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

$a = [];
$a[10] = 100;
$a[9] = 20;

Здесь в массиве первый элемент имеет ключ 10, а второй - 9, то есть сохраняется порядок, в котором элементы были добавлены.

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

reset - ставит указатель на первый элемент и возвращает его значение
next/prev - перемещает указатель на следующий/предыдущий элемент
end - пермещает указатель на последний элемент и возвращает его значение
key - возвращает ключ текущего элемента
current - возвращает значение текущего элемента

Подробности в мануале.

Многие операции с массивами неявно сбраывают или передвигают указатель, например, цикл foreach.

Так, они почти никогда не нужны. Иногда они помогают быстро получить первый/последний элемент, не зная его индекса.
60 Кб, 340x707
#619 #1078652
>>1077031

В адаптивной версии в шапке гигансткий текст. Ну то есть лозунг про "digital branding agency" занимает целый экран. Зачем он такой там нужен? Я тебе в третий раз уже наверно напоминаю, что надо подойти к адаптивной версии творчески. То есть, сам лозунг конечно стоит оставить, но уменьшить его до адекватного размера. Также, можно убрать центирование лозунга, оно хорошо смотрится на широком экране, но глупо выглядит на маленькой ширине.

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

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

Далее, надо проверить твой HTML валидатором: https://html5.validator.nu/?doc=https://theknacker.github.io/Webpaint/webpaint.html&showimagereport=yes

Нужно посмотреть, что он там пишет и если есть ошибки, исправить их.

Далее, тут:

> <div class="service_item">


> <img src="images/Computer_iMac.png" width="62px" height="59px"/>


В атрибутах width/height разве можно писать px?

> <title>WebPaint</title>


> <meta charset="utf-8">


Это ошибка, кодировка должна идти ДО любых текстов.

> <a href="https://orss.ru/rss_1.html" target="_blank"><img src="images/rss.svg" width="30" height="30" alt="rss"/></a>


Зачем тут img? Разве нельзя сделать иконку просто фоновой картинкой к ссылке?

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

Также, в CSS неправильно залдан шрифт. Если вставить на страницу текст, то абзацы (p) в нем используют один шрифт, а список (ul/li) использует другой шрифт. Это потому, что у тебя неправильно задан шрифт:

> p {


> font: 14px latoregular, serif;


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

Тут еще нашел странное место:

> table {


> max-width: 500px;



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

Тут ошибка:

> .logo {


> float: left;


> display: inline-block;


при включенном float значение display приравнивается к block. Это какой-то хак для отдельных браузеров?

> .transite, .featured a img, .social img, nav a, .button {


> transition: all 200ms linear;


Почему тут all?

> <a href="tel:0247 541 65 87" class="tel"><div>0247 541 65 87</div></a>


Зачем тут лишний div внутри a? И почему div, а не span? И почему без имени класса?

Сделай отдельную страницу, на которой в body находится только обычный текст с разными стандартными тегами (p, strong, a, em, h1-h6, ul, ol, li, table, img, blockquote), и подключи к ней тот же CSS файл (style.css). Убедись, что все отоображается нормально. Если этого не сделать, то когда на сайт будут добавлять новые страницы, все эти косяки повылезают и придется целиком переделывать верстку.

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

Если ты хотел еще подучить CSS, то в моих задачах на HTML есть последние задачи (про переключатель и про вкладки), они вроде относительно сложные.
60 Кб, 340x707
#619 #1078652
>>1077031

В адаптивной версии в шапке гигансткий текст. Ну то есть лозунг про "digital branding agency" занимает целый экран. Зачем он такой там нужен? Я тебе в третий раз уже наверно напоминаю, что надо подойти к адаптивной версии творчески. То есть, сам лозунг конечно стоит оставить, но уменьшить его до адекватного размера. Также, можно убрать центирование лозунга, оно хорошо смотрится на широком экране, но глупо выглядит на маленькой ширине.

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

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

Далее, надо проверить твой HTML валидатором: https://html5.validator.nu/?doc=https://theknacker.github.io/Webpaint/webpaint.html&showimagereport=yes

Нужно посмотреть, что он там пишет и если есть ошибки, исправить их.

Далее, тут:

> <div class="service_item">


> <img src="images/Computer_iMac.png" width="62px" height="59px"/>


В атрибутах width/height разве можно писать px?

> <title>WebPaint</title>


> <meta charset="utf-8">


Это ошибка, кодировка должна идти ДО любых текстов.

> <a href="https://orss.ru/rss_1.html" target="_blank"><img src="images/rss.svg" width="30" height="30" alt="rss"/></a>


Зачем тут img? Разве нельзя сделать иконку просто фоновой картинкой к ссылке?

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

Также, в CSS неправильно залдан шрифт. Если вставить на страницу текст, то абзацы (p) в нем используют один шрифт, а список (ul/li) использует другой шрифт. Это потому, что у тебя неправильно задан шрифт:

> p {


> font: 14px latoregular, serif;


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

Тут еще нашел странное место:

> table {


> max-width: 500px;



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

Тут ошибка:

> .logo {


> float: left;


> display: inline-block;


при включенном float значение display приравнивается к block. Это какой-то хак для отдельных браузеров?

> .transite, .featured a img, .social img, nav a, .button {


> transition: all 200ms linear;


Почему тут all?

> <a href="tel:0247 541 65 87" class="tel"><div>0247 541 65 87</div></a>


Зачем тут лишний div внутри a? И почему div, а не span? И почему без имени класса?

Сделай отдельную страницу, на которой в body находится только обычный текст с разными стандартными тегами (p, strong, a, em, h1-h6, ul, ol, li, table, img, blockquote), и подключи к ней тот же CSS файл (style.css). Убедись, что все отоображается нормально. Если этого не сделать, то когда на сайт будут добавлять новые страницы, все эти косяки повылезают и придется целиком переделывать верстку.

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

Если ты хотел еще подучить CSS, то в моих задачах на HTML есть последние задачи (про переключатель и про вкладки), они вроде относительно сложные.
#620 #1078653
>>1077031

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

- booking.com (хотя на мой взгляд, у него довольно перегруженный дизайн, но мобильная версия относительно адекватная)
- geektimes.com
- meduza.io
- reddit.com (но мне не нравится, как он на каждой странице навязывает свое приложение, так делать не надо. И еще мне не нравится прелоадер)
#621 #1078654
>>1077721

Ты бы посмотрел в документации или в коде, что такое @web и откуда он берется. И тогда может быть будет понятно, куда смотреть дальше.

>>1077140

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

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

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

Ну и если тебе результат не важен, так можно наверно вообще ничего не делать, верно?

>>1077196

Посмотри на код Юи. Там стоит @, который должен подавлять ошибку при отсутствии файла. Но у тебя она не подавляется и привыодит к выбросу исключения. Почему? Есть разные версии:

- ты написал свой обработчик ошибок, который игнорирует @
- ты поменял что-то в конфиге PHP, например, включил опцию scream http://php.net/manual/ru/book.scream.php
- ты включил какую-то опцию в Юи, которая включает scream
- ты поставил нестабильную версию Юи, в которой присутствует баг

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

>>1077257

Кеш Хрома вообще тут не при чем.

>>1077209

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

Главная проблема - что могут появляться побочные эффекты (вот тут это описано у меня: https://github.com/codedokode/pasta/blob/master/good-code.md#Избегай-побочных-эффектов )

>>1077250

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

function createDownloadFileResponse(string $fileName, ParameterBag $server): Response
function createDownloadFileResponse(\SplFileObject $file, ParameterBag $server): Response

(я передаю параметры $_SERVER как ParameterBag, не помню точный тип).
#621 #1078654
>>1077721

Ты бы посмотрел в документации или в коде, что такое @web и откуда он берется. И тогда может быть будет понятно, куда смотреть дальше.

>>1077140

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

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

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

Ну и если тебе результат не важен, так можно наверно вообще ничего не делать, верно?

>>1077196

Посмотри на код Юи. Там стоит @, который должен подавлять ошибку при отсутствии файла. Но у тебя она не подавляется и привыодит к выбросу исключения. Почему? Есть разные версии:

- ты написал свой обработчик ошибок, который игнорирует @
- ты поменял что-то в конфиге PHP, например, включил опцию scream http://php.net/manual/ru/book.scream.php
- ты включил какую-то опцию в Юи, которая включает scream
- ты поставил нестабильную версию Юи, в которой присутствует баг

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

>>1077257

Кеш Хрома вообще тут не при чем.

>>1077209

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

Главная проблема - что могут появляться побочные эффекты (вот тут это описано у меня: https://github.com/codedokode/pasta/blob/master/good-code.md#Избегай-побочных-эффектов )

>>1077250

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

function createDownloadFileResponse(string $fileName, ParameterBag $server): Response
function createDownloadFileResponse(\SplFileObject $file, ParameterBag $server): Response

(я передаю параметры $_SERVER как ParameterBag, не помню точный тип).
#622 #1078655
>>1077082

Есть бесплатная версия скриншотов на сайте modern.ie, не требующая регистрации (за счет Майкрософта).

Есть бесплатный, но не идеальный, сервис http://browsershots.org/ - но там нет маков, мобильных устройств, и только Хромы с Фаерфоксами.

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

Кстати, вы бы могли помочь проекту Browsershots, улучшив их Screenshot Factory для других браузеров (как я понимаю, тут можно было бы попробовать интегрировать Selenium, который позволяет управлять не только Хромами и Фаерфоксами), а также написав Screenshot Factory для мобильных устройств.

>>1077066

Что касается верстки, то в инструментах разработчика в браузере есть кнопка для тестирования мобильной верстки. Она делает такие вещи:

- меняет размер окна
- имитирует поведение моб. браузера, например, в отношении тега meta viewport, умеет отображать страницу в уменьшенном масштабе например, позволяет прокручивать страницу перетаскиванием
- выставляет мобильный User-Agent при отправке запросов на сервер
- в Хроме еще есть возможность имитировать медленный интернет

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

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


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

>>1077072

Ты про метатег meta viewport? Он игнорируется десктопными браузерами при нормальной работе, но в режиме тестирования адаптивной верстки он учитывается.
#622 #1078655
>>1077082

Есть бесплатная версия скриншотов на сайте modern.ie, не требующая регистрации (за счет Майкрософта).

Есть бесплатный, но не идеальный, сервис http://browsershots.org/ - но там нет маков, мобильных устройств, и только Хромы с Фаерфоксами.

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

Кстати, вы бы могли помочь проекту Browsershots, улучшив их Screenshot Factory для других браузеров (как я понимаю, тут можно было бы попробовать интегрировать Selenium, который позволяет управлять не только Хромами и Фаерфоксами), а также написав Screenshot Factory для мобильных устройств.

>>1077066

Что касается верстки, то в инструментах разработчика в браузере есть кнопка для тестирования мобильной верстки. Она делает такие вещи:

- меняет размер окна
- имитирует поведение моб. браузера, например, в отношении тега meta viewport, умеет отображать страницу в уменьшенном масштабе например, позволяет прокручивать страницу перетаскиванием
- выставляет мобильный User-Agent при отправке запросов на сервер
- в Хроме еще есть возможность имитировать медленный интернет

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

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


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

>>1077072

Ты про метатег meta viewport? Он игнорируется десктопными браузерами при нормальной работе, но в режиме тестирования адаптивной верстки он учитывается.
#623 #1078657
А, я выше упомянул modern.ie, вот прямая ссылка для бесплатного получения скриншотов в ИЕ и некоторых других браузерах, включая мобильные: https://developer.microsoft.com/en-us/microsoft-edge/tools/screenshots/?url=https://theknacker.github.io/Webpaint/webpaint.html
#624 #1078681
>>1078639
я другой анон, спасибо за разъяснение. А поясните, надо ли после форича его обратно на первый ставить? Это критично вообще?
#625 #1078686
>>1078655
спасибо
#626 #1078698
>>1078681

Не надо.

Форич сам его сбрасывает как нужно.
#627 #1078724
Анон, помоги с простой (пока не для меня) задачей. Надо на сайте сделать так, чтобы header и footer всегда отображались, т.е. чтобы страницы адаптировались под разрешение пользователя.
Сайт на wordpress, тема tesseract, если важно.
@sslrinc
#628 #1078778
Ларавелепроблемы, господа погромисты. Есть сайт с каталогом товаров и поисковым фильтром в виде чекбоксов. Отправка данных фильтра осуществляется через форму методом пост, после чего в контроллере с помощью $request->flash() данные фильтра из формы сохраняются в сессию, а потом клиенту отправляется view, на котором уже отображаются отфильтрованные товары и все галочки с фильтра на месте благодаря функции old(). НО, поскольку товаров много я использую пагинацию и при переходе на следующую страницу галочки на чекбоксах уже не сохраняются, хотя в методе есть session()->reflash(), который по идее должен оставить данные из сессии на еще один реквест. Подскажи, умный анон, что я делаю не так?
#629 #1078821
>>1078778

Зачем ты так все переусложнил и что тебе мешает добавить параметры поиска в URL?

/catalog?model=sony&price=1000&page=2
#630 #1078830
>>1078821
Просто их очень много. Товаров сотни тысяч, параметров десятки и сотни. И всю вот эту бороду в URL видеть совсем не хочется.
#631 #1078831
>>1078830

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

Я бы советовал посмотреть как в Яндекс-Маркете сделано например и сделать так же. У них тоже параметров много и все работает.
#632 #1078834
>>1078831
А может ты и прав. Я пожалуй в понедельник на свежую голову подумаю над этим.
#633 #1078853
>>1078778
Ни кода, ну хуя не показал...
При каждом запросе сохраняй сессию заново и все.

Создай класс-обьект формы поиска.
Например на псевдокоде
class SearchParam
-- searchString: string
-- searchCheckBox: array

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

Так же незабуть сделать кнопку "очистить фильты", которая чистит форму и сессию.
#634 #1079104
Чё-то столько вакансий на Symfony развелось, что я даже задумался о перекате на него с Yii 2. Стоит ли?
#635 #1079105
Алсо, мы тонем. Перекатывайте уже.
#636 #1079116
https://github.com/codedokode/pasta/blob/master/soft/php-install.md

Актуальный гайд установки?
#637 #1079118
>>1079116
Какую версию лучше ставить начинающему? Самую новую?
#638 #1079129
>>1078652

>Зачем тут img? Разве нельзя сделать иконку просто фоновой картинкой к ссылке?


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

>В атрибутах width/height разве можно писать px?


Не знал, что автоматически пиксели как единица стоят.

>при включенном float значение display приравнивается к block. Это какой-то хак для отдельных браузеров?


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

>Не очень понятно, почему никакая таблица на всем сайте не может быть шире 500px.


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

>Зачем тут лишний div внутри a? И почему div, а не span? И почему без имени класса?


Потому что я забыл про существование span. С этим значение была какая то временная проблема (В связи с кривой версткой) о которой я забыл. Но я его удалю.
>>1078653
Спасибо ОП.

Сейчас я пока читаю это: https://www.w3.org/TR/CSS22/
веришь или нет ОП я сначала изучал CSS3, а не ранние стандарты, и только недавно осознал, что проще чем выучить стандарт нет ничего и что я больше времени потерял. После 22 перейду на модули. В планах сейчас уже хорошо бы и правильно забить в голову стандарты и исправить ошибки в дальнейшем. Т.е пока попробую значения все, а параллельно буду скидывать работу по сайту.
#639 #1079131
>>1078653
Да кстати круто сделали.
#640 #1079132
>>1078653

>reddit.com


>но мне не нравится, как он на каждой странице навязывает свое приложение, так делать не надо. И еще мне не нравится прелоадер


А этот div.side с поиском, логином с рекламой и паролем как тебе?
#641 #1079180
>>1079132

Не знаю, сайдбар как сайдбар, на многих сайтах используется. Кстати, обнаружил интересную штуку: в Хроме в средствах разработчика на вкладке Element можно нажать Ctrl + F, ввести .side (как CSS селектор) и он подсветит соответствующий элемент.

>>1079129

> В многих браузерах слетает я заметил, раньше там спрайты стояли, но в мозиле и старых ИЕ все слетает напрочь



Привел бы кусочек CSS кода. Ты картинку добавлял как content: ''; position: absolute; width: x; height: y; background-image: z; или как content: url(...)? Первое разве что в ИЕ6-7 может не работать, а так, это CSS2.1 и он должен работать везде (в случае обычного PNG).

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



В общем-то да, чтение стандарта полезно тем, что видна общая логика, как в CSS те или иные вещи сделаны, там все подробно расписано. Но целиком по моему его учить не обязательно. Подробно стоит читать в первую очередь разделы вроде такого https://www.w3.org/TR/CSS22/visuren.html (про позиционирование и его тонкости), а какие-то простые вещи вроде color или font-size можно и по диагонали пролистывать.

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

Также, полезно понимать, как давно и где поддерживается та или иная фича из CSS3/4 или HTML5. Если ты будешь это знать, ты сможешь сразу верстать так, чтобы страница отображалась во всех требуемых браузерах, и тебе не придется многкратно тестировать и исправлять проблемы. Эта информация есть на сайте caniuse.com.

Не хочешь какие-то дополнительные задачки на CSS? У меня тут есть парочка под рукой:

1) Чат. Нужно сверстать интерфейс для чата. Он состоит из 2 частей: верхняя, где выводятся сообщения и нижняя, где есть поля и кнопки для создания нового сообщения. В верхней части выводятся сообщения, если их мало, то они должны быть прижаты вниз (так что сверху над ними пустое место), если их много, должна появляться линейка прокрутки. Нижняя часть содержит, допустим, поле ввода сообщения и кнопку отправки.

Тут есть 2 варианта задачи, попроще и посложнее:

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

2) Центрирование картинок

На сайте есть окошко под картинку, неизвестной заранее ширины и неизвестной, но фиксированной высоты (например, высота 100px, ширина = ширине окна или ширина = ширине родителя, высота = 50% ширины). Размеры неизвестны, так как мы не знаем, в окне какого размера будет отображаться страница и хотим сделать верстку максимально адаптивной.

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

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

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

Также, есть усложненная версия задачи. В ней высота окошка не задается фиксированно, а может меняться от a до b (например: от 100px до 200px). Соответственно, если картинка высокая, то окошко может растягиваться по высоте, если картинка широкая, то окошко ужимается по высоте. Это позволяет в большинстве случаев отобразить картинку без полей, так, что ее пропорции соответствуют пропорции окошка.

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

3) Вывод адаптивных SVG-картинок

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

Можешь порешать, если захочешь попрактиковаться. Тут может быть несколько решений, каждое со своими недостатками. Первая задача в варианте б, вполне возможно, не решается без флексбокса, но я не уверен.
#641 #1079180
>>1079132

Не знаю, сайдбар как сайдбар, на многих сайтах используется. Кстати, обнаружил интересную штуку: в Хроме в средствах разработчика на вкладке Element можно нажать Ctrl + F, ввести .side (как CSS селектор) и он подсветит соответствующий элемент.

>>1079129

> В многих браузерах слетает я заметил, раньше там спрайты стояли, но в мозиле и старых ИЕ все слетает напрочь



Привел бы кусочек CSS кода. Ты картинку добавлял как content: ''; position: absolute; width: x; height: y; background-image: z; или как content: url(...)? Первое разве что в ИЕ6-7 может не работать, а так, это CSS2.1 и он должен работать везде (в случае обычного PNG).

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



В общем-то да, чтение стандарта полезно тем, что видна общая логика, как в CSS те или иные вещи сделаны, там все подробно расписано. Но целиком по моему его учить не обязательно. Подробно стоит читать в первую очередь разделы вроде такого https://www.w3.org/TR/CSS22/visuren.html (про позиционирование и его тонкости), а какие-то простые вещи вроде color или font-size можно и по диагонали пролистывать.

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

Также, полезно понимать, как давно и где поддерживается та или иная фича из CSS3/4 или HTML5. Если ты будешь это знать, ты сможешь сразу верстать так, чтобы страница отображалась во всех требуемых браузерах, и тебе не придется многкратно тестировать и исправлять проблемы. Эта информация есть на сайте caniuse.com.

Не хочешь какие-то дополнительные задачки на CSS? У меня тут есть парочка под рукой:

1) Чат. Нужно сверстать интерфейс для чата. Он состоит из 2 частей: верхняя, где выводятся сообщения и нижняя, где есть поля и кнопки для создания нового сообщения. В верхней части выводятся сообщения, если их мало, то они должны быть прижаты вниз (так что сверху над ними пустое место), если их много, должна появляться линейка прокрутки. Нижняя часть содержит, допустим, поле ввода сообщения и кнопку отправки.

Тут есть 2 варианта задачи, попроще и посложнее:

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

2) Центрирование картинок

На сайте есть окошко под картинку, неизвестной заранее ширины и неизвестной, но фиксированной высоты (например, высота 100px, ширина = ширине окна или ширина = ширине родителя, высота = 50% ширины). Размеры неизвестны, так как мы не знаем, в окне какого размера будет отображаться страница и хотим сделать верстку максимально адаптивной.

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

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

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

Также, есть усложненная версия задачи. В ней высота окошка не задается фиксированно, а может меняться от a до b (например: от 100px до 200px). Соответственно, если картинка высокая, то окошко может растягиваться по высоте, если картинка широкая, то окошко ужимается по высоте. Это позволяет в большинстве случаев отобразить картинку без полей, так, что ее пропорции соответствуют пропорции окошка.

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

3) Вывод адаптивных SVG-картинок

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

Можешь порешать, если захочешь попрактиковаться. Тут может быть несколько решений, каждое со своими недостатками. Первая задача в варианте б, вполне возможно, не решается без флексбокса, но я не уверен.
#642 #1079208
>>1079180
Спасибо, как раз буду практиковаться пока буду читать, скину результаты через недельку.
#643 #1079249
Аноны объясните плз как нормально реализуется патерн для работы с бд "Table Data Gateway".
http://prntscr.com/h04mn5
1. Сюда я не понимаю что и как написать.
2. Тут, как я понимаю, пишутся функции для взаимодействия с выбраной таблицей.
И еще вопрос где прописывается соединение с таблицей и как включается в класс.
#644 #1079305
Вот у меня вопрос про расширения функционала для студентов. Допустим у нас есть TDG вида:
class StudentsTableDataGateway
{
public function __construct(\pdo $pdo)
{ / .... / }
public function getStudent(int $id)
{ / .... / }
public function save(student $student)
{ / .... / }
// etc
}
Допустим он установлен на 3-х разных доменах (универ, колледж при универе и лицей при универе. Живой пример). И вот для универа нам нужно показывать средний бал поступивших. Как нам расширять функционал TDG все не сломав? Варианты, которые пришли мне в голову:
1.Просто написать запрос в контроллере, не касаясь TDG вообще. Понятно, что это совсем плохо и убивает все преимущества паттерна.
2.Добавить в изначальный TDG функцию выполняющую любой запрос к таблице. Мне показалось, что это почти пункт 1 только нагажено в другом месте.
3.Наследоваться от нашего TDG с добавлением новой функции getAverageTestScore(). Это мой текущий вариант действий.
4.Изначально делать все через интерфейсы. Это мне посоветовали на просторах интернета. Я понимаю как это поможет в случае если у нас разные БД и соответственно разные TDG, но как это решает вышеописанную задачу?
ОП помогай, у меня уже мозг закипает.
#645 #1079425
>>1077977
Спасибо, всё работает, я вот только не понял момент про паблик метод. Насколько я понимаю, если не уточнять область видимости, то метод будет видим как паблик или что-то около того. А вот переменную класса я не могу оставить с дефолтным ключевым словом, мне компилятор ошибку выбивает. И еще этот $this-> оче напрягает писать к каждой переменной в методах класса, чому оно само не в курсе какая переменная локальная, а какая классовая?
#646 #1079435
>>1079305
Ты можешь выбирать что показывать во Вью.(класс который у тебя выводит все)
#647 #1079755
https://ideone.com/UeJQ1P регулярки на номер телефона.
#648 #1079816
>>1079755

>Right: 84951234567 позвать люсю



мимонеОП
#649 #1079861
>>1079755

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

(не)?честный = соответствует словам "нечестный" и "честный"
(ab?){2,4} = соответствует словам aa, aba, abab, ababaa

В регулярке нужно использовать флаг u, иначе он может считать кириллицу не буквами, а 2 странными символами.

Твоя регулярка допускает номера, начинающиеся с 7 без плюса, а также с +8

Нужно улучшать код.

>>1079305

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

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

> Добавить в изначальный TDG функцию выполняющую любой запрос к таблице.


Это уже будет не TDG, у тебя будут SQL запросы раскиданы по всему коду.

> Изначально делать все через интерфейсы


Тут наверно это не подойдет.
#650 #1079862
>>1079249

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

> Сюда я не понимаю что и как написать.


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

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

PDO - это встроенный в PHP класс для соединения и выполнения запросов к разным видам БД: http://php.net/manual/ru/book.pdo.php В интернете много статей про него, в том числе на русском.

То есть мы как бы разделяем работу с БД на слои:

- нижний слой - PDO - знает, как соединиться с БД и как выполнять SQL запросы, но не знает ничего про таблицы, колонки, итд
- верхний слой - TDG - знает, какие есть таблицы, какие в них колонки, но не знает, как соединятьяся БД, а использует для этого объект PDO
- остальной код не знает ничего ни про БД, ни про таблицы, а вызывает методы TDG, чтобы что-то получить или изменить в БД

Такое разделение тебе будет еще часто встречаться.

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


Верно. Они выглядят примерно так:

public function getNewsCount()
{
$result = $this->pdo->query("SELECT COUNT(*) FROM news");
$count = $result->fetchColumn();
return $count;
}

> где прописывается соединение с таблицей и как включается в класс.


Ты создаешь объект PDO, ему передаешь параметры соединения и передаешь этот объект при создании объекта TDG. Изучи PDO для начала.
#650 #1079862
>>1079249

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

> Сюда я не понимаю что и как написать.


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

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

PDO - это встроенный в PHP класс для соединения и выполнения запросов к разным видам БД: http://php.net/manual/ru/book.pdo.php В интернете много статей про него, в том числе на русском.

То есть мы как бы разделяем работу с БД на слои:

- нижний слой - PDO - знает, как соединиться с БД и как выполнять SQL запросы, но не знает ничего про таблицы, колонки, итд
- верхний слой - TDG - знает, какие есть таблицы, какие в них колонки, но не знает, как соединятьяся БД, а использует для этого объект PDO
- остальной код не знает ничего ни про БД, ни про таблицы, а вызывает методы TDG, чтобы что-то получить или изменить в БД

Такое разделение тебе будет еще часто встречаться.

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


Верно. Они выглядят примерно так:

public function getNewsCount()
{
$result = $this->pdo->query("SELECT COUNT(*) FROM news");
$count = $result->fetchColumn();
return $count;
}

> где прописывается соединение с таблицей и как включается в класс.


Ты создаешь объект PDO, ему передаешь параметры соединения и передаешь этот объект при создании объекта TDG. Изучи PDO для начала.
#651 #1079874
>>1079118

Самую новую.

>>1079116

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

>>1079105

Погоди немного, через несколько дней перекатим.

>>1079425

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


С каким? Нужно писать public $x; или private $x; И перед методами, кстати, тоже в PSR рекомендуется всегда писать явно public/private.

> И еще этот $this-> оче напрягает писать к каждой переменной в методах класса, чому оно само не в курсе какая переменная локальная, а какая классовая?



Оно может определять, но тогда при чтении кода это будет непонятно. Вот например в Яве можно не писать this, и в итоге они перед полями класса начинают префиксы приписывать, чтобы отличить их от переменных. Вот кусочек кода из Андроида: https://android.googlesource.com/platform/packages/apps/IM/+/master/src/com/android/im/app/AddContactActivity.java#66

Там видно, что перед именами полей пишут букву m, чтобы отличать их от переменных:

> private Spinner mListSpinner;


...

> mListSpinner = (Spinner) findViewById(R.id.choose_list);



Хотя конечно код получается короче в итоге. Ну и неудобно, если у тебя и переменная и поле имеют одинаковое имя:

public function setName(name) {
$this->name = name;
}
#651 #1079874
>>1079118

Самую новую.

>>1079116

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

>>1079105

Погоди немного, через несколько дней перекатим.

>>1079425

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


С каким? Нужно писать public $x; или private $x; И перед методами, кстати, тоже в PSR рекомендуется всегда писать явно public/private.

> И еще этот $this-> оче напрягает писать к каждой переменной в методах класса, чому оно само не в курсе какая переменная локальная, а какая классовая?



Оно может определять, но тогда при чтении кода это будет непонятно. Вот например в Яве можно не писать this, и в итоге они перед полями класса начинают префиксы приписывать, чтобы отличить их от переменных. Вот кусочек кода из Андроида: https://android.googlesource.com/platform/packages/apps/IM/+/master/src/com/android/im/app/AddContactActivity.java#66

Там видно, что перед именами полей пишут букву m, чтобы отличать их от переменных:

> private Spinner mListSpinner;


...

> mListSpinner = (Spinner) findViewById(R.id.choose_list);



Хотя конечно код получается короче в итоге. Ну и неудобно, если у тебя и переменная и поле имеют одинаковое имя:

public function setName(name) {
$this->name = name;
}
#652 #1079875
>>1079861
Спасибо ОП.
#653 #1079886
>>1068062

Решено верно.

>>1068087

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

>>1068108

Я по коду хотел замечание сделать, ты зря делаешь 2 разных переменных с одним именем тут:

> decrypted.then(function(decrypted) {



Это создает путаницу, лучше назвать первую переменную decryptedPromise.

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

Что касается промисов. Промис - это объект, представляющий значение, которое будет получено когда-то в будущем. Ты можешь преобразовать обещание вернуть значение A (Promise<A>) в обещание вернуть значение B (Promise<B>) c помощью метода then, в который передается функция, преобразующая A в B.

Соответственно расшифровка - это и есть преобразование (Array<encrypted> -> Array<decrypted>). На входе мы получим массив зашифрованных сообщение encrypted, на выходе мы должны вернуть массив расшифрованных сообщений decrypted. Расшифровка тоже асинхронная, но это не проблема так как функция-преобразователь A -> B может вернуть Promise<B> вместо самого значения B.

Пишем код:

function decryptMessageAsync(message) {
// отправляет сообщение на расшифровку и возвращает промис
}

var encryptedPromise = getMessages();
var decryptedMessagesPromise = encryptedPromise.then(function (encryptedMessages) {

// Получаем массив промизов расшифрованных сообщений
var decryptedPromises = encryptedMessages.map(decryptMessageAsync);

// получаем из массива промизов один промиз с массивом расшифрованных сообщений
return Promise.all(decryptedPromises);
});

В decryptedMessagesPromise мы имеем промиз, который вернет массив расшифрованных сообщений. Мы можем например передать его во view:

decryptedMessagesPromise.then(function (messages) {
view.showMessages(messages);
});

Другой вариант - добавить сообщения в локальное хранилище, изменение которого вызовет обновление view:

decryptedMessagesPromise.then(function (messages) {
messageStore.append(messages);
});

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

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

Также, тут есть недостаток. Расшифровка сообщений - асинхронная, но тут мы ждем, пока они не расшифруются все. Можно написать более продвинутую версию кода:

var encryptedPromise = getMessages();

// Promise<Array<Promise<decrypted>>>
var decryptedMessagesPromise = encryptedPromise.then(function (encryptedMessages) {

// Получаем массив промизов расшифрованных сообщений
var decryptedPromises = encryptedMessages.map(decryptMessageAsync);
return decryptedPromises;
});

decryptedMessagesPromise.then(function (decryptedPromiseArray) {
decryptedPromiseArray.each(function (decryptedPromise) {
decryptedPromise.done(function (decrypted) {
messagesView.displayMessage(decrypted);
});
})
});

Здесь мы видим громоздкую тяжелочитаемую конструкцию, а это верный признак проблемы, которая решается "добавлением еще одной абстракции". Попробуем применить тут реактивное программирование. Я напомню, что там есть объект Observable, который представляет собой поток каких-то событий. У нас будет 2 потока: поток, в который прибывают зашифрованные сообщения, и поток, в который приходя расшифрованные сообщения.

// Promise<encrypted[]>
var encryptedArrayPromise = getMessages();
// Поток массивов зашифрованных сообщений
var messageArrayStream = Rx.Observable.fromPromise(encryptedArrayPromise);
// Поток отдельных зашифрованных сообщений
var encryptedStream = messageArrayStream.flatMap((encryptedArray) => encryptedArray);
// Поток расшифрованных сообщений
var decryptedStream = encryptedStream.map(decryptMessageAsync);

decryptedStream.subscribe(function (decrypted) {
view.addOneMessage(decrypted);
});

Я должен тут предупредить, что я не писал ничего на Reactive и код отражает только общую идею. Не факт, что он работает.
#653 #1079886
>>1068062

Решено верно.

>>1068087

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

>>1068108

Я по коду хотел замечание сделать, ты зря делаешь 2 разных переменных с одним именем тут:

> decrypted.then(function(decrypted) {



Это создает путаницу, лучше назвать первую переменную decryptedPromise.

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

Что касается промисов. Промис - это объект, представляющий значение, которое будет получено когда-то в будущем. Ты можешь преобразовать обещание вернуть значение A (Promise<A>) в обещание вернуть значение B (Promise<B>) c помощью метода then, в который передается функция, преобразующая A в B.

Соответственно расшифровка - это и есть преобразование (Array<encrypted> -> Array<decrypted>). На входе мы получим массив зашифрованных сообщение encrypted, на выходе мы должны вернуть массив расшифрованных сообщений decrypted. Расшифровка тоже асинхронная, но это не проблема так как функция-преобразователь A -> B может вернуть Promise<B> вместо самого значения B.

Пишем код:

function decryptMessageAsync(message) {
// отправляет сообщение на расшифровку и возвращает промис
}

var encryptedPromise = getMessages();
var decryptedMessagesPromise = encryptedPromise.then(function (encryptedMessages) {

// Получаем массив промизов расшифрованных сообщений
var decryptedPromises = encryptedMessages.map(decryptMessageAsync);

// получаем из массива промизов один промиз с массивом расшифрованных сообщений
return Promise.all(decryptedPromises);
});

В decryptedMessagesPromise мы имеем промиз, который вернет массив расшифрованных сообщений. Мы можем например передать его во view:

decryptedMessagesPromise.then(function (messages) {
view.showMessages(messages);
});

Другой вариант - добавить сообщения в локальное хранилище, изменение которого вызовет обновление view:

decryptedMessagesPromise.then(function (messages) {
messageStore.append(messages);
});

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

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

Также, тут есть недостаток. Расшифровка сообщений - асинхронная, но тут мы ждем, пока они не расшифруются все. Можно написать более продвинутую версию кода:

var encryptedPromise = getMessages();

// Promise<Array<Promise<decrypted>>>
var decryptedMessagesPromise = encryptedPromise.then(function (encryptedMessages) {

// Получаем массив промизов расшифрованных сообщений
var decryptedPromises = encryptedMessages.map(decryptMessageAsync);
return decryptedPromises;
});

decryptedMessagesPromise.then(function (decryptedPromiseArray) {
decryptedPromiseArray.each(function (decryptedPromise) {
decryptedPromise.done(function (decrypted) {
messagesView.displayMessage(decrypted);
});
})
});

Здесь мы видим громоздкую тяжелочитаемую конструкцию, а это верный признак проблемы, которая решается "добавлением еще одной абстракции". Попробуем применить тут реактивное программирование. Я напомню, что там есть объект Observable, который представляет собой поток каких-то событий. У нас будет 2 потока: поток, в который прибывают зашифрованные сообщения, и поток, в который приходя расшифрованные сообщения.

// Promise<encrypted[]>
var encryptedArrayPromise = getMessages();
// Поток массивов зашифрованных сообщений
var messageArrayStream = Rx.Observable.fromPromise(encryptedArrayPromise);
// Поток отдельных зашифрованных сообщений
var encryptedStream = messageArrayStream.flatMap((encryptedArray) => encryptedArray);
// Поток расшифрованных сообщений
var decryptedStream = encryptedStream.map(decryptMessageAsync);

decryptedStream.subscribe(function (decrypted) {
view.addOneMessage(decrypted);
});

Я должен тут предупредить, что я не писал ничего на Reactive и код отражает только общую идею. Не факт, что он работает.
#654 #1079888
>>1068108

Я еще должен предупредить, что в моем коде в обоих примерах мы отправляем все сообщения на расшифровку одновременно. Это может быть не очень эффективно, если расшифровка будет идти параллельно и процессор постоянно будет переключаться между потоками. Но с другой стороны, если ядер несколько, мы бы могли так задействовать их все. В общем, надо смотреть по ситуации.
#655 #1080070
https://regex101.com/r/w36Gqd/1
никак не могу сделать так, чтобы включить возможный отступ между знаком плюс и цифрой 7
пытался написать [+]\\s*7 но что-то ничего не получалось
#656 #1080092
>>1080070
Уже не надо

Прошу оценить мою регулярку теперь: https://ideone.com/ZBnB38

Вот старая:>>1079755

Стало лучше?
#657 #1080108
>>1068374

> Но в теле, при гет запросе, не советуется.


У GET запросов нет тела

> Т.к. при хттпс запросе, строка с адресом не кодируется


Неверно. При HTTPS шифруется весь запрос целиком. Однако атакующий все равно видит IP адрес сайта, с которым идет соединение, его сертификат (где указан домен), а также специальное дополнение к SSL позволяет указать домен сайта в открытом виде при установке соединения. То есть атакующий видит только домен и IP/порт, с которым идет соединение.

>>1068397

Поле date не нужно, метод createRandomDate нужно сделать статическим, и чтобы он возвращал сразу объект DateTime. Также твой генератор никак не проверяет например что дата получается реалистичная и что у тебя не получится 31 февраля. Нужно генераторерировать не месяц/день по отдельности, а номер дня в году (в еще лучше - вообще номер дня начиная с 1 янв 1970) и из него уже получать дату. Изучи unix timestamp.

>>1068676

Используй встроенный в PHP шаблонизатор: https://github.com/codedokode/pasta/blob/master/php/templates.md

>>1069103

Используй инструменты разработчика в барузере (Ctrl + Shift + I), чтобы проверить, нет ли ошибок в твоем скрипте.
#658 #1080109
>>1069394

> каким размером делать превью для картинок?


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

> Нужно ли перекодировать видео для превью?


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

Могу предложить такой вариант:

Анализируем информацию о поддержке форматов видео/аудио:

- https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
- https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery
- http://caniuse.com/#search=video

и внимательно читаем все примечания

- выбираем 2-3 формата, охватывающих максимальное число браузеров. Учитываем примечания и особенности форматов.
- выбираем желаемый размер, битрейт и параметры качества видео
- пишем конвертор на основе ffmpeg (открытая программа-перекодировщик видео) и gearman (система выполнения фоновых задач в PHP). Заодно делаем картинки-превьюшки к видео, а при желании - анимированные превьюшки, как на ютубе.
- пытаемся понять, есть у нас право использовать патентованные кодеки вроде H.264 или нет (в итоге решаем, что раз это поддерживается в ffmpeg, то наверно есть)
- не забываем, что процесс перекодировки может зависнуть, отвалиться с ошибкой, предусматриваем обработку таких ситуаций. Запускать сторонний процесс удобно с помощью библиотеки symfony process
- при загрузке страницы с видео добавляем тег video с несколькими source и тестируем во всех доступных браузерах

Это сложно, предупреждаю честно, но даст тебе очень ценный опыт.

Не забудь про мобильные платформы.

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

Вообще, по моему опыту, с поддержкой разных форматов все плохо. Например, свободный браузер Хромиум не вопроизводит видео в Twitter, Dailymotion, и других сервисах. Chrome воспроизводит, но за счет закрытых компонентов от Гугла. Свободный фаерфокс тоже имеет проблемы с вопроизведением.

Без перекодировки получается такой вариант:

- определяем тип видео
- выводим тег video с source и указанием типа и надеемся, что браузер его вопроизведет (скорее всего нет)
#658 #1080109
>>1069394

> каким размером делать превью для картинок?


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

> Нужно ли перекодировать видео для превью?


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

Могу предложить такой вариант:

Анализируем информацию о поддержке форматов видео/аудио:

- https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
- https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery
- http://caniuse.com/#search=video

и внимательно читаем все примечания

- выбираем 2-3 формата, охватывающих максимальное число браузеров. Учитываем примечания и особенности форматов.
- выбираем желаемый размер, битрейт и параметры качества видео
- пишем конвертор на основе ffmpeg (открытая программа-перекодировщик видео) и gearman (система выполнения фоновых задач в PHP). Заодно делаем картинки-превьюшки к видео, а при желании - анимированные превьюшки, как на ютубе.
- пытаемся понять, есть у нас право использовать патентованные кодеки вроде H.264 или нет (в итоге решаем, что раз это поддерживается в ffmpeg, то наверно есть)
- не забываем, что процесс перекодировки может зависнуть, отвалиться с ошибкой, предусматриваем обработку таких ситуаций. Запускать сторонний процесс удобно с помощью библиотеки symfony process
- при загрузке страницы с видео добавляем тег video с несколькими source и тестируем во всех доступных браузерах

Это сложно, предупреждаю честно, но даст тебе очень ценный опыт.

Не забудь про мобильные платформы.

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

Вообще, по моему опыту, с поддержкой разных форматов все плохо. Например, свободный браузер Хромиум не вопроизводит видео в Twitter, Dailymotion, и других сервисах. Chrome воспроизводит, но за счет закрытых компонентов от Гугла. Свободный фаерфокс тоже имеет проблемы с вопроизведением.

Без перекодировки получается такой вариант:

- определяем тип видео
- выводим тег video с source и указанием типа и надеемся, что браузер его вопроизведет (скорее всего нет)
#659 #1080115
>>1069432

Тогда выведи на страницу.

>>1069453

Может быть ты его прописал в автозапуск или в сервисы.

>>1069585

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

>>1069614

По гит: это система управления версиями. Как минимум уметь делать add/commit, pull/push, а лучше еще знать git log, ветки, как узнать, кто сделал то или иное изменение и зачем.

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

>>1069620

В документации этого нет?

https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Concepts_Behind_IndexedDB

> Everything you do in IndexedDB always happens in the context of a transaction. The IndexedDB API provides lots of objects that represent indexes, tables, cursors, and so on, but each of these is tied to a particular transaction. Thus, you cannot execute commands or open cursors outside of a transaction.



> Но что если я просто сделаю


>>DB.objectStore("hui").add({cocol:"semen"});


А где ты возьмешь объект DB? И есть ли у него метод objectStore? Если ты изучишь документацию, ты увидешь, что до objectStore можно добраться только через транзакцию.

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

Изучи, что такое транзакции, прежде чем критиковать.

Если тебе тяжело работать напрямую с транзакциями, ты всегда можешь сделать фукнцию-обертку, которая будет создавать временную транзакцию, делать операцию с БД и закрывать транзакцию.
#659 #1080115
>>1069432

Тогда выведи на страницу.

>>1069453

Может быть ты его прописал в автозапуск или в сервисы.

>>1069585

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

>>1069614

По гит: это система управления версиями. Как минимум уметь делать add/commit, pull/push, а лучше еще знать git log, ветки, как узнать, кто сделал то или иное изменение и зачем.

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

>>1069620

В документации этого нет?

https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Concepts_Behind_IndexedDB

> Everything you do in IndexedDB always happens in the context of a transaction. The IndexedDB API provides lots of objects that represent indexes, tables, cursors, and so on, but each of these is tied to a particular transaction. Thus, you cannot execute commands or open cursors outside of a transaction.



> Но что если я просто сделаю


>>DB.objectStore("hui").add({cocol:"semen"});


А где ты возьмешь объект DB? И есть ли у него метод objectStore? Если ты изучишь документацию, ты увидешь, что до objectStore можно добраться только через транзакцию.

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

Изучи, что такое транзакции, прежде чем критиковать.

Если тебе тяжело работать напрямую с транзакциями, ты всегда можешь сделать фукнцию-обертку, которая будет создавать временную транзакцию, делать операцию с БД и закрывать транзакцию.
#660 #1080116
>>1069948

> $homoCreditTotal = credit($percent = 1.04, $servicePay = 500,


нужно писать просто $homoCreditTotal = credit(1.04, 500, ... , а то ты создаешь лишние бесполезные переменные.

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

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

$startpay добавляется каждый месяц к сумме долга.

$monthlypay у тебя всегда равна 5000.

Попробуй написать код так:

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

>>1069955

Да, удаление должно отправлять POST запрос. Можно на ту же самую страницу, можно на отдельную.

> Или нужно делать две разных модели?


Модель представляет какую-то сущность (например, пользователя), а не операцию над ним.

>>1069977

> так вот нельзя выбирать рандомное слово из массива:


> $word1[rand(1, count($word1))]


Можно, но лучше использовать mt_rand, так как оно дает более "случайные" числа, а также, индексы в массиве считаются с 0, а не с 1.
#660 #1080116
>>1069948

> $homoCreditTotal = credit($percent = 1.04, $servicePay = 500,


нужно писать просто $homoCreditTotal = credit(1.04, 500, ... , а то ты создаешь лишние бесполезные переменные.

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

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

$startpay добавляется каждый месяц к сумме долга.

$monthlypay у тебя всегда равна 5000.

Попробуй написать код так:

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

>>1069955

Да, удаление должно отправлять POST запрос. Можно на ту же самую страницу, можно на отдельную.

> Или нужно делать две разных модели?


Модель представляет какую-то сущность (например, пользователя), а не операцию над ним.

>>1069977

> так вот нельзя выбирать рандомное слово из массива:


> $word1[rand(1, count($word1))]


Можно, но лучше использовать mt_rand, так как оно дает более "случайные" числа, а также, индексы в массиве считаются с 0, а не с 1.
#661 #1080117
>>1070017

Добавить проверку авторизации в контроллер-предок. Также, можно посомтреть: нет ли в Юи события вроде "beforeRequest" или фронт-контроллера.

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

>>1070026

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

>>1070079

Если освоить 8 способов поизиционирования, то фреймворк не понадобится: https://github.com/codedokode/pasta/blob/master/html/positioning.md

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

>>1070261

Тут наверно не стоит записывать расшифрованные сообщения обратно в messages, а стоит использовать новый массив. Ну и стоит подумать над кешированием расшифрованных сообщений, а то если их каждый раз заново расшифровывать, медленно все работать будет. Хотя, если слишком много кешировать, то памяти будет много потребляться.
#662 #1080118
>>1070522

В твоем случае проще отдельных echo натыкать, не создавая массив:

echo первое слово;
echo второе слово;

итд.

>>1074425

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

Контроллеры, модели, валидация, формы - наверно это 100% стоит изучать.

>>1074464

Есть сайты с обзором хостингов, с рейтингами, отзывами, таблицами сравнений и тд. Погугли.

>>1074474

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

>>1074513

У куки есть такой параметр как Path (погугли). Возможно, твои авторизационные куки доступны не на всех страницах сайта.

Алсо как всегда прорекламирую свой урок по HTTP где мельком упоминаются куки: https://github.com/codedokode/pasta/blob/master/network/http.md
#662 #1080118
>>1070522

В твоем случае проще отдельных echo натыкать, не создавая массив:

echo первое слово;
echo второе слово;

итд.

>>1074425

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

Контроллеры, модели, валидация, формы - наверно это 100% стоит изучать.

>>1074464

Есть сайты с обзором хостингов, с рейтингами, отзывами, таблицами сравнений и тд. Погугли.

>>1074474

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

>>1074513

У куки есть такой параметр как Path (погугли). Возможно, твои авторизационные куки доступны не на всех страницах сайта.

Алсо как всегда прорекламирую свой урок по HTTP где мельком упоминаются куки: https://github.com/codedokode/pasta/blob/master/network/http.md
#663 #1080119
>>1074880

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

>>1075151

нужна привязка к краям строки (^ и $)

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

Можешь почитать мануал http://php.net/manual/ru/pcre.pattern.php

>>1075232

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

>>1075611

Думаю, речь об этих плагинах, хотя не уверен: https://dev.mysql.com/doc/refman/5.7/en/authentication-plugins.html

Тут еще есть ответ по теме: https://stackoverflow.com/questions/33991228/what-is-the-default-root-pasword-for-mysql-5-7/33991229#33991229

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

Вообще, в линуксе обычно программы исопльзуют системную таблицу пользователей, а не свою (как mysql). Ну например, постгрес по умолчанию логинится под текущим пользователем ОС.

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

Если ты используешь phpMyAdmin, проверь, что он не доступен снаружи. Были раньше случаи, когда там находили дыры, и я бы не стал его выставлять в интернет вообще. Ну или хотя бы закрыл HTTP авторизацией, доверия к его коду у меня нету. И защиты от подбора паролей там по моему тоже нет.
#663 #1080119
>>1074880

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

>>1075151

нужна привязка к краям строки (^ и $)

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

Можешь почитать мануал http://php.net/manual/ru/pcre.pattern.php

>>1075232

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

>>1075611

Думаю, речь об этих плагинах, хотя не уверен: https://dev.mysql.com/doc/refman/5.7/en/authentication-plugins.html

Тут еще есть ответ по теме: https://stackoverflow.com/questions/33991228/what-is-the-default-root-pasword-for-mysql-5-7/33991229#33991229

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

Вообще, в линуксе обычно программы исопльзуют системную таблицу пользователей, а не свою (как mysql). Ну например, постгрес по умолчанию логинится под текущим пользователем ОС.

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

Если ты используешь phpMyAdmin, проверь, что он не доступен снаружи. Были раньше случаи, когда там находили дыры, и я бы не стал его выставлять в интернет вообще. Ну или хотя бы закрыл HTTP авторизацией, доверия к его коду у меня нету. И защиты от подбора паролей там по моему тоже нет.
#664 #1080120
>>1076338

> То есть тут лучше вообще эту строку убрать и сделать заголовки на ошибку сервера, помимо display_erorrs?


Можно выводить подробности ошибки если включен display_errors в конфиге PHP. То есть на dev сервере.

Заголовки (HTTP код 5xx) нужны в любом случае.

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


Книга написана во времена PHP5, когда этой фичи в PHP не было.

> bindValue для 'order by :field :direction' не работает. У меня это проверяется в Pagere'е, хотя, согласен, странно это, лучше в контроллере валидацию делать, у тебя это справедливо замечено.


Я не об этом. Имена полей надо подставлять напрямую в запрос, но перед этим надо в той же самой функции их проверить. Иначе как понять, есть инъекция или нет? Лазать по всему коду? Даже это не гарантирует, что завтра кто-то где-то эту функцию не вызовет без филььтрации параметров от пользователя.

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

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


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

> Состояние в данном случае – это имитация stateful за счет куки и объект будто бы живет на протяжении многих запросов или имеется в виду наличие важных полей?


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

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


Интересная точка зрения. Сгенерировать токен, сохранить в куку, а в БД записать только хеш. Тогда после удаления куки повторно восстановить ее будет невозможно. Можно и так сделать, я не против.

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

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

> А какая есть альтернатива, ну кроме Doctrine и других библиотек (они же вроде тоже поверх PDO)?


Получать массив из БД и написать свою функцию, которая на основе массива создает объект. У тебя одна таблица, это не так и сложно. В больших приложениях, конечно, нужен ORM.

> а какая альтернатива, сеттеры в отдельности?


А почему нет?

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


Сделать метод updateAttributes(array $attrs) - так будет универсальнее всего.

> То есть тут по смыслу не подходит? Лучше !is_null?


Да, когда ты пишешь is_null то видно что ты проверяешь на null, а когда isset - непонятно, может это значит что переменная может не существовать. Запутывает.

> Я исправил, но вопрос: use в шаблонах вообще никак?


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

> Как создать пустой объект? Убрать все тот же конструктор, ну или значение дефолтные null прописать (не особо надежно и удобно).



$s = new Student();

Так наверно логичнее всего.

> Согласен, но а если метод переименовать, ну типа checkForm


Можно переименовать.

> с редиректом тоже согласен, то есть шлю заголовок с кодом 500?


Редирект это код 3xx. Или я что-то не понял?

> Спрашиваю, чтобы лучше понять и больше уяснить.]


Спрашивай еще, если что.
#664 #1080120
>>1076338

> То есть тут лучше вообще эту строку убрать и сделать заголовки на ошибку сервера, помимо display_erorrs?


Можно выводить подробности ошибки если включен display_errors в конфиге PHP. То есть на dev сервере.

Заголовки (HTTP код 5xx) нужны в любом случае.

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


Книга написана во времена PHP5, когда этой фичи в PHP не было.

> bindValue для 'order by :field :direction' не работает. У меня это проверяется в Pagere'е, хотя, согласен, странно это, лучше в контроллере валидацию делать, у тебя это справедливо замечено.


Я не об этом. Имена полей надо подставлять напрямую в запрос, но перед этим надо в той же самой функции их проверить. Иначе как понять, есть инъекция или нет? Лазать по всему коду? Даже это не гарантирует, что завтра кто-то где-то эту функцию не вызовет без филььтрации параметров от пользователя.

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

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


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

> Состояние в данном случае – это имитация stateful за счет куки и объект будто бы живет на протяжении многих запросов или имеется в виду наличие важных полей?


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

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


Интересная точка зрения. Сгенерировать токен, сохранить в куку, а в БД записать только хеш. Тогда после удаления куки повторно восстановить ее будет невозможно. Можно и так сделать, я не против.

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

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

> А какая есть альтернатива, ну кроме Doctrine и других библиотек (они же вроде тоже поверх PDO)?


Получать массив из БД и написать свою функцию, которая на основе массива создает объект. У тебя одна таблица, это не так и сложно. В больших приложениях, конечно, нужен ORM.

> а какая альтернатива, сеттеры в отдельности?


А почему нет?

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


Сделать метод updateAttributes(array $attrs) - так будет универсальнее всего.

> То есть тут по смыслу не подходит? Лучше !is_null?


Да, когда ты пишешь is_null то видно что ты проверяешь на null, а когда isset - непонятно, может это значит что переменная может не существовать. Запутывает.

> Я исправил, но вопрос: use в шаблонах вообще никак?


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

> Как создать пустой объект? Убрать все тот же конструктор, ну или значение дефолтные null прописать (не особо надежно и удобно).



$s = new Student();

Так наверно логичнее всего.

> Согласен, но а если метод переименовать, ну типа checkForm


Можно переименовать.

> с редиректом тоже согласен, то есть шлю заголовок с кодом 500?


Редирект это код 3xx. Или я что-то не понял?

> Спрашиваю, чтобы лучше понять и больше уяснить.]


Спрашивай еще, если что.
#665 #1080121
>>1076473

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

> Как у пхп с многопоточностью,


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

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

>>1077020

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

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

>>1080092

> (([+]\\s*7)|8)



Можно просто ([+]\\s*7|8)

> \W


Может быть тут лучше указать конкретные символы, а не вообще любые? А то выражение 8 + 1 + 2 + 3 + 4 ... он тоже за номер телефона примет.

А так, в общем, верно.
#666 #1080129
>>1080121
Спасибо большое за проверку
#667 #1080235
А как и где лучше всего делать валидацию? Например, если есть сторонняя библиотека, то нужно создавать класс, унаследованный от класса либы, либо агрегирующий класс либы, в котором все нужные для сущности проверки делаются и дергается это все из контроллеров, или же как-то еще? Кто-то в самой сущности предлагает это делать. Такое вот нашел:
https://stackoverflow.com/questions/39641671/doctrine-entity-validation-at-construct
https://ocramius.github.io/doctrine-best-practices/#/1
https://stackoverflow.com/questions/9744265/validate-a-domain-entity-upon-setting-each-property-or-all-at-once-later
https://stackoverflow.com/questions/9829312/how-to-handle-domain-entity-validation-before-its-persisted
https://stackoverflow.com/questions/9747865/is-it-okay-to-store-a-domain-entitys-mutable-properties-as-a-value-object
https://lostechies.com/jimmybogard/2016/04/29/validation-inside-or-outside-entities/
Еще вопрос: делаю файлообменник, и все вроде замечательно, но почему-то не переписываются дефолтные параметры php.ini на nginx, хотя пишу в конфиге: fastcgi_paramPHP_VALUE"memory_limit = 500M; post_max_size = 400M; upload_max_filesize = 300M"; и client_max_body_size 400m; в блоке http не забыл, однако все равно остается по дефолту, сервер и php-сgi перезапускал, хотя не уверен, что последнее нуждается в этом, запутался уже. Когда меняю глобальный php.ini, все работает, значит проблема в конфиге, причем в phpinfo() есть такое: $_SERVER['PHP_VALUE']memory_limit = 500M; post_max_size = 400M; upload_max_filesize = 300M, а сами параметры не меняются, ошибка заголовка content-length с указанием стандартных 8М. Глобально ставить не хочу, так как желаю разобраться и удобно это на любой location ставить любые параметры, только можно ли отдельный php.ini создать и указать в конфиге nginx или php-cgi, ну в любом случае можно хотя бы через php_value менять (а сами значения в другом файле хранить для читабельности и импортировать)
#668 #1080275
>>1080235

У тебя за nginx стоит php-fpm или Аапч? Почему не пишешь?

Тут http://php.net/manual/ru/install.fpm.configuration.php в примере настройки разделяются символом \n, а не точкой с запятой.

> только можно ли отдельный php.ini создать и указать в конфиге nginx или php-cgi,


Если ты используешь php-fpm, то в его конфиге можно менять настройки PHP: http://php.net/manual/ru/install.fpm.configuration.php

> php-cgi,


я надеюсь, ты не используешь PHP в режиме CGI?

> удобно это на любой location ставить любые параметры,


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

> (а сами значения в другом файле хранить для читабельности и импортировать)


Конфиг нгинкса позволяет инклюды, не знаю как насчет php-fpm.

> А как и где лучше всего делать валидацию?


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

$result = $validator->validate($something);

Часто валидация используется вместе с сохранением/обновлением (и вообще, отдельно не нужна), в этом случае удобно может быть совместить эти операции, тем самым исключая возможность сохранить невалидную сущность:

// валидирует и сохраняет
$result = $service->saveIfValid($entity);

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


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

> Кто-то в самой сущности предлагает это делать.


Так делают в Active Record обычно (в Юи например). В случае Data mapper это непрактично, так как у сущности например нет доступа к БД, который может понадобиться при валидации. Так можно делать только какие-то простые валидации.

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

> Где должна быть валидация


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

> Валидация в конструкторе


Почему в конструкторе? Что делать с результатом валидации? Что делать, если валидация не проходит? Что делать, если мы поменяли какое-то свойство сущности?

> ENTITIES SHOULD ALWAYS BE VALID


Весьма спорная точка зрения. Как это проверять? дергать валидатор после любого изменения? А что, если я меняю несколько свойств, и в процессе изменения сущность временно становится невалидной? по моему, валидацию проще делать на каком-то определенном этапе, например, вставке в БД или вызывать явно из контроллера.

> INVALID STATE SHOULD BE IN A DIFFERENT OBJECT


> (You may need a DTO)


Выглядит как усложнение, если честно

И что самое интересное, презентация не предлангает никакого решения. Зато там надо промотать 20 картинок в начале + какое-то видео.

А вообще, если есть разные подходы, нужно сравнивать преимущества и недостатки и выбирать более подходящий. Редко бывает так, что одно решение работает дял всех случаев.
#668 #1080275
>>1080235

У тебя за nginx стоит php-fpm или Аапч? Почему не пишешь?

Тут http://php.net/manual/ru/install.fpm.configuration.php в примере настройки разделяются символом \n, а не точкой с запятой.

> только можно ли отдельный php.ini создать и указать в конфиге nginx или php-cgi,


Если ты используешь php-fpm, то в его конфиге можно менять настройки PHP: http://php.net/manual/ru/install.fpm.configuration.php

> php-cgi,


я надеюсь, ты не используешь PHP в режиме CGI?

> удобно это на любой location ставить любые параметры,


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

> (а сами значения в другом файле хранить для читабельности и импортировать)


Конфиг нгинкса позволяет инклюды, не знаю как насчет php-fpm.

> А как и где лучше всего делать валидацию?


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

$result = $validator->validate($something);

Часто валидация используется вместе с сохранением/обновлением (и вообще, отдельно не нужна), в этом случае удобно может быть совместить эти операции, тем самым исключая возможность сохранить невалидную сущность:

// валидирует и сохраняет
$result = $service->saveIfValid($entity);

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


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

> Кто-то в самой сущности предлагает это делать.


Так делают в Active Record обычно (в Юи например). В случае Data mapper это непрактично, так как у сущности например нет доступа к БД, который может понадобиться при валидации. Так можно делать только какие-то простые валидации.

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

> Где должна быть валидация


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

> Валидация в конструкторе


Почему в конструкторе? Что делать с результатом валидации? Что делать, если валидация не проходит? Что делать, если мы поменяли какое-то свойство сущности?

> ENTITIES SHOULD ALWAYS BE VALID


Весьма спорная точка зрения. Как это проверять? дергать валидатор после любого изменения? А что, если я меняю несколько свойств, и в процессе изменения сущность временно становится невалидной? по моему, валидацию проще делать на каком-то определенном этапе, например, вставке в БД или вызывать явно из контроллера.

> INVALID STATE SHOULD BE IN A DIFFERENT OBJECT


> (You may need a DTO)


Выглядит как усложнение, если честно

И что самое интересное, презентация не предлангает никакого решения. Зато там надо промотать 20 картинок в начале + какое-то видео.

А вообще, если есть разные подходы, нужно сравнивать преимущества и недостатки и выбирать более подходящий. Редко бывает так, что одно решение работает дял всех случаев.
#669 #1080317
Я другой анон, отвечу >>1080275

>> (You may need a DTO)


> Выглядит как усложнение, если честно


Сложности - это постоянно гадать в каком состоянии сущность, есть ли в ней одни поля и обнулены ли другие, из-за чего в коде гораздо больше assert'ов и проверок вида if (!$entity->property) throw new \LogicException()
Рекомендую всё-таки посмотреть оригинальное видео: https://www.youtube.com/watch?v=WW2qPKukoZY
И есть ещё одно на ту же тему (достаточно одного аудио): https://youtu.be/lfdAwl3-X_c?t=34s

Мне кажется, что $customer->order($product) и $user->like($video) выглядят гораздо читабельнее и естественнее, чем
$likeService->addLike($user, $video) // Читается как "добавить лайк пользователю, видео"

Недавно наткнулся на интересный пример: https://gist.github.com/fesor/dda6c4c37a17509f18c2c9486323d997
Проблема с обновлением нескольких свойств решается с помощью Embeddable доктрины.
#670 #1080399
Котят, какой лучше движок использовать для создания интернет магазина, где наименований от 13к и каждые из них нужно снабдить картинкой с характеристикой.
Wordpress подойдет? Или посоветуйте какая из CMS платформ надежнее для использования, даже если сложна для изучения, все равно только этим и занимаюсь.

Сам подобного сделать не смогу, но чтобы пока функционировал сайт пока основной магазин постепенно встает на ноги, просто хочу чтобы сразу люди как то набирались пока я учусь. Физическая версия магазина уже есть и там если правильно выражаюсь имеется "Клиентская база" района в котором он находится(Делу 4 года уже), сейчас появился второй магазин и он находится в городе, и пока он становится на ноги я хочу создать сайт и потихоньку его совершенствовать, а позднее перекинуть его с движка на свои наработки из головы. Подчеркну: Нет я не свалю с треда как только сделаю то, что мне нужно, не ради этого я изучаю и C, мне нравится эта деятельность
Понятное дело, что все я освоить смогу только лет через пять, но как бы не представиться за этот срок.
#671 #1080400
>>1080399
Да подпись отклеилась KnackerНубяраСишник

Чтобы было понятно.
#672 #1080420
>>1080118

>У куки есть такой параметр как Path (погугли). Возможно, твои авторизационные куки доступны не на всех страницах сайта.


Не, я уже нашёл проблему. В модели User, в findIdentity($id) было return static::findOne($username); вместо return static::findOne(['id' => $id]);
#673 #1080484
Есть реальная задача: простой CRUD, однако проблема с категориями и товаром, решил использовать nested set в реализации от Доктрины (вообще Симфони взял) и весь товар в одной таблице, с характеристиками в jsonb от Postgres. Все понятно, а вот будет ли удобно искать товар по этим характеристикам и фильтровать, а также добавлять новый товар (ну то есть при появлении новой категории товара со своим набором характеристик надо будет лишь добавлять новый контроллер с вьюхой для админки, где будет список свойств-инпутов, и вообще можно новую сущность делать для удобства, так как это нечасто случается, зато БД не меняется – http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/inheritance-mapping.html), вопрос так будет удобно и как добавлять произвольные свойства на отдельный товар?)?
И еще как лучше реализовать недавно просмотренные товары: куках или на localStorage? Есть ли нормальные библиотеки для этого, хотя вроде и так несложно.
И как реализуется поиск с множеством фильтров: диапозон цены, материал, размер? QueryBuilder'ом? Еще про ElasticSearch слышал, но не уверен, что именно он мне нужен.
#674 #1080493
>>1080484
И стоит ли общие для всех товаров характеристики в отдельном от jsonb поле держать (varchar, например)? Типа производитель, или туда вct характеристики одном поле jsonb, ко всем вместе?
#675 #1080510
>>1080399
Вордпресс не бери, из бесплатных можешь взять Opencart. Только заранее посмотри какие плагины тебе нужны, т.к. для первого опенкарта их больше.
#676 #1080524
>>1078654

>- ты поменял что-то в конфиге PHP, например, включил опцию scream http://php.net/manual/ru/book.scream.php


Спасибо, оп. Это у меня xdebug при установке его включил оказывается. Заодно вообще узнал что за скрим такой.
#677 #1080553
Чота не выходит у меня каменный цветочек.

Вот Yii. Я его пытаюсь освоить. И по каждому вопросу читаю, чего умного пишут - и нихрена не понимаю. Значит нужно откатиться в самые основы. Окей. Но и в основах я тоже много чего не понимаю. Значит нужно откатиться к общей теории MVC и ООП. Окей. Но и там много непонятного. Значит нужно откатиться к кондовому php и учить его, начиная с самых основ, не пренебрегая базовыми аргоритмами, типа красно-чёрного древа, сортировки пузырьком и прочего.

Возникает вопрос: программировать-то когда? Как по мне, выучить всё это я не смогу. Просто потому, что без практики теория мертва и быстро забывается. У меня есть в мозгах некий объём памяти, но его явно не хватает. И возникает вопрос: я неправильно вкатываюсь, или просто тупой для программирования? Как бы это понять? Потому что если реально тупой, то и ну его нахрен. Смысл пытаться прыгнуть выше головы? А если не тупой, то значит нужно будет пнять, что делаю неправильно.
#678 #1080557
>>1080553
Да, добавлю. Я полтора года уже "вкатываюсь". Начинал с базового html/css/js/php и постепенне усложненял задачи и методы их решения. Есть три проектика, которые даже работают (хоть и кривые). А с Yii такое ощущение, что достиг потолка.
#679 #1080586
>>1080553
мб я не прав. но смысл по каждому вопросу что то читать. делай проект и пытаясь реализовать там какую то фишку. про неё читай. как раз будет и теория и практика.
#680 #1080654
>>1080510

>Бесплатный


А другие, платные варианты, какие посоветуешь?
#681 #1080807
ОП, как считаешь, хороши ли курсы https://knpuniversity.com/tracks/symfony для изучения данного фреймворка? И вообще, есть ли хорошие англоязычные курсы по php, symfony?
142 Кб, 1544x1065
#682 #1080830
Объясните, пожалуйста, почему, если раскомментировать 14 строку, перестает обновлять свойство?

https://jsfiddle.net/ezr3z202/

Написано же, что при копировании передает по ссылке:

https://www.google.ru/search?q=передача+массива+по+ссылке+js&oq=передача+массива+по+ссылке+js
#683 #1080850
Два часа как вкатился в пэхапэ, есть азарт, есть интерес.
2 вопроса:
1) Почему все хуесосят пыху и восхваляют пайтон? Может все-таки ну его? Цель стоит - как можно быстрее найти работу на 300-400 бачей джуном-макакой-петухом, как вы их там называете.
2) Дошел до урока про циклы, запилил таблицу умножения(без подглядываний!), первый раз пошевелил мозгами за последние года два при этом. Вот линк: https://ideone.com/eiRdA4 . Как её можно было накодить рациональнее и проще?
Атакую дальше.
#684 #1080865
>>1080850
Nihuya ty geniy!
#685 #1080925
>>1080865
Вообще-то нет.

Всё тот же нововкатившийся-недокатившийся.
3 часа ебал мозг как написать строчку в цикле, которая считает +10% ко вкладу каждый год(задача про 16 летнего пиздюка и 10к рублей под 10%). Вот что получилось: https://ideone.com/kfeCSZ . С ответами мануала результаты расходятся, если кто ткнет носом где я проебался в расчетах - буду признателен.
#686 #1080933
>>1080925
Million budet na vklade cherez 49 let.
Vkladchiku ispolnitsja 65 let.
Dojivet.

У тебя там 1000 вместо 10000
#687 #1080966
>>1080933
И то правда, спасибо.

Надругался над задачей про школьника и айфон в кредит: https://ideone.com/00mo1t.
У анона-гуру-опа в примере по-другому она решена, так как я - считается правильным?
П.С. Пока что самое сложное - чисто писать код, чтобы было как у анона все красиво и структурировано, у меня такое чувство, что я хаотично леплю из говна что-то. Всем похуй, но все-таки.
#688 #1080968
>>1080966
Быстрофикс, https://ideone.com/kQ33vy вот эта ссылка.
#689 #1080970
Вопрос возможно глупый. Зачем нужна анонимная функция ? И как ее тогда вызвать? Спасибо!
#690 #1080972
>>1080970
И еще немного добавлю. Вот есть код, который я взял с хабрахабра https://ideone.com/39V8kL
ссылка на статью: https://habrahabr.ru/post/259991/

Немного редактирую его: https://ideone.com/DvFJM2

и ломаю, но почему-то ничего не изменяется, все также значения равны true
https://ideone.com/PL3Hdm
#691 #1080981
>>1080970

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

Создание и вызов обычной функции:

function someFunc($x) { ... }
someFunc(1000);

Создание и вызов анонимной функции:

$someFunc = function ($x) { ... };
$someFunc(1000);

Главные особенности анонимных функций:

- анонимные функции можно сохранять в переменные, складывать в массивы, передавать в функции, возвращать из функций. Например, можно сделать функцию, которая создает и возвращает анонимную функцию
- так как у них нет имени, то одну и ту же функцию можно создать в любом числе экземпляров (а 2 обычные функции с одним и тем же именем создать нельзя)
- способность при создании анонимной функции сохранить значения переменных снаружи функции с помощью слова use и позже использовать их в ней (функция вместе с сохраненными значениями внешних переменных называется замыкание - closure)
- при создании анонимной функции внутри объекта, она сохраняет значение $this, и к нему можно позже обращаться изнутри функции

Есть еще информация тут: https://habrahabr.ru/post/259991/

Зачем они нужны? Разберем пример.

Представь, что у тебя есть склад. На складе лежат товары, у каждого товара есть вес (в кг), цена и название.

Склад можно описать с помощью массива товаров (попробуй). У меня получилось так:

$warehouse = [
['name' => 'картошка', 'weight' => 100, 'price' => 100500],
['name' => 'морковка', 'weight' => 50, 'price' => 5000],
...
];

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

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

function findByName($warehouse, $name) { ... }

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

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

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

- товары с названием на букву "А"
- товары легче 100 кг
- товары, у которых цена за килограмм меньше 10

Как представить в коде и как передать в функцию эти критерии поиска? Как передать условие "вес менее 100 кг"? Тут-то и приходят на помощь анонимные функции. Мы можем выразить критерий поиска в виде анонимной функции, которая получает на вход товар и возвращает true или false в зависимости от того, соответствует товар условию поиска или нет.

Вот пример функции, которая получает на вход товар (массив с информацией об одном товаре) и проверяет, что он весит меньше 100 кг:

$checkWeightIsLessThan100 = function ($item) {
return $item['weight'] < 100;
};

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

$items = findItems($warehouse, $checkWeightLessThan100);

Задание:

1) допиши код findItems, чтобы все это работало
2) прочитай в мануале про array_map и array_filter
3) прочитай в мануале про usort. Эта функция позволяет отсортировать (упорядочить) элементы массива по произвольному критерию. Напиши функцию, которая с помощью usort отсортирует товары на складе, чтобы они шли в таком порядке:

а) сначала группа товаров с ценой менее 1000
б) за ними группа товаров с ценой менее 5000
в) за ними оставшиеся товары

Внутри групп а, б, в товары сортируются по названию (по алфавиту).

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

function createCounter($start) { ... }

$c1 = createCounter(1); // создаем первый счетчик, который начинает отсчет с 1. В $c1 должна записаться анонимная функция, которая при каждом вызове будет возвращать числа, начиная с 1

echo $с1(); // выводит 1
echo $c1(); // выводит 2
echo $c1(); // выводит 3

$c2 = createCounter(0); // создаем вторую независимую функцию-счетчик, считающую с нуля

echo $c2(); // 0
echo $c2(); // 1

// при этом первая функция-счетчик тоже работает:

echo $c1(); // 4
echo $c1(); // 5

Думаю, этого хватит, чтобы получить общее представление об анонимных функциях. Спрашивай, если что-то непонятно.
#691 #1080981
>>1080970

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

Создание и вызов обычной функции:

function someFunc($x) { ... }
someFunc(1000);

Создание и вызов анонимной функции:

$someFunc = function ($x) { ... };
$someFunc(1000);

Главные особенности анонимных функций:

- анонимные функции можно сохранять в переменные, складывать в массивы, передавать в функции, возвращать из функций. Например, можно сделать функцию, которая создает и возвращает анонимную функцию
- так как у них нет имени, то одну и ту же функцию можно создать в любом числе экземпляров (а 2 обычные функции с одним и тем же именем создать нельзя)
- способность при создании анонимной функции сохранить значения переменных снаружи функции с помощью слова use и позже использовать их в ней (функция вместе с сохраненными значениями внешних переменных называется замыкание - closure)
- при создании анонимной функции внутри объекта, она сохраняет значение $this, и к нему можно позже обращаться изнутри функции

Есть еще информация тут: https://habrahabr.ru/post/259991/

Зачем они нужны? Разберем пример.

Представь, что у тебя есть склад. На складе лежат товары, у каждого товара есть вес (в кг), цена и название.

Склад можно описать с помощью массива товаров (попробуй). У меня получилось так:

$warehouse = [
['name' => 'картошка', 'weight' => 100, 'price' => 100500],
['name' => 'морковка', 'weight' => 50, 'price' => 5000],
...
];

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

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

function findByName($warehouse, $name) { ... }

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

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

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

- товары с названием на букву "А"
- товары легче 100 кг
- товары, у которых цена за килограмм меньше 10

Как представить в коде и как передать в функцию эти критерии поиска? Как передать условие "вес менее 100 кг"? Тут-то и приходят на помощь анонимные функции. Мы можем выразить критерий поиска в виде анонимной функции, которая получает на вход товар и возвращает true или false в зависимости от того, соответствует товар условию поиска или нет.

Вот пример функции, которая получает на вход товар (массив с информацией об одном товаре) и проверяет, что он весит меньше 100 кг:

$checkWeightIsLessThan100 = function ($item) {
return $item['weight'] < 100;
};

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

$items = findItems($warehouse, $checkWeightLessThan100);

Задание:

1) допиши код findItems, чтобы все это работало
2) прочитай в мануале про array_map и array_filter
3) прочитай в мануале про usort. Эта функция позволяет отсортировать (упорядочить) элементы массива по произвольному критерию. Напиши функцию, которая с помощью usort отсортирует товары на складе, чтобы они шли в таком порядке:

а) сначала группа товаров с ценой менее 1000
б) за ними группа товаров с ценой менее 5000
в) за ними оставшиеся товары

Внутри групп а, б, в товары сортируются по названию (по алфавиту).

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

function createCounter($start) { ... }

$c1 = createCounter(1); // создаем первый счетчик, который начинает отсчет с 1. В $c1 должна записаться анонимная функция, которая при каждом вызове будет возвращать числа, начиная с 1

echo $с1(); // выводит 1
echo $c1(); // выводит 2
echo $c1(); // выводит 3

$c2 = createCounter(0); // создаем вторую независимую функцию-счетчик, считающую с нуля

echo $c2(); // 0
echo $c2(); // 1

// при этом первая функция-счетчик тоже работает:

echo $c1(); // 4
echo $c1(); // 5

Думаю, этого хватит, чтобы получить общее представление об анонимных функциях. Спрашивай, если что-то непонятно.
#692 #1080983
>>1080972

Во-первых, лучше использовать var_dump или print_r, так как echo выводит только строки или числа, и не может вывести значения true/false.

Во-вторых, надо убрать assert: https://ideone.com/RClA8x

И все начнет работать верно.

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

В самой статье echo assert нету, так что это ты сам придумал такую странную конструкцию.
#693 #1080989
>>1080966

Лучше не использовать транслит, а писать названия переменных по-английски (Google Translate в помощь, если забыл английский). Смотрится ужасно, читать тяжело (а вообще, PHP позволяет писать переменные кирилицей, но не надо так делать).

> for ($teloKredita;$teloKredita > 0;$n++) {


В первой части пишется действие, которое выполняется перед началом цикла. У тебя это $teloKredita - бессмысленная команда, которая ничего не делает и которую ты поставил наугад, не понимая, что она значит. Так не годится.

В твоем случае там надо либо написать $teloKredita = 40000; (а еще лучше так: $teloKredita = 40000, $n = 0; - тогда будет логичнее) либо ничего не писать вообще.

> $teloKredita=($teloKredita*1.03)+1000-$viplata;


Комиссию (1000) и процент лучше было вынести в переменные, чтобы их легко было поменять и чтобы при чтении не возникало вопроса: а что это за 1000?

Число 40000 у тебя вписано 2 раза в код, неудобно его менять.

Также, у тебя есть довольно бессмысленные вычисления:

> $sdacha=$viplata -($viplata+$teloKredita);


Достаточно вспомнить математику и увидим, что $viplata вычитается сама из себя, и остается просто

> $sdacha= -$teloKredita;



Это мы можем объединить со следующей строчкой ($vsego=$zaplatil-$sdacha;) и получится просто $vsego = $zaplatil + $teloKredita;

То есть ты переусложнил код.

Ну и сам алгоритм, вместо ухода в минус, лучше было сделать так:

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

> У анона-гуру-опа в примере по-другому она решена,


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

>>1080925

> for ($money; $money < 1000000; $n++ ) {


Тут бессмысленная первая команда $money, которая ничего не делает с переменной (увы, PHP разрешает такие бессмысленные команды). Логичнее тут сделать присвоение начальных значений переменным, которые используются в цикле (money и n).

Код выровнен неправильно, пропусти его через phpformatter.com

> echo "Million budet na vklade


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

Сам алгоритм верный. Но оформление кода страшноватое.

>>1080850

Если кому-то не нравится PHP, то причины надо спрашивать у них. Я тебе сэкономлю время и дам сразу готовый список: https://habrahabr.ru/post/315152/

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

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

for ($i меняется от 1 до 10) {
for ($j меняется от 1 до 10) {
выводим произведение $i и $j;
}
}

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

Также, ты используешь числа 1 и 11, но лучше писать 1 и 10, чтобы было понятнее.

> $x++ && $n=0;


ЧТо это за конструкция? Как она должна работать? Тут надо использовать if, а не пытаться записать код запутанным способом. && - это оператор, который выполняет код справа только если слева получилось истинное значение ( мануал http://php.net/manual/ru/language.operators.logical.php ) , и твой код эквивалентен этому:

$x++;
if ($x != 0) {
$n = 0;
}

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

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

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

printf("%6s", 100); // выводит 100 + 3 пробела
printf("%6s %6s", 100, 20); // выводит 100, 3 пробела, 20, 4 пробела
printf("%4d", 10); // выводит 2 пробела, за ними 10

%6s значит, что надо вывести строку, добив ее справа пробелами минимум до 6 символов
%6d значит, что надо вывести число, добив его слева пробелами до 6 символов

Мануал: http://php.net/manual/ru/function.printf.php (что значат проценты, описано в мануале по sprintf http://php.net/manual/ru/function.sprintf.php )

Предупреждение: printf корректно добивает пробелами только цифры и латиницу, но не кирилицу (но для этой задачи этого хватит), объяснение: https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md
#693 #1080989
>>1080966

Лучше не использовать транслит, а писать названия переменных по-английски (Google Translate в помощь, если забыл английский). Смотрится ужасно, читать тяжело (а вообще, PHP позволяет писать переменные кирилицей, но не надо так делать).

> for ($teloKredita;$teloKredita > 0;$n++) {


В первой части пишется действие, которое выполняется перед началом цикла. У тебя это $teloKredita - бессмысленная команда, которая ничего не делает и которую ты поставил наугад, не понимая, что она значит. Так не годится.

В твоем случае там надо либо написать $teloKredita = 40000; (а еще лучше так: $teloKredita = 40000, $n = 0; - тогда будет логичнее) либо ничего не писать вообще.

> $teloKredita=($teloKredita*1.03)+1000-$viplata;


Комиссию (1000) и процент лучше было вынести в переменные, чтобы их легко было поменять и чтобы при чтении не возникало вопроса: а что это за 1000?

Число 40000 у тебя вписано 2 раза в код, неудобно его менять.

Также, у тебя есть довольно бессмысленные вычисления:

> $sdacha=$viplata -($viplata+$teloKredita);


Достаточно вспомнить математику и увидим, что $viplata вычитается сама из себя, и остается просто

> $sdacha= -$teloKredita;



Это мы можем объединить со следующей строчкой ($vsego=$zaplatil-$sdacha;) и получится просто $vsego = $zaplatil + $teloKredita;

То есть ты переусложнил код.

Ну и сам алгоритм, вместо ухода в минус, лучше было сделать так:

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

> У анона-гуру-опа в примере по-другому она решена,


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

>>1080925

> for ($money; $money < 1000000; $n++ ) {


Тут бессмысленная первая команда $money, которая ничего не делает с переменной (увы, PHP разрешает такие бессмысленные команды). Логичнее тут сделать присвоение начальных значений переменным, которые используются в цикле (money и n).

Код выровнен неправильно, пропусти его через phpformatter.com

> echo "Million budet na vklade


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

Сам алгоритм верный. Но оформление кода страшноватое.

>>1080850

Если кому-то не нравится PHP, то причины надо спрашивать у них. Я тебе сэкономлю время и дам сразу готовый список: https://habrahabr.ru/post/315152/

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

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

for ($i меняется от 1 до 10) {
for ($j меняется от 1 до 10) {
выводим произведение $i и $j;
}
}

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

Также, ты используешь числа 1 и 11, но лучше писать 1 и 10, чтобы было понятнее.

> $x++ && $n=0;


ЧТо это за конструкция? Как она должна работать? Тут надо использовать if, а не пытаться записать код запутанным способом. && - это оператор, который выполняет код справа только если слева получилось истинное значение ( мануал http://php.net/manual/ru/language.operators.logical.php ) , и твой код эквивалентен этому:

$x++;
if ($x != 0) {
$n = 0;
}

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

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

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

printf("%6s", 100); // выводит 100 + 3 пробела
printf("%6s %6s", 100, 20); // выводит 100, 3 пробела, 20, 4 пробела
printf("%4d", 10); // выводит 2 пробела, за ними 10

%6s значит, что надо вывести строку, добив ее справа пробелами минимум до 6 символов
%6d значит, что надо вывести число, добив его слева пробелами до 6 символов

Мануал: http://php.net/manual/ru/function.printf.php (что значат проценты, описано в мануале по sprintf http://php.net/manual/ru/function.sprintf.php )

Предупреждение: printf корректно добивает пробелами только цифры и латиницу, но не кирилицу (но для этой задачи этого хватит), объяснение: https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md
#694 #1080994
>>1080830

Странный код тут:

> name : ["Hooves"]


Почему имя сделано массивом? Может быть несколько имен? Тогда должно быть не name, а names - логичнее ведь?

> document.getElementById("old").textContent = Derpy.surname;


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

По поводу вопроса. Начнем с теории. Примитивные значения (строки, числа, true, false, null, undefined) всегда копируются и передаются по значению. Объекты (включая массивы, функции, регулярные выражения) всегда передаются по ссылке. Пример:

// Создает в памяти новый массив и записывает ссылку (указатель на массив, идентификатор массива, номер массива) на него в a
var a = [];

// Копирует ссылку на тот же самый массив (а не сам массив) в переменную b
var b = a;

// Добавляет в массив элемент
a.push('test');

console.log(b); // ['test']

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

var Family = {};
var Derpy = {};

// создает где-то в памяти массив №1 и записывает ссылку на него в Family.name
Family.name = ['Hooves'];

// копирует ссылку на массив №1 в Derpy.surname
Derpy.surname = Family.name;

// Изменяет фамилию в массиве №1
Family.name[0] = "Whooves";

// Создает массив №2 и записывает ссылку на него в Family.name
Family.name = ["Whooves"];

// При этом в Derpy.surname по-прежнему остается ссылка на массив №1

То есть конструкция [..] создает новый объект-массив, а оператор '=' копирует ссылку на него в переменную слева.
#694 #1080994
>>1080830

Странный код тут:

> name : ["Hooves"]


Почему имя сделано массивом? Может быть несколько имен? Тогда должно быть не name, а names - логичнее ведь?

> document.getElementById("old").textContent = Derpy.surname;


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

По поводу вопроса. Начнем с теории. Примитивные значения (строки, числа, true, false, null, undefined) всегда копируются и передаются по значению. Объекты (включая массивы, функции, регулярные выражения) всегда передаются по ссылке. Пример:

// Создает в памяти новый массив и записывает ссылку (указатель на массив, идентификатор массива, номер массива) на него в a
var a = [];

// Копирует ссылку на тот же самый массив (а не сам массив) в переменную b
var b = a;

// Добавляет в массив элемент
a.push('test');

console.log(b); // ['test']

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

var Family = {};
var Derpy = {};

// создает где-то в памяти массив №1 и записывает ссылку на него в Family.name
Family.name = ['Hooves'];

// копирует ссылку на массив №1 в Derpy.surname
Derpy.surname = Family.name;

// Изменяет фамилию в массиве №1
Family.name[0] = "Whooves";

// Создает массив №2 и записывает ссылку на него в Family.name
Family.name = ["Whooves"];

// При этом в Derpy.surname по-прежнему остается ссылка на массив №1

То есть конструкция [..] создает новый объект-массив, а оператор '=' копирует ссылку на него в переменную слева.
#695 #1080997
>>1080807

Вообще, мне не нравится, что в первом уроке там есть пункт "ReactJS talks to your API". А ты знаком с ReactJs, с реализацией MVC на клиенте, с SPA? Это требует предварительного изучения темы и какого-то опыта. Я уверен, что этот пункт туда включен только ради популярного ключевого слова, которое часто встречается в вакансиях.

Далее, в этом уроке идет речь про сервисы: https://knpuniversity.com/screencast/symfony-fundamentals

Я сразу предупрежу, что если ты не изучал DI преварительно (бесстыдно прорекламирую свой урок по теме DI https://github.com/codedokode/pasta/blob/master/arch/di.md ), ну и MVC ( https://github.com/codedokode/pasta/blob/master/arch/mvc.md ) то ты плохо вообдще поймешь, зачем нужны сервисы, значем нужен контейнер и это будет выглядеть для тебя как бессмысленное усложнение.

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

Далее идет урок про Доктрину. Опять же, перед ее изучением очень полезно было бы прочитать про паттерны работы с БД, Active Record, Data Mapper ( https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md ), ну и конечно за 40 минут с Доктриной можно только познакомиться, но не изучить ее. Чтобы изучить Доктрину, придется прочесть большую часть официального мануала по ней, не надо строить иллюзий.

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

То есть ты можешь попробовать пройти этот курс, там тебе покажут, что можно делать с Симфони, но читать документацию на сайте Симфони придется все равно. У нас есть задачка в ОП-посте на Симфони про TestHub (посложнее) и про файлообменнник (попроще). Ты мог бы попробовать сделать одну из них, чтобы получить практический опыт, познакомиться с тем, какие сложности возникают при исопльзовании Симфони. Задача на TestHub довольно близка к реальным задачам.
#695 #1080997
>>1080807

Вообще, мне не нравится, что в первом уроке там есть пункт "ReactJS talks to your API". А ты знаком с ReactJs, с реализацией MVC на клиенте, с SPA? Это требует предварительного изучения темы и какого-то опыта. Я уверен, что этот пункт туда включен только ради популярного ключевого слова, которое часто встречается в вакансиях.

Далее, в этом уроке идет речь про сервисы: https://knpuniversity.com/screencast/symfony-fundamentals

Я сразу предупрежу, что если ты не изучал DI преварительно (бесстыдно прорекламирую свой урок по теме DI https://github.com/codedokode/pasta/blob/master/arch/di.md ), ну и MVC ( https://github.com/codedokode/pasta/blob/master/arch/mvc.md ) то ты плохо вообдще поймешь, зачем нужны сервисы, значем нужен контейнер и это будет выглядеть для тебя как бессмысленное усложнение.

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

Далее идет урок про Доктрину. Опять же, перед ее изучением очень полезно было бы прочитать про паттерны работы с БД, Active Record, Data Mapper ( https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md ), ну и конечно за 40 минут с Доктриной можно только познакомиться, но не изучить ее. Чтобы изучить Доктрину, придется прочесть большую часть официального мануала по ней, не надо строить иллюзий.

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

То есть ты можешь попробовать пройти этот курс, там тебе покажут, что можно делать с Симфони, но читать документацию на сайте Симфони придется все равно. У нас есть задачка в ОП-посте на Симфони про TestHub (посложнее) и про файлообменнник (попроще). Ты мог бы попробовать сделать одну из них, чтобы получить практический опыт, познакомиться с тем, какие сложности возникают при исопльзовании Симфони. Задача на TestHub довольно близка к реальным задачам.
#696 #1080998
>>1080553

Делай задачу на студентов из ОП поста тогда. Можно на том же самом Юи. Если с ООП сложности, то в ОП посте есть учебник и в нем глава по ООП с довольно понятным объяснением. Посмотри ее, если тебе все на 100% понятно, то можно конечно и не изучать.

Красно-черные деревья тебе не понадобятся. пока не захочешь понять, как устроены индексы в БД. Полезное знание, но не для твоего нынешнего уровня наверно.
#697 #1081001
>>1080484

> и весь товар в одной таблице, с характеристиками в jsonb от Postgres.


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

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

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

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

Если производительности будет не хватать (если у тебя больше нескольких тысяч товаров), тебе понадобится внешний поисковый демон вроде sphinx или Lucene или аналогичный (ElasticSearch).

> зато БД не меняется


В случае EAV тоже.

> как лучше реализовать недавно просмотренные товары: куках или на localStorage?


Куки так как localStorage не передается на сервер, а значит придется все переусложнять и делать лишние запросы. Ты ведь надеюсь не думал засовывать HTML вертску в localStorage, а только id товаров?

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

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


Я советую сделать объект, представляющий условия поиска (с полями, соответствующими критериям поиска). Это сильно улучшит твой код.
#698 #1081006
>>1080399

>>1080399

Наверняка есть сайты с обзорами и рейтингами CMS, посмотри на них.

>>1080317

> Сложности - это постоянно гадать в каком состоянии сущность, есть ли в ней одни поля и обнулены ли другие


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

> и проверок вида if (!$entity->property) throw new \LogicException()


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

> Недавно наткнулся на интересный пример: https://gist.github.com/fesor/dda6c4c37a17509f18c2c9486323d997


И в этом примере мы видим, сколько тут усложнений:

- не используется присвоение id базой данных, так как поле id не может быть пустым
- используются статические методы (то есть глобальное состояние): EventStore::remember(...) - мы пишем данные непонятно куда. Что будет с ними дальше? Где гарантия что эти изменения будут сохранены и не потеряются? Из кода этого не видно. Мне это напоминает Active Record, где сущность сохраняет сама себя, только тут это делается в классе EventStore. Почему они не используют DI? наверно потому что конструктор тогда будет выглядеть некрасиво и создавать сущности неудобно.
- мы видим некий объект MetaInformation $meta - а это случайно не та самая анемичная модель?
- в конструкторе может быть много аргументов. Тут используются простые сущности, но в реальных проектах у тебя может быть до 40-50 полей у сущности (можно дробить ее на более мелкие сущности, но тут вопрос: ради чего мы это делаем? Чтобы уложиться в используемый подход?).
- тут используется listener. Искренне ненавижу паттерн Observer в серверном коде, так как он усложняет его понимание. Мне лично нравится, когда в коде идет просто последовательность команд.

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

> Мне кажется, что $customer->order($product) и $user->like($video) выглядят гораздо читабельнее и естественнее, чем


> $likeService->addLike($user, $video) // Читается как "добавить лайк пользователю, видео"


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

Вот смотри, с теми же лайками у нас есть как минимум такое АПИ:

- addLike(user, object): ?Error - надо учесть, что метод может вернуть ошибку, и должен проверить разные условия (например, имеет ли право пользователь ставить лайки? не превысил ли дневной лимит лайков? можно ли ставить лайки к этой сущности? не лайкал ли он ее раньше?)
- removeLike(user, object): ?Error
- isLiked(user, object):bool или canAddLike(user, object):bool - чтобы заблокировать кнопку лайка в интерфейсе
- getLikedObjects(user): Likeable[]
- getLikeCount(object): int
- getLikers(object): User[]

Я могу сказать, что лайки относительно простое АПИ. Но даже оно потребует строк 300-400 кода, и ты предлагаешь, видимо, все это АПИ засунуть в класс User? Как минимум getLikers() туда не подойдет по смыслу. Получается, надо разбить его на части и раскидать по разным классам.

Ты упомнянул выше $customer->order($product). Ну во-первых, там будет не $product, а $cart. Даже в самом простом магизине без дисконтных программ и аналитики этот метод делает многое: проверяет пользователя и товары в корзине, резервирует товары, рассылает уведомления. Логика может быть реально сложной и ты всю ее хочешь засунуть в один класс. Ну вот тебе код реальной CMS для интернет магазинов, я думаю, там даже есть примеры описанного тобой подхода, посмотри: https://github.com/magento/magento2

Мне кажется, что удобнее иметь LikeService, который может использовать DI, который предоставляет это АПИ и который знает все о лайках, правилах их установки итд. И в нем иметь простой, понятный код, который легко изучить и поддерживать, без всяких observer. И как следствие, анемичную модель. Мне нравится идея,что слой сервисов реализует определенное внутреннее АПИ, которым пользуются вышележащие слои, например, контроллеры.

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

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

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

> Рекомендую всё-таки посмотреть оригинальное видео


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

Ну и я тут еще кое-что вспомнил. Часто поля по логике могут быть пустыми. Ну например, автор комментария может оставить его от имени пользователя, а может оставить анонимно - и тогда поле author будет
пусто. Или пользователь может заполнить часть полей в форме, сохранить ее, а остальные заполнить позже.
#698 #1081006
>>1080399

>>1080399

Наверняка есть сайты с обзорами и рейтингами CMS, посмотри на них.

>>1080317

> Сложности - это постоянно гадать в каком состоянии сущность, есть ли в ней одни поля и обнулены ли другие


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

> и проверок вида if (!$entity->property) throw new \LogicException()


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

> Недавно наткнулся на интересный пример: https://gist.github.com/fesor/dda6c4c37a17509f18c2c9486323d997


И в этом примере мы видим, сколько тут усложнений:

- не используется присвоение id базой данных, так как поле id не может быть пустым
- используются статические методы (то есть глобальное состояние): EventStore::remember(...) - мы пишем данные непонятно куда. Что будет с ними дальше? Где гарантия что эти изменения будут сохранены и не потеряются? Из кода этого не видно. Мне это напоминает Active Record, где сущность сохраняет сама себя, только тут это делается в классе EventStore. Почему они не используют DI? наверно потому что конструктор тогда будет выглядеть некрасиво и создавать сущности неудобно.
- мы видим некий объект MetaInformation $meta - а это случайно не та самая анемичная модель?
- в конструкторе может быть много аргументов. Тут используются простые сущности, но в реальных проектах у тебя может быть до 40-50 полей у сущности (можно дробить ее на более мелкие сущности, но тут вопрос: ради чего мы это делаем? Чтобы уложиться в используемый подход?).
- тут используется listener. Искренне ненавижу паттерн Observer в серверном коде, так как он усложняет его понимание. Мне лично нравится, когда в коде идет просто последовательность команд.

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

> Мне кажется, что $customer->order($product) и $user->like($video) выглядят гораздо читабельнее и естественнее, чем


> $likeService->addLike($user, $video) // Читается как "добавить лайк пользователю, видео"


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

Вот смотри, с теми же лайками у нас есть как минимум такое АПИ:

- addLike(user, object): ?Error - надо учесть, что метод может вернуть ошибку, и должен проверить разные условия (например, имеет ли право пользователь ставить лайки? не превысил ли дневной лимит лайков? можно ли ставить лайки к этой сущности? не лайкал ли он ее раньше?)
- removeLike(user, object): ?Error
- isLiked(user, object):bool или canAddLike(user, object):bool - чтобы заблокировать кнопку лайка в интерфейсе
- getLikedObjects(user): Likeable[]
- getLikeCount(object): int
- getLikers(object): User[]

Я могу сказать, что лайки относительно простое АПИ. Но даже оно потребует строк 300-400 кода, и ты предлагаешь, видимо, все это АПИ засунуть в класс User? Как минимум getLikers() туда не подойдет по смыслу. Получается, надо разбить его на части и раскидать по разным классам.

Ты упомнянул выше $customer->order($product). Ну во-первых, там будет не $product, а $cart. Даже в самом простом магизине без дисконтных программ и аналитики этот метод делает многое: проверяет пользователя и товары в корзине, резервирует товары, рассылает уведомления. Логика может быть реально сложной и ты всю ее хочешь засунуть в один класс. Ну вот тебе код реальной CMS для интернет магазинов, я думаю, там даже есть примеры описанного тобой подхода, посмотри: https://github.com/magento/magento2

Мне кажется, что удобнее иметь LikeService, который может использовать DI, который предоставляет это АПИ и который знает все о лайках, правилах их установки итд. И в нем иметь простой, понятный код, который легко изучить и поддерживать, без всяких observer. И как следствие, анемичную модель. Мне нравится идея,что слой сервисов реализует определенное внутреннее АПИ, которым пользуются вышележащие слои, например, контроллеры.

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

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

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

> Рекомендую всё-таки посмотреть оригинальное видео


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

Ну и я тут еще кое-что вспомнил. Часто поля по логике могут быть пустыми. Ну например, автор комментария может оставить его от имени пользователя, а может оставить анонимно - и тогда поле author будет
пусто. Или пользователь может заполнить часть полей в форме, сохранить ее, а остальные заполнить позже.
#699 #1081026
>>1081006

>не люблю смотреть видео


Я тоже почему то не люблю смотреть конференции и видео всякие, они отнимают времени больше, чем если бы ты у первоисточника все брал.
#700 #1081040
>>1080553

>И возникает вопрос: я неправильно вкатываюсь, или просто тупой для программирования?


> полтора года уже "вкатываюсь". Начинал с базового html/css/js/php и постепенне усложненял задачи и методы их решения. Есть три проектика, которые даже работают (хоть и кривые).


Хуй знает в чем у тебя проблема. Я такой же ньюфаг, только у меня наоборот было - я нихуя не понимала до того как начала решать задачки типа студентов ОПа, и мне кстати Юи зашел на отлично. Но проблема в том, что ООП и MVC как правило очень хуево объясняют. По части MVC - ну смотри. Главная фишка - отделение логики от ее представление пользователю. Это надо для того, что у тебя не было лапши в коде, и пхпшный код, и верства шаблонов(т.е. страниц сайта) было легко поддерживать - изменять, дополнять и проч.
Модели - это собственно твои данные. Именно в них производятся основные вычисления - работа с БД, всякие там алгоритмы для бизнеса. Тут главное понимать, что они только принимают какие-то данные - как правило параметры для вычислений, и возвращают результат этих вычислений - например выборку из БД, но не отображают их пользователю. Например в том же ЮИ рассказ про модели начинаются с формочек - вот к пример делаешь ты формочку для регистрации нового юзера, вот тебе сразу же модель юзера - там и валидация к примеру. Потом ты берешь эту модель и делаешь еще одну, наследованную от ActiveRecord, только она уже нужна для записи в базу, и так далее.
Вью(представление) - это просто модуль, который рисует html страничку с версткой, которая отображается пользователю. Там должно быть минимум пхпшного кода, только условия и цикли, ну и в зависимости от платформы на которой ты пишешь еще всякие там виджеты могут вставляться напрямую, но никаких вычислений.
Контроллер - это просто кусок приложения, который первым принимает запрос от пользователя(в данном случае это то что он адресную строку напишет) и на его основании решает что делать дальше. В общем виде это выглядит так: 1) Контроллер получает запрос от пользователя и разбирает его; 2) На основании полученных данных он запускает нужные вычисления в моделях 3) Получает готовые данные из моделей 4) Передает их в модуль отображения этих данных, которые потом уже рисуют вывод(html страничку).
На самом деле это все не так уж и сложно, главное базовые правила понять.
#700 #1081040
>>1080553

>И возникает вопрос: я неправильно вкатываюсь, или просто тупой для программирования?


> полтора года уже "вкатываюсь". Начинал с базового html/css/js/php и постепенне усложненял задачи и методы их решения. Есть три проектика, которые даже работают (хоть и кривые).


Хуй знает в чем у тебя проблема. Я такой же ньюфаг, только у меня наоборот было - я нихуя не понимала до того как начала решать задачки типа студентов ОПа, и мне кстати Юи зашел на отлично. Но проблема в том, что ООП и MVC как правило очень хуево объясняют. По части MVC - ну смотри. Главная фишка - отделение логики от ее представление пользователю. Это надо для того, что у тебя не было лапши в коде, и пхпшный код, и верства шаблонов(т.е. страниц сайта) было легко поддерживать - изменять, дополнять и проч.
Модели - это собственно твои данные. Именно в них производятся основные вычисления - работа с БД, всякие там алгоритмы для бизнеса. Тут главное понимать, что они только принимают какие-то данные - как правило параметры для вычислений, и возвращают результат этих вычислений - например выборку из БД, но не отображают их пользователю. Например в том же ЮИ рассказ про модели начинаются с формочек - вот к пример делаешь ты формочку для регистрации нового юзера, вот тебе сразу же модель юзера - там и валидация к примеру. Потом ты берешь эту модель и делаешь еще одну, наследованную от ActiveRecord, только она уже нужна для записи в базу, и так далее.
Вью(представление) - это просто модуль, который рисует html страничку с версткой, которая отображается пользователю. Там должно быть минимум пхпшного кода, только условия и цикли, ну и в зависимости от платформы на которой ты пишешь еще всякие там виджеты могут вставляться напрямую, но никаких вычислений.
Контроллер - это просто кусок приложения, который первым принимает запрос от пользователя(в данном случае это то что он адресную строку напишет) и на его основании решает что делать дальше. В общем виде это выглядит так: 1) Контроллер получает запрос от пользователя и разбирает его; 2) На основании полученных данных он запускает нужные вычисления в моделях 3) Получает готовые данные из моделей 4) Передает их в модуль отображения этих данных, которые потом уже рисуют вывод(html страничку).
На самом деле это все не так уж и сложно, главное базовые правила понять.
#701 #1081042
>>1081040

>я нихуя не понимала


Когда обдвачевался и не можешь определить свой пол.
#702 #1081061
57 Кб, 916x515
#703 #1081086
>>1080994
Вот я об этом и спрашиваю: если бы я передал во второй объект строку, значение бы не обновилось, всё по мануалу. Но я передаю массив, и значение обновляется, всё по мануалу! Но почему в 15 строке происходит также присваивание массива, но значение не обновляется? Вообще не могу понять, и я подозреваю, что это настолько важно — разобраться, что у меня просто всё зудит.
#704 #1081087
>>1081086

DOM (то есть обращение к textContent) тут вообще не при чем. Посмотри внимательно на ту часть кода, что я выписал в своем посте (в ней строка 15 раскомментирована). Ты можешь заменить запись в DOM на console.log - это ничего не поменяет.
#705 #1081094
>>1081040
То, что ты пишешь - это понятно, с этим проблм нет. Проблемы начинаются, когда нужно сделать, например, разграничение доступа по ролям. Чтобы гостю только главная страница, пользователю ве, а товарищу модератору ещё и редактирование всего. Гугл много чего по этой теме выдаёт, но я не осиливаю. Максимум на что меня хватает - это на копипасту примеров, с рулеткой; заработает/не заработает.
98 Кб, 800x599
#706 #1081164
Что это означает? Прочитал в мануале, не до конца понял.
#707 #1081171
>>1081094

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

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

>>1081164

Предлагают настроить какой-то кластер. Кластер - это когда несколько машин с БД, и они синхронизируются друг с другом.
#708 #1081172
http://prntscr.com/h1d95t
а зачем и как завершать скрипт? мы же все равно выше редирект делаем.
#709 #1081174
>>1081171

>Нужно остановиться и попробовать в чем-то разобраться от начал и до конца


Дык вот на это-то у меня мозгов и не хватает. Когда пытаюсь разобраться, погружаюсь в какую-то жопу какого-нибудь метода в потрохах фреймврка и вообще не понимаю, что и почему.
#710 #1081204
>>1080989
Дорогой анон, огромное спасибо за отзывчивость!
Переделал задачу по кредиту следующим образом: https://ideone.com/W7VVDc
2 вопроса:
1) Мне не нравится, что нужно создавать отдельную переменную под 40000, чтобы потом посчитать переплату(так как переменная $bodyLoan(тело кредита) меняется на протяжении всего цикла и я не могу её использовать). Есть какое-то "правильное" решение?
2) Чтобы корректно обозначить месяцы вынужден присваивать n=1;, что тоже кажется костыльным и нелогичным, но ничего лучше не придумал.
Пойду пока траить остальные задачи.
#711 #1081346
>>1081204
Всё тот же анон, не могущий в таблицу умножения.
Таблицу сделал: https://ideone.com/SvBfDo , но вот как столбики расположить с помощью printf - так и не докумекал. Тёмный лес. Пару часов ломал голову - по нулям. Начиная с того, что понятия не имею как вложить "$i x $j = $result" в аргумент функции printf n printf("%6s", n);. И заканчивая чтением мануала, который любезно линканул ОП - голова вообще не воспринимает, что там написано.
#712 #1081429
>>1081346
https://ideone.com/XHw4a2 не это имел в виду?
#713 #1081434
>>1080997
Понял.
Студентов и файлообменник я уже делал. Тестхаб тоже начинал. Но это было где то весной, хочу заново освежить знания по симфони.
Ну в общем ответ на свой вопрос я получил. Пройду курсы. Получу общее представление обо всём, а потом к тестхабу приступлю и уже углублюсь
#714 #1081446
>>1081429
Очень годная подсказка, спасибо!
Но мои лыжи всё равно не едут.
Понятно как сдвинуть столбик влево или вправо, но как его "поднять", чтобы он был на одном уровне с соседним столбиком?
#715 #1081496
Учу php уже два месяца, решаю задачки от ОПа и на кодеварс, но постоянно залезаю в мануал, так как не могу запомнить нужный порядок параметров в функциях, их названия и какие значения они возвращают. Практика не особо помогает, так как я "храню инфу" не в своей голове, а в мануале. Как их можно запомнить? Пока что надумал выписать штук 50-70 на листочек и учить как иностранные слова, лол.
#716 #1081507
>>1081496

Я тоже постоянно открываю гугл, когда пишу код. Если ты поставишь мощную IDE вроде Netbeans или PhpStorm, то там встроен список функций и работает автодополнение по ним, и есть подсказки.

В Sublime Text тоже есть автодополнение по стандартным функциям.
28 Кб, 542x354
#717 #1081517
Сап антуанам. Пытаюсь изучать регексп, процесс идет довольно трудно. Задачка от опа: проверить номера на определенные правила, заменить +7 на 8, и удалить пробелы. Шаблон криво но работает, но главная суть в том что я не могу получить нужные мне ГРУППЫ ЗАХВАТА ($0, $1, $2) в preg_replace например. На скрине видно что первая группа зеленая, вторая красная, а синяя это нулевая, как бы я не ебался с этими скобочками, средние цифры всегда будут синими. Мне по другому переписывать шаблон или тут еще можно что-то сделать?
#718 #1081546
>>1081446
Опять я. Почему implode() не хочет принимать второй параметр $yobamassiv[n]?
И почему, даже если я придумываю йоба-костыль, типа: $randomNota = [$noti[$rng]]; , то цикл срабатывает всего один раз и на выходе добавляется лишь одна нота.
https://ideone.com/PU31m0
#719 #1081553
>>1081546

>Почему implode() не хочет принимать второй параметр $yobamassiv[n]?


Потому что она хочет весь массив, а не его элемент. Внимательней смотри мануал.

>цикл срабатывает всего один раз и на выходе добавляется лишь одна нота.


Цикл срабатывает сколько нужно. Просто, переменная каждый раз перезаписывается.
Трудно судить о логической ошибке, по результату работы цикла. Легче, по результату каждой итерации:
https://ideone.com/9Wf5bR
#720 #1081562
>>1081171
Два чая, лучше помучаться над базой, изучить ее и пройти с закреплением, а потом уже не нужно будет к ней возвращаться, ну лишь в крайних случаях, и то когда вернешься все вспомнишь и не будешь тратить время.
#721 #1081692
Есть годный ресурс для тренировки в sql запросах http://www.sql-ex.ru. Проблема только в том, что сайт 2002г., и соответственно там вырвиглазный инерфейс. Есть что то похожее, но более современное? Наприме с удобной консолькой и все такое.
#722 #1081720
>>1081692

sqlfiddle - это не то? Он правда лежит довольно часто.
#723 #1081728
Ньюфаг в треде. Есть один мой говносайт. При логине выдаются сессионые переменные name и hashedpassword. Собственно, по этим переменным проверяется доступ к контенту для авторизованных пользователей (банальный isset). Мне нужно удалённо разлогинивать выбранных пользователей (т.е. удалять эти переменные unset'ом). Подскажите лучший алгоритм реализации? Я думаю писать в БД флаг, который у пользователя при обновлении страницы проверяется и происходит удаление сессионных переменных, флаг сбрасывается.
#724 #1081780
подскажите по верстке. Пытаюсь разобраться как использовать повторяющиеся блоки в макете. Начал гуглить, но какого-то одного определенного метода нет, везде по разному проблему решают. Что лучше почитать по этой теме, да ещё чтобы с примерами для даунов типа меня
#725 #1081802
>>1081720

>sqlfiddle


Нет. Sql-ex это именно задания по запросам. Задания хорошие, но интрефейс вырвиглазный.
#726 #1081814
>>1081802
Решил вопрос. На сайте можно скачать sql скрипты которые сами тебе все установят, а там уже можно в любой удобной среде писать запросы, я MySQL workbench юзаю. Короче рекомендую эти задачки для ньюфагов.
#727 #1081853
>>1081814

>На сайте можно скачать sql скрипты которые сами тебе все установят


Анон, скинь ссылку. В упор не вижу, где у них дамп скачать.
#728 #1081890
Чем array_walk от array_map отличается? Я мануал читал, но ничего толком не понял, если честно.
#729 #1081894
Привет, по наследству досталась древняя БД на MySQL, интересно как решать подобную задачу по уму.

Есть таблица на 111 гб (5 млн записей), весит так много из-за того, что в каждой записи есть колонка с огромным json-ом вида {{item_id: 1, item_name: '', item_id: 4, item_name: ''}, ...}

Нужно раз в неделю обходить всю эту таблицу и пересчитывать как часто встречается каждый item, то есть на выходе будет что-то вроде
item_id | popularity
1 | 400
2 | 222
...

И вписать эти данные в таблицу Items. Как можно быстрее решить такую задачу? У меня пока только решение в лоб:
1 - достаём из БД данные частями по 5-10 тысяч (только это занимает полторы минуты каждый раз)
2 - на стороне PHP разбираем JSON, обновляем popularity для всех Items в json-е с помощью UPDATE item SET popularity = popularity + 1 WHERE id IN (...)

Есть ещё идея скрипт по определению popularity выполнить один раз и на каждое изменение json-массива триггерить пересчёт popularity только для нескольких item.
#730 #1081902
>>1081814
http://www.sql-ex.ru/db_script_download.php держи. Только там перед use 'computers' надо два тире удалить, тогда нормально запрос отработает. Хз что это такое.
#731 #1081903
>>1081894
Попробуй просто группировкой.
#732 #1081908
>>1081890
array_map проходится по массиву, применяя функцию к каждому элементу, на выходе у array_map новый массив, старый останется нетронутым.
Допустим у тебя есть функция, которая прибавляет к аргументу число 2:
function plus2($arg) {
return $arg + 2;
};

plus2(10); // выдаст 12

Можно применить эту функцию к массиву, если ты хочешь, чтобы все его элементы увеличились на 2:
$arr = [1,2,3];
var_dump(array_map('plus2', $arr)); // выдаст [3,4,5]
var_dump($arr); // выдаст [1,2,3]

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

>>1081903
Нельзя там группировкой, я же пишу, что данные в JSON и разбирать их нужно только на стороне PHP. Используется старая версия MySQL без поддержки JSON Data Type.
#733 #1081926
http://www.askona.ru/matrasy/askona/orgskok/joy.htm
Как они сделали такой выбор размера-цены? На уровне БД это как может выглядеть? Как вообще в БД делаются такие вещи, когда есть много размеров (цветов) и разные цены соответственно?
#734 #1081971
>>1081894

> достаём из БД данные частями по 5-10 тысяч (только это занимает полторы минуты каждый раз)



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

Выборки вида SELECT ... FROM table LIMIT 1000 OFFSET 100000 довольно неэффективны, так как надо пропускать много записей. Гораздо эффективнее использовать выборку по индексированному полю (например, id или времени вставки):

Первый раз делаем SELECT ... FROM table LIMIT 1000 и запоминаем id последней записи
Второй раз делаем SELECT ... FROM table WHERE id > :lastId LIMIT 1000 и снова берем id последней записи
И так далее.

Статьи

http://use-the-index-luke.com/no-offset
https://habrahabr.ru/post/217521/
https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
https://ruhighload.com/post/Paging+using+MySQL

Далее, обновление тоже можно оптимизировать. Запрос на обновление создает неявную транзакцию и коммитить транзакцию на каждую строчку может быть неэффективно. выгоднее может быть открыть транзакцию, обновить N (N ~ 1000, подбирается опытным путем) строчек и закоммитить (гугли optimise bulk updat mysql).

Ну и разумеется, неэффективно обновлять одну и ту же строчку несколько раз. Надо на стороне PHP группировать данные и делать UPDATE ... SET x = x + N вместо нескольких запросов.

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

И еще конечно остаются очевидные варианты в виде денормализации данных, вынесению из JSON во внешние таблицы.

Я работал с таблицами такого объема и конечно неколько минут на выборку (если там не сложный запрос) это конечно перебор. У тебя ведь просто выборка через SELECT ... FROM table без хитрых джойнов и условий?
#734 #1081971
>>1081894

> достаём из БД данные частями по 5-10 тысяч (только это занимает полторы минуты каждый раз)



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

Выборки вида SELECT ... FROM table LIMIT 1000 OFFSET 100000 довольно неэффективны, так как надо пропускать много записей. Гораздо эффективнее использовать выборку по индексированному полю (например, id или времени вставки):

Первый раз делаем SELECT ... FROM table LIMIT 1000 и запоминаем id последней записи
Второй раз делаем SELECT ... FROM table WHERE id > :lastId LIMIT 1000 и снова берем id последней записи
И так далее.

Статьи

http://use-the-index-luke.com/no-offset
https://habrahabr.ru/post/217521/
https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
https://ruhighload.com/post/Paging+using+MySQL

Далее, обновление тоже можно оптимизировать. Запрос на обновление создает неявную транзакцию и коммитить транзакцию на каждую строчку может быть неэффективно. выгоднее может быть открыть транзакцию, обновить N (N ~ 1000, подбирается опытным путем) строчек и закоммитить (гугли optimise bulk updat mysql).

Ну и разумеется, неэффективно обновлять одну и ту же строчку несколько раз. Надо на стороне PHP группировать данные и делать UPDATE ... SET x = x + N вместо нескольких запросов.

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

И еще конечно остаются очевидные варианты в виде денормализации данных, вынесению из JSON во внешние таблицы.

Я работал с таблицами такого объема и конечно неколько минут на выборку (если там не сложный запрос) это конечно перебор. У тебя ведь просто выборка через SELECT ... FROM table без хитрых джойнов и условий?
#735 #1081974
>>1081926

Либо там есть таблица цен-размеров, где хранятся строки вида:

id товара | id размера (или сам размер) | цена

Либо там цена как-то считается просто по формуле.

А что сложного-то?
#736 #1081981
>>1081894

Кстати, могу поделиться еще одной хитростью. Если у тебя есть сфинкс (sphinx search), то он выполняет группировки в несколько раз (иногда раз в 10-20) быстрее mysql. То есть если есть большая таблица (как у тебя) и надо например посчитать, сколько раз там встречается то или иное значение:

SELECT x, COUNT(*) FROM t GROUP BY x;

То сфинкс может оказаться быстрее. Хотя по идее и mysql и сфинксу нужно сделать полный обход таблицы, но у сфинкса это получается быстрее , может он как-то данные эффективнее в памяти хранит, не знаю, но разница может быть приличной, раз в 10-20. Мне кажется, это связано с тем, что в сфинксе просто меньше данных, которые надо обойти.
#737 #1081986
Могу в жс, как по-быстрому в пхп вкатиться?
#738 #1082015
Никак не могу разбить в текст регулярки на элементы массива.

Через preg_split просто вырезает кусок из текста.
#739 #1082040
>>1082015
текст под регулярку*

задание из темы повторим.

Но я чет передумал, не отвечайте мне.

Хочу додуматься сам
#740 #1082045
>>1081974
Я так и думал, но вопрос: как такие промежуточные таблицы в ORM мапятся, но то есть на одну сущность или на две?
#741 #1082050
Это самое. Если лопается голова от элементарных задач опа на строки и массивы, потому что ты не способен охватить мысленно весь алгоритм, так сбиваешься постоянно, когда пытаешься его продумать - это нормально? Или я проверку не прошел и мне не стоит заниматься программированием? Этот скилл прокачается, если я буду задрачивать задачки?

Задачка ОПА про стихосложение, например:
https://ideone.com/bFOly8
Ебал ей голову себе пол дня, в итоге сами видите че. Я безнадежен? Как вылечить тротлинг мозга?
Я правда хочу осилить хотя бы рублёвое пиэйчпи, готов ебашить сутки напролет, благо времени куча. Как расшевелить мозги? Может логические задачки какие порешать, или книги про алгоритмы почитать?
#742 #1082056
>>1082045

Наверно зависит от ORM. В Доктрине одна таблица это одна сущность, значит на таблицу цен нужен отдельный класс.

Не понимаю, в чем тут сложность. В принципе, никто не запрещает добавить метод получения всех цен в класс товара так, что про дополнительную таблицу даже знать не надо.
#743 #1082067
>>1082050

>Этот скилл прокачается, если я буду задрачивать задачки?


Конечно, больше практики.
#744 #1082164
Тут сидят C/C++ программисты?
#745 #1082167
>>1082164
Вряд ли. Для них есть отдельные треды.
Если ты изучаешь C - добро пожаловать сюда: https://2ch.hk/pr/res/1074988.html (М) ,
C++ ? Тогда сюда https://2ch.hk/pr/res/1065530.html (М)
someApprentice #746 #1082173
>>1079886

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


У меня есть обработка ошибок в готовом черновом коде, но она идёт немного запутанным способом

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L62

Ошибка отправляется назад в backend. Я это исправлю в скоре.

>unhandledPromise


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

var promise = new Promise(function (resolve, reject) {
if (something) {
resolve();
} else {
//unhandledPromise
reject();
}
});

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


Я впервые пишу приложение на js и впервые работаю с его библеотеками, и у меня ещё большая путаница в голове с Обещаниями. Можно подсказку как узнавать что ошибка произошла? То есть например, в случае с ajax мы на вход функции onRejected отправляем jqXHR и textStatus. Насколько я понимаю, они (аргументы функции) появляются в самом коде метода ajax и возвращаются с помощью Promise.reject(jqXHR, textStatus), я правильно понимаю? Из чего следует, что подробности об ошибке Обещания нужно искать в самом коде приложения. Это так?

>Также, тут есть недостаток. Расшифровка сообщений - асинхронная, но тут мы ждем, пока они не расшифруются все. Можно написать более продвинутую версию кода:


>decryptedPromise.done(function (decrypted) {


>.done()


У стандартного ES6 класса Promise нету метода .done().

>Здесь мы видим громоздкую тяжелочитаемую конструкцию, а это верный признак проблемы, которая решается "добавлением еще одной абстракции". Попробуем применить тут реактивное программирование. Я напомню, что там есть объект Observable, который представляет собой поток каких-то событий. У нас будет 2 потока: поток, в который прибывают зашифрованные сообщения, и поток, в который приходя расшифрованные сообщения.


Я ещё только ознакамливаюсь с паттерном Observable и реактивным порграммированием. У меня в совокупности с вашими замечаниями ( https://gist.github.com/codedokode/6dfde1f0ec3d895bc940b67e7919cc29 ), в которых вы упоминали об этом, есть к этому вопросы, которые я задам после того как напишу приложение без модели. Причина по которой я хочу написать приложение без модели, это потому, что я хочу на собственом опыте хочу понять в чём разница между приложением с моделью и приложением с ней.

>>1080119

>Думаю, речь об этих плагинах, хотя не уверен: https://dev.mysql.com/doc/refman/5.7/en/authentication-plugins.html


Я должен оговориться, что в Debian stretch заместо mysql идёт MariaDB. Я не знаю как теперь у mysql с этим обстоят дела. Наверно, нужно проверить.

>Если ты используешь phpMyAdmin, проверь, что он не доступен снаружи. Были раньше случаи, когда там находили дыры, и я бы не стал его выставлять в интернет вообще. Ну или хотя бы закрыл HTTP авторизацией, доверия к его коду у меня нету. И защиты от подбора паролей там по моему тоже нет.


Я не пользуюсь им, потому что мне кажется что такого рода приложения говорят о некомпетенции программиста, потому что доступ к mysql можно получить и через консоль. То что вы тоже не доверияте ему говорит о том, что моя интуиция мне подсказывает правильно.
someApprentice #746 #1082173
>>1079886

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


У меня есть обработка ошибок в готовом черновом коде, но она идёт немного запутанным способом

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L62

Ошибка отправляется назад в backend. Я это исправлю в скоре.

>unhandledPromise


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

var promise = new Promise(function (resolve, reject) {
if (something) {
resolve();
} else {
//unhandledPromise
reject();
}
});

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


Я впервые пишу приложение на js и впервые работаю с его библеотеками, и у меня ещё большая путаница в голове с Обещаниями. Можно подсказку как узнавать что ошибка произошла? То есть например, в случае с ajax мы на вход функции onRejected отправляем jqXHR и textStatus. Насколько я понимаю, они (аргументы функции) появляются в самом коде метода ajax и возвращаются с помощью Promise.reject(jqXHR, textStatus), я правильно понимаю? Из чего следует, что подробности об ошибке Обещания нужно искать в самом коде приложения. Это так?

>Также, тут есть недостаток. Расшифровка сообщений - асинхронная, но тут мы ждем, пока они не расшифруются все. Можно написать более продвинутую версию кода:


>decryptedPromise.done(function (decrypted) {


>.done()


У стандартного ES6 класса Promise нету метода .done().

>Здесь мы видим громоздкую тяжелочитаемую конструкцию, а это верный признак проблемы, которая решается "добавлением еще одной абстракции". Попробуем применить тут реактивное программирование. Я напомню, что там есть объект Observable, который представляет собой поток каких-то событий. У нас будет 2 потока: поток, в который прибывают зашифрованные сообщения, и поток, в который приходя расшифрованные сообщения.


Я ещё только ознакамливаюсь с паттерном Observable и реактивным порграммированием. У меня в совокупности с вашими замечаниями ( https://gist.github.com/codedokode/6dfde1f0ec3d895bc940b67e7919cc29 ), в которых вы упоминали об этом, есть к этому вопросы, которые я задам после того как напишу приложение без модели. Причина по которой я хочу написать приложение без модели, это потому, что я хочу на собственом опыте хочу понять в чём разница между приложением с моделью и приложением с ней.

>>1080119

>Думаю, речь об этих плагинах, хотя не уверен: https://dev.mysql.com/doc/refman/5.7/en/authentication-plugins.html


Я должен оговориться, что в Debian stretch заместо mysql идёт MariaDB. Я не знаю как теперь у mysql с этим обстоят дела. Наверно, нужно проверить.

>Если ты используешь phpMyAdmin, проверь, что он не доступен снаружи. Были раньше случаи, когда там находили дыры, и я бы не стал его выставлять в интернет вообще. Ну или хотя бы закрыл HTTP авторизацией, доверия к его коду у меня нету. И защиты от подбора паролей там по моему тоже нет.


Я не пользуюсь им, потому что мне кажется что такого рода приложения говорят о некомпетенции программиста, потому что доступ к mysql можно получить и через консоль. То что вы тоже не доверияте ему говорит о том, что моя интуиция мне подсказывает правильно.
#747 #1082176
>>1082167
Да ладно, как будто я и не знал.
#748 #1082181
>>1082167
Нее спасибо, там какие то ублюдки агрессивные сидят, нет уж, останусь тут.
#749 #1082249
Сейчас laravel самый "хайповый" фреймворк выходит?
#750 #1082284
>>1082249
Типа того. Скоро его место phalcon займет. А вообще они не нужны когда ты можешь в симфони/доктрину.
#751 #1082358
>>1081986
бамп вопросу
#752 #1082385
Аноны (а лучше ОП) посмотрите, пожалста, решение задачи "Вектор" с учебника ОПа. Что исправить, что подправить, что правильно?
http://sandbox.onlinephpfunctions.com/code/c02804add7e68d607e821d536ba1c7664c4ff505
#753 #1082388
>>1082358
Тут все вкатываются через учебник в шапке.
#754 #1082416
Почему не работает запроса вида:

select distinct
maker
from
product
where
product.type IN ('PC') AND product.type NOT IN ('Laptop')
Я не понимаю как работает NOT IN?
#755 #1082432
>>1082050
Бамп конкретно по решению задачи, какие замечания?
#756 #1082451
>>1082416

Мануал https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_not-in

> expr NOT IN (value,...)



> This is the same as NOT (expr IN (value,...)).



Проверяет, что значение поля НЕ входит в список. В твоем случае равносильно type <> 'Laptop'.

Только надо учесть что в случае NULL там может быть особое поведение. Например сравнение NULL = NULL вернет не 1 (истина), а UNKNOWN если я не путаю. Мануал: https://dev.mysql.com/doc/refman/5.7/en/working-with-null.html
#757 #1082515
Аноны, переходите в новый тред >>1082507 (OP)

Тут будут только ответы на старые посты. Если вас пропустили - напомните о себе в новом треде.

>>1082050

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

-----

Дан список товаров на складе вида (название, вес), например:

ром, 50 кг
сахар, 100 кг
ром, 35 кг
сахар, 20 кг
болты, 200 кг

Как видно, некоторые товары повторяются. Напиши программу, которая принимает на вход список товаров (в каком виде - придумай сам) и выводит сгруппированный по товарам список, для примера выше это будет:

ром, 85 кг
сахар, 120 кг
болты, 200 кг

-----

Дан текст, найди в нем слова, которые встречаются больше 1 раза. Текст может содержать слова на русском языке, пробелы между ними и знаки препинания. Пример текста: "Ехал Грека через реку, видит Грека - в реке рак." (повторяется слово "Грека").

-----

Дан текст, найди в нем слова, в которых идет 3 или более согласных подряд.

-----

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

$slovar = [$word1,$word2,$word3, ["\n"], $word4,$word5];

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

для (каждого отдельного массива в $slovar) {
берем случайное слово из массива;
выводим его;
}

Ну и конкретно по коду:

> if ($i/3 == 1) {


Не проще написать if ($i == 3) ?

Ну и циклы как-то переусложнены.
#757 #1082515
Аноны, переходите в новый тред >>1082507 (OP)

Тут будут только ответы на старые посты. Если вас пропустили - напомните о себе в новом треде.

>>1082050

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

-----

Дан список товаров на складе вида (название, вес), например:

ром, 50 кг
сахар, 100 кг
ром, 35 кг
сахар, 20 кг
болты, 200 кг

Как видно, некоторые товары повторяются. Напиши программу, которая принимает на вход список товаров (в каком виде - придумай сам) и выводит сгруппированный по товарам список, для примера выше это будет:

ром, 85 кг
сахар, 120 кг
болты, 200 кг

-----

Дан текст, найди в нем слова, которые встречаются больше 1 раза. Текст может содержать слова на русском языке, пробелы между ними и знаки препинания. Пример текста: "Ехал Грека через реку, видит Грека - в реке рак." (повторяется слово "Грека").

-----

Дан текст, найди в нем слова, в которых идет 3 или более согласных подряд.

-----

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

$slovar = [$word1,$word2,$word3, ["\n"], $word4,$word5];

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

для (каждого отдельного массива в $slovar) {
берем случайное слово из массива;
выводим его;
}

Ну и конкретно по коду:

> if ($i/3 == 1) {


Не проще написать if ($i == 3) ?

Ну и циклы как-то переусложнены.
#758 #1082529
>>1082385

Код надо было сдвинуть влево на 4 пробела, после <?php отступ не добавляется.

@access private можно не писать, это писали в PHP4, когда не было ключевых слов private/public, а сейчас они есть и дублировать их не требуется.

> Get an array of employees


> @return array


Лучше писать @return Employee[] (мануал http://docs.phpdoc.org/guides/types.html#arrays )

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

public function getDepartmentName():string { ... }

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

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

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

> private function addEmployeeToDepartment(


> switch ($profession) {


В таких случаях стоит всегда добавлять default с выбросом исключения для отлова ошибок.

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

$header = ['Департамент', 'сотр.', 'тугр.', 'кофе'];
$rows[] = [
$dep->getName(),
$dep->getEmployeeCount(),
...
];

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

Не надо много раз писать try/catch, можно сделать это 1 раз, а можно вообще не ловить исключение, так как по умолчанию PHP его выведет сам.

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

Ждем еще антикризисные меры.

Если захочешь еще попрактиковать ООП, у меня есть задачка про гостиницу:

------

Есть Гостиница, в ней есть Номера. Для каждого Номера известен его номер, количество Гостей, которое в него влезет, а также цена за сутки. В Гостиницу приезжают Гости. Нужно сделать ООП-модель Гостиницы с такими возможностями:

- получить список свободных номеров на определенную дату
- получить список свободных номеров, которые будут свободны в определенный диапазон дат (от A до B)
- дан список Гостей и диапазон дат, в которые они хотели бы заселиться. Необходимо подобрать им самый дешевый и маленький Номер, который их вместит и который свободен в это время.
- то же самое, но при отстутствии одного подходящего номера для Гостей разрешается заселить их в несколько номеров, опять же, начиная с самых дешевых. Например, приехало 3 Гостя, но все 3-местные номера заняты и мы выделяем 2 2-местных, или 3 1-местных или 1-местный + 2-местный.
- зарегистрировать проживание данных Гостей в данных Номерах на данный период
- получить историю заселения Номера (кто в нем когда жил)
- получить историю заселения Гостя (в каких номерах он жил)
- получить статистику доходов Гостиницы за данный диапазон дат (в день A отдель заработал X тугриков, в день B - Y тугриков и так далее)

----

И если хочешь попрактиковаться еще, в учебнике была задача про вычисление выражения. Усложненная версия этой задачи - вычислить выражение с учетом приоритетов операций, добавить работу с обычными дробями (вроде 1/3) без потерь точности, все это на ООП. Хотя если честно, это может отнять время, так что может и не стоит делать.
#758 #1082529
>>1082385

Код надо было сдвинуть влево на 4 пробела, после <?php отступ не добавляется.

@access private можно не писать, это писали в PHP4, когда не было ключевых слов private/public, а сейчас они есть и дублировать их не требуется.

> Get an array of employees


> @return array


Лучше писать @return Employee[] (мануал http://docs.phpdoc.org/guides/types.html#arrays )

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

public function getDepartmentName():string { ... }

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

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

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

> private function addEmployeeToDepartment(


> switch ($profession) {


В таких случаях стоит всегда добавлять default с выбросом исключения для отлова ошибок.

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

$header = ['Департамент', 'сотр.', 'тугр.', 'кофе'];
$rows[] = [
$dep->getName(),
$dep->getEmployeeCount(),
...
];

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

Не надо много раз писать try/catch, можно сделать это 1 раз, а можно вообще не ловить исключение, так как по умолчанию PHP его выведет сам.

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

Ждем еще антикризисные меры.

Если захочешь еще попрактиковать ООП, у меня есть задачка про гостиницу:

------

Есть Гостиница, в ней есть Номера. Для каждого Номера известен его номер, количество Гостей, которое в него влезет, а также цена за сутки. В Гостиницу приезжают Гости. Нужно сделать ООП-модель Гостиницы с такими возможностями:

- получить список свободных номеров на определенную дату
- получить список свободных номеров, которые будут свободны в определенный диапазон дат (от A до B)
- дан список Гостей и диапазон дат, в которые они хотели бы заселиться. Необходимо подобрать им самый дешевый и маленький Номер, который их вместит и который свободен в это время.
- то же самое, но при отстутствии одного подходящего номера для Гостей разрешается заселить их в несколько номеров, опять же, начиная с самых дешевых. Например, приехало 3 Гостя, но все 3-местные номера заняты и мы выделяем 2 2-местных, или 3 1-местных или 1-местный + 2-местный.
- зарегистрировать проживание данных Гостей в данных Номерах на данный период
- получить историю заселения Номера (кто в нем когда жил)
- получить историю заселения Гостя (в каких номерах он жил)
- получить статистику доходов Гостиницы за данный диапазон дат (в день A отдель заработал X тугриков, в день B - Y тугриков и так далее)

----

И если хочешь попрактиковаться еще, в учебнике была задача про вычисление выражения. Усложненная версия этой задачи - вычислить выражение с учетом приоритетов операций, добавить работу с обычными дробями (вроде 1/3) без потерь точности, все это на ООП. Хотя если честно, это может отнять время, так что может и не стоит делать.
#759 #1082530
>>1082432
Попробовал осилить палиндром.
Вот только на ideone видимо открутили mb модуль.
Нашел альтернативу: http://phpfiddle.org/
Но без понятия как линковать оттуда код, поэтому линк бросаю на ideone:
https://ideone.com/hlU88a
Может кому-то не лень будет копипастнуть оттуда код.
#760 #1082531
>>1082015

Ты имеешь в виду что? Разбить текст на массив предложений? На массив слов?

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

Если на слова, то надо разбивать по не-буквам (так как слово это последовательность букв).
#761 #1082535
>>1081780

Что ты имеешь в виду? Блоки, которые повторяются на одной странице или на разных страницах сайта?

Вообще, есть концепция верстки независимыми блоками, так, что любой блок можно легко взять и перенести в другое место сайта например, она называется БЭМ: https://ru.bem.info/methodology/quick-start/

>>1081728

Тебе надо либо хранить сессии PHP в БД либо сделать аналог сессий с хранением в БД. Как иначе-то?

>>1081546

Код какой-то странный:

> $randomNota = [$noti[$rng]];


Зачем создавать массив из единственного элеимента?

Тебе надо сделать так:

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

$notes = [];
...
$notes[] = 'do';
....
echo implode(' ', $notes);

Алсо на западе ноты часто обозначают просто буквами (c = до, d = ре и так далее). Ну или ты можешь просто писать их по-русски.
#761 #1082535
>>1081780

Что ты имеешь в виду? Блоки, которые повторяются на одной странице или на разных страницах сайта?

Вообще, есть концепция верстки независимыми блоками, так, что любой блок можно легко взять и перенести в другое место сайта например, она называется БЭМ: https://ru.bem.info/methodology/quick-start/

>>1081728

Тебе надо либо хранить сессии PHP в БД либо сделать аналог сессий с хранением в БД. Как иначе-то?

>>1081546

Код какой-то странный:

> $randomNota = [$noti[$rng]];


Зачем создавать массив из единственного элеимента?

Тебе надо сделать так:

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

$notes = [];
...
$notes[] = 'do';
....
echo implode(' ', $notes);

Алсо на западе ноты часто обозначают просто буквами (c = до, d = ре и так далее). Ну или ты можешь просто писать их по-русски.
#762 #1082536
>>1080981

>Если ты знаешь ООП.


К сожалению, еще не начал изучать.

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



Вот: https://ideone.com/XhydTt#stdin. Правильно ли дописал? А то может я неправильно понял. Если правильно, то можно было как-то лучше? Спасибо.

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



И что будет если вернется true ? false ?

что будет если искать товар с параметром false?

Я обязательно сейчас буду пытаться понять, просто кусочек написал, чтобы разбираться потихоньку
#763 #1082538
>>1081517

Когда ты пишешь выражение вроде

(....){10}

То в круглые скобки будет захвачена только одна цифра (скорее всего последняя). Это легко исправить, добавив еще одни круглые скобки:

((...){10})

А внутреннии скобки можно сделать незахватывающими.
#764 #1082547
>>1081204

> Мне не нравится, что нужно создавать отдельную переменную под 40000, чтобы потом посчитать переплату(так как переменная $bodyLoan(тело кредита) меняется на протяжении всего цикла и я не могу её использовать). Есть какое-то "правильное" решение?



Можно присвоить в начале программы $bodyLoad = 40000 и дальше ее же уменьшать. Можно сделать 2 переменных - начальное, неизменное значение и текущее значение долга.

В коде у тебя числа 40 000 и 5 000 повторяются 2 раза - это стоит исправить.

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

> Total for the loan was paid: 56270.186744521 RUB


А должно быть 61270. Ты там чуть ошибся с формулами.

>>1081346

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

Посмотрим на пример таблицы:

...1...2...3...4
...5...6...7...8

Как такую таблицу вывести? Если присмотреться, видно, что перед каждым числом стоит по 3 пробела, а в общем под одно число отведено 4 символа (3 пробела + 1 цифра). Мы выводим 4 числа, затем переводим строку и выводим еще 4 числа:

printf("%4d", 1);
printf("%4d", 2);
printf("%4d", 3);
printf("%4d", 4);
echo "\n";
printf("%4d", 5);
printf("%4d", 6);
printf("%4d", 7);
printf("%4d", 8);

%4d - 4 здесь значит ширину поля, а d - значит, что мы выводим число.

Вот тебе надо сделать примерно то же, но не копипастой одной и той же строки, а циклом.

>>1081174

Можешь в треде спросить, правда не сразу, но ответят.
#764 #1082547
>>1081204

> Мне не нравится, что нужно создавать отдельную переменную под 40000, чтобы потом посчитать переплату(так как переменная $bodyLoan(тело кредита) меняется на протяжении всего цикла и я не могу её использовать). Есть какое-то "правильное" решение?



Можно присвоить в начале программы $bodyLoad = 40000 и дальше ее же уменьшать. Можно сделать 2 переменных - начальное, неизменное значение и текущее значение долга.

В коде у тебя числа 40 000 и 5 000 повторяются 2 раза - это стоит исправить.

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

> Total for the loan was paid: 56270.186744521 RUB


А должно быть 61270. Ты там чуть ошибся с формулами.

>>1081346

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

Посмотрим на пример таблицы:

...1...2...3...4
...5...6...7...8

Как такую таблицу вывести? Если присмотреться, видно, что перед каждым числом стоит по 3 пробела, а в общем под одно число отведено 4 символа (3 пробела + 1 цифра). Мы выводим 4 числа, затем переводим строку и выводим еще 4 числа:

printf("%4d", 1);
printf("%4d", 2);
printf("%4d", 3);
printf("%4d", 4);
echo "\n";
printf("%4d", 5);
printf("%4d", 6);
printf("%4d", 7);
printf("%4d", 8);

%4d - 4 здесь значит ширину поля, а d - значит, что мы выводим число.

Вот тебе надо сделать примерно то же, но не копипастой одной и той же строки, а циклом.

>>1081174

Можешь в треде спросить, правда не сразу, но ответят.
#765 #1082548
>>1081172

die(), exit(), может быть return - зависит от того, как твой скрипт написан.

>>1082173

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

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

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

> У меня есть обработка ошибок


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

>>unhandledPromise


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


Не, это событие https://developer.mozilla.org/en-US/docs/Web/Events/unhandledrejection

У window есть событие error, которое происходит при непойманном исключении. Если в промисе произошло reject и оно не было обработано, то сработает событие unhandledrejection. Можно с его помощью централизованно собирать ошибки. Но проблема конечно в том, что это ловит глобально все ошибки, не позволяя например ловить их только в рамках одного класса. И в ФФ судя по MDN не работает. Обработка ошибок в промисах (по моему личному мнению) сделана неудачно.

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

var x = getMessages().then(null, function (error) {
// исключение перехватится и будет возвращено внутри промиса x
throw new Error(error);
});

> То есть например, в случае с ajax мы на вход функции onRejected отправляем jqXHR и textStatus.


Если произойдет ошибка, то jQuery вызовет onRejected, верно.

> Насколько я понимаю, они (аргументы функции) появляются в самом коде метода ajax и возвращаются с помощью Promise.reject(jqXHR, textStatus), я правильно понимаю?


Нет, в коде ошибка, в reject информация об ошибке передается одним аргументом-исключением:

reject(new RequestError(textStatus));

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


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

> У стандартного ES6 класса Promise нету метода .done().


Это я наверно из PHP взял. Тогда then().

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


Ок

> в Debian stretch заместо mysql идёт MariaDB.


Так это форк mysql (как и percona), и я думаю, там процентов на 95 тот же самый код.

> мне кажется что такого рода приложения говорят о некомпетенции программиста


Ну я бы не был столь категоричен, в GUI в принципе тоже есть свои преимущества (например, таблицы можно выводить более качественно, особенно большие, прокрутка лучше реализуется). Веб-интерфейс конечно имеет свои недостатки - например, нельзя отменить долго выполняющийся запрос (а в консоли можно через Ctrl + C). Но есть и другие GUI клиенты, и в принципе, если кому-то нравится ими пользоваться, почему бы и нет. Там например можно сохранять часто выполняемые запросы, можно редактировать таблицы визуально и тд.
#765 #1082548
>>1081172

die(), exit(), может быть return - зависит от того, как твой скрипт написан.

>>1082173

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

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

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

> У меня есть обработка ошибок


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

>>unhandledPromise


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


Не, это событие https://developer.mozilla.org/en-US/docs/Web/Events/unhandledrejection

У window есть событие error, которое происходит при непойманном исключении. Если в промисе произошло reject и оно не было обработано, то сработает событие unhandledrejection. Можно с его помощью централизованно собирать ошибки. Но проблема конечно в том, что это ловит глобально все ошибки, не позволяя например ловить их только в рамках одного класса. И в ФФ судя по MDN не работает. Обработка ошибок в промисах (по моему личному мнению) сделана неудачно.

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

var x = getMessages().then(null, function (error) {
// исключение перехватится и будет возвращено внутри промиса x
throw new Error(error);
});

> То есть например, в случае с ajax мы на вход функции onRejected отправляем jqXHR и textStatus.


Если произойдет ошибка, то jQuery вызовет onRejected, верно.

> Насколько я понимаю, они (аргументы функции) появляются в самом коде метода ajax и возвращаются с помощью Promise.reject(jqXHR, textStatus), я правильно понимаю?


Нет, в коде ошибка, в reject информация об ошибке передается одним аргументом-исключением:

reject(new RequestError(textStatus));

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


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

> У стандартного ES6 класса Promise нету метода .done().


Это я наверно из PHP взял. Тогда then().

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


Ок

> в Debian stretch заместо mysql идёт MariaDB.


Так это форк mysql (как и percona), и я думаю, там процентов на 95 тот же самый код.

> мне кажется что такого рода приложения говорят о некомпетенции программиста


Ну я бы не был столь категоричен, в GUI в принципе тоже есть свои преимущества (например, таблицы можно выводить более качественно, особенно большие, прокрутка лучше реализуется). Веб-интерфейс конечно имеет свои недостатки - например, нельзя отменить долго выполняющийся запрос (а в консоли можно через Ctrl + C). Но есть и другие GUI клиенты, и в принципе, если кому-то нравится ими пользоваться, почему бы и нет. Там например можно сохранять часто выполняемые запросы, можно редактировать таблицы визуально и тд.
#766 #1082551
>>1082536

> Вот: https://ideone.com/XhydTt#stdin. Правильно ли дописал? А то может я неправильно понял. Если правильно, то можно было как-то лучше? Спасибо.



Да, правильно, если надо найти только один товар. Но если может быть несколько товаров с одинаковым именем, то надо возвращать не 1 товар, а массив.

> И что будет если вернется true ? false ?


Функция представляет собой критерий поиска. Она получает на вход 1 товар и должна вернуть:

- true если товар соответствует критерию (это то, что мы ищем)
- false если нет

То есть твой код получает функцию-критерий поиска. Он обходит склад, для каждого товара по очереди вызывает эту функцию и если она вернет true, то добавляет товар в список подходящих под условия.
#767 #1082553
Аноны, переходите в новый тред >>1082507 (OP)

Если вас пропустили - напомните о себе в новом треде.
#768 #1082586
>>1082535
да, повторяющиеся блоки на разных страницах, например меню или подвал страницы. Пока попробовал через require(). Еще нагуглил метод SSI, но он, как я понял, с php не очень дружит
#769 #1082695
>>1082586

Тебе нужен require (команда PHP). SSI это синтаксис в Апаче.
#770 #1082908
>>1080998
На кой делать студентов в yii, там по сути хеллоуворлд, описаный в документации фреймворка.
#771 #1082960
>>1081971
Спасибо за ответ, учёл советы. Ещё помогло распараллеливание (через процессы ОС, без чего-либо хитрого):
php script.php 0 500000 &
php script.php 500000 1000000 &
...

> просто выборка через SELECT ... FROM table без хитрых джойнов и условий?


Увы, да, заслуга предыдущего разработчика, который даже джойны толком не знал и повсюду в коде использовал N + 1. Договорились с заказчиком с нуля переписывать.

>>1081981
Тоже запомню.
#772 #1083067
Замена одного слова на другое
https://ideone.com/Rivr5w
последний пример - чистейшая удача окончание а
someApprentice #773 #1083110
>>1082548

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


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


Как вы говорили, мне нужно обработать ошибку дешифровки. Например, может быть передан неправильный passphrase. Изучив код библиотеки я выяснил, что, при дешифровке ключа, метод Key.prototype.decrypt(...) возвращает false, если ключевое слово не подошло.

https://openpgpjs.org/openpgpjs/doc/key.js.html#line389

И после этого, при получении сообщений, я проверяю этот метод перед дешифровкой

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L284
https://github.com/someApprentice/chat/blob/master/public/js/crypter.js#L11-L21

Здесь всё понятно, потому что нету никаких Обещаний.

А вот в сам метод дешифровки завязан на Обещании, и мне до сих пор не понятно как оно работает
Вот его код https://openpgpjs.org/openpgpjs/doc/message.js.html#line95

>return Promise.resolve()...


Означает вернуть выполненное обещание с пустым значением

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

>...then(


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

Сначала проверит ключ сессии что это может быть? и если он неверен выбросит ошибку

Затем отфилтрует какие-то пакеты

И если ни одного из них ни найдено вернет false (null?)

Затем возмёт первый попавшейся пакет
И с его помощью асинхронно выполнит рашифровку

https://openpgpjs.org/openpgpjs/doc/packet_symmetrically_encrypted.js.html#line66
https://openpgpjs.org/openpgpjs/doc/packet_sym_encrypted_integrity_protected.js.html#line113
symEncryptedAEADProtected не нашел

Метды выше выполняют какой-то алгоритм дешифровки, выбрасывают исключения если что-то не получилось и опять возвращают выполненное обещание с пустым значением return Promise.resolve(). Причём, когда происходит ошибка не возвращается Promise.reject(new Error(...)). Я не понимаю как это работает.
Вы поэтому упоминули про unhandledRejection? Его нужно где-то повесить?

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

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

var privateKey = '-----BEGIN PGP PRIVATE KEY BLOCK ... END PGP PRIVATE KEY BLOCK-----';
var encrypted = '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----';

// Если ключ неправильный, то вбрасываются ошибки
// https://openpgpjs.org/openpgpjs/doc/key.js.html#line1030
// https://openpgpjs.org/openpgpjs/doc/key.js.html#line1036
privateKey = openpgp.key.readArmored(privateKey).keys[0];

// Если ключевая фраза не подошла, то просто вернётся false
var success = privateKey.decrypt(this.passphrase);

if (success) {
var options = {
// Если шифр неверен, опять же, вбрасываются ошибки
// https://openpgpjs.org/openpgpjs/doc/encoding_armor.js.html#line285
// https://openpgpjs.org/openpgpjs/doc/encoding_armor.js.html#line337
message: openpgp.message.readArmored(encrypted),
privateKey: privateKey
};

// Вешаем unhandledRejection
window.addEventListener("unhandledrejection", function (e) {
console.log(e.reason);
});

// Если ключ не подходит, то ошибка должна произойти где-то здесь и пойматься в unhandledRejection
var promise = openpgp.decrypt(options).then(function(decrypted) {
return decrypted;
});
}

>>>unhandledPromise


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


>Не, это событие https://developer.mozilla.org/en-US/docs/Web/Events/unhandledrejection


>


>У window есть событие error, которое происходит при непойманном исключении. Если в промисе произошло reject и оно не было обработано, то сработает событие unhandledrejection. Можно с его помощью централизованно собирать ошибки. Но проблема конечно в том, что это ловит глобально все ошибки, не позволяя например ловить их только в рамках одного класса. И в ФФ судя по MDN не работает. Обработка ошибок в промисах (по моему личному мнению) сделана неудачно.


>


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


>


>var x = getMessages().then(null, function (error) {


>// исключение перехватится и будет возвращено внутри промиса x


>throw new Error(error);


>});



>Если в промисе произошло reject и оно не было обработано, то сработает событие unhandledrejection.


Т.е. в случае если не был повешан .then(..., onRejected) или .catch(onRejected)?

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

var promise = openpgp.decrypt(options).then(function(decrypted) {
if (decrypted instanceof Error) {
console.log(decrypted.reason)
} else {
return decrypted;
}
});

?

Надо спросить у авторов библиотеки почему они не делают reject?

>Можно с его помощью централизованно собирать ошибки.


А можно небольшой пример как это делается?

>И в ФФ судя по MDN не работает.


Не совсем понял, что именно не работает?

>> У стандартного ES6 класса Promise нету метода .done().


>Это я наверно из PHP взял. Тогда then().


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


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


>Ок


Я опечатался. Какой стыд.

разница между приложением с моделью и приложенеем без неё*
someApprentice #773 #1083110
>>1082548

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


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


Как вы говорили, мне нужно обработать ошибку дешифровки. Например, может быть передан неправильный passphrase. Изучив код библиотеки я выяснил, что, при дешифровке ключа, метод Key.prototype.decrypt(...) возвращает false, если ключевое слово не подошло.

https://openpgpjs.org/openpgpjs/doc/key.js.html#line389

И после этого, при получении сообщений, я проверяю этот метод перед дешифровкой

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L284
https://github.com/someApprentice/chat/blob/master/public/js/crypter.js#L11-L21

Здесь всё понятно, потому что нету никаких Обещаний.

А вот в сам метод дешифровки завязан на Обещании, и мне до сих пор не понятно как оно работает
Вот его код https://openpgpjs.org/openpgpjs/doc/message.js.html#line95

>return Promise.resolve()...


Означает вернуть выполненное обещание с пустым значением

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

>...then(


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

Сначала проверит ключ сессии что это может быть? и если он неверен выбросит ошибку

Затем отфилтрует какие-то пакеты

И если ни одного из них ни найдено вернет false (null?)

Затем возмёт первый попавшейся пакет
И с его помощью асинхронно выполнит рашифровку

https://openpgpjs.org/openpgpjs/doc/packet_symmetrically_encrypted.js.html#line66
https://openpgpjs.org/openpgpjs/doc/packet_sym_encrypted_integrity_protected.js.html#line113
symEncryptedAEADProtected не нашел

Метды выше выполняют какой-то алгоритм дешифровки, выбрасывают исключения если что-то не получилось и опять возвращают выполненное обещание с пустым значением return Promise.resolve(). Причём, когда происходит ошибка не возвращается Promise.reject(new Error(...)). Я не понимаю как это работает.
Вы поэтому упоминули про unhandledRejection? Его нужно где-то повесить?

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

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

var privateKey = '-----BEGIN PGP PRIVATE KEY BLOCK ... END PGP PRIVATE KEY BLOCK-----';
var encrypted = '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----';

// Если ключ неправильный, то вбрасываются ошибки
// https://openpgpjs.org/openpgpjs/doc/key.js.html#line1030
// https://openpgpjs.org/openpgpjs/doc/key.js.html#line1036
privateKey = openpgp.key.readArmored(privateKey).keys[0];

// Если ключевая фраза не подошла, то просто вернётся false
var success = privateKey.decrypt(this.passphrase);

if (success) {
var options = {
// Если шифр неверен, опять же, вбрасываются ошибки
// https://openpgpjs.org/openpgpjs/doc/encoding_armor.js.html#line285
// https://openpgpjs.org/openpgpjs/doc/encoding_armor.js.html#line337
message: openpgp.message.readArmored(encrypted),
privateKey: privateKey
};

// Вешаем unhandledRejection
window.addEventListener("unhandledrejection", function (e) {
console.log(e.reason);
});

// Если ключ не подходит, то ошибка должна произойти где-то здесь и пойматься в unhandledRejection
var promise = openpgp.decrypt(options).then(function(decrypted) {
return decrypted;
});
}

>>>unhandledPromise


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


>Не, это событие https://developer.mozilla.org/en-US/docs/Web/Events/unhandledrejection


>


>У window есть событие error, которое происходит при непойманном исключении. Если в промисе произошло reject и оно не было обработано, то сработает событие unhandledrejection. Можно с его помощью централизованно собирать ошибки. Но проблема конечно в том, что это ловит глобально все ошибки, не позволяя например ловить их только в рамках одного класса. И в ФФ судя по MDN не работает. Обработка ошибок в промисах (по моему личному мнению) сделана неудачно.


>


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


>


>var x = getMessages().then(null, function (error) {


>// исключение перехватится и будет возвращено внутри промиса x


>throw new Error(error);


>});



>Если в промисе произошло reject и оно не было обработано, то сработает событие unhandledrejection.


Т.е. в случае если не был повешан .then(..., onRejected) или .catch(onRejected)?

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

var promise = openpgp.decrypt(options).then(function(decrypted) {
if (decrypted instanceof Error) {
console.log(decrypted.reason)
} else {
return decrypted;
}
});

?

Надо спросить у авторов библиотеки почему они не делают reject?

>Можно с его помощью централизованно собирать ошибки.


А можно небольшой пример как это делается?

>И в ФФ судя по MDN не работает.


Не совсем понял, что именно не работает?

>> У стандартного ES6 класса Promise нету метода .done().


>Это я наверно из PHP взял. Тогда then().


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


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


>Ок


Я опечатался. Какой стыд.

разница между приложением с моделью и приложенеем без неё*
someApprentice #774 #1083114
>>1082548

>> Насколько я понимаю, они (аргументы функции) появляются в самом коде метода ajax и возвращаются с помощью Promise.reject(jqXHR, textStatus), я правильно понимаю?


>Нет, в коде ошибка, в reject информация об ошибке передается одним аргументом-исключением:


>


>reject(new RequestError(textStatus));


Но где вызывается сам reject() тогда? Мне почему-то кажеться, что, обычно, где-то по среди кода возвращается Promise.reject(...), это не так?

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


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


Кхм, неправильно понял ваш намёк сначала.

В предыдущем посте я выяснил какие ошибки могут произойти:

>>1083110

>- передана неверная ключивая фраза


В этом случае нужно просто предложить заного ввести ключевую фразу заного. Что я уже сделал.

>- передан неправильный шифр сообщения


>- передан неправильный ключ


>- ключ не подходит к данному шифру


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

В принципе, стандартная процедура. Для меня сначала нужно понять как именно обработать эти ошибки.
#775 #1083950
Пытаюсь решить задачку на рекурсию от ОПа, которую он в прошлом треде постил:

>1) Дан список категорий товаров в виде такого массива:



>$categories = [


>// id, название, parentId, кол-во товаров


>[1, 'Бытовая техника', null, 0],


>[2, 'Телевизоры', 1, 0],


>[3, 'LCD-телевизоры', 2, 20],


>[4, 'Телевизоры с газоразрядным дисплеем', 16],


>[5, 'Стиральные машины', 1, 0],


>[6, 'Холодильники', 1, 0],


>...


>];



>Для каждого товара указан уникальный id категории, >название, id родительской категории или null, если ее >нет, количество товаров в этой категории без учета >категорий-детей. Используя эти данные:



>а) Напиши функцию, которая для любого переданной >id категории вернет массив, содержащий id этой >категории и всех ее предков, начиная от корня >дерева.



>Например, для категории 3 вернет массив [1, 2, 3] >(Бытовая техника -> Телевизоры -> LCD-телевизоры). А >для 1 - массив [1].



>б) Напиши функцию, которая для любой категории >вернет массив id ее потомков. Например для id = 2 >функция должна вернуть массив [3, 4]



>в) Напиши функцию, которая вернет массив >категорий-сестер (то есть категорий, имеющих того >же родителя). Для id = 2 функция должна вернуть >массив [5, 6]



>г) Напиши функцию, которая выведет список >категорий в виде дерева "лесенкой", с указанием >числа товаров с учетом дочерних категорий:



>Бытовая техника (36)


>- Телевизоры (36)


>-- LCD-телевизоры (20)


>-- Телевизоры с газоразрядным дисплеем (16)


>Стиральные машины


>Холодильники


Что-то у меня совсем не получается. М. б. кто-нибудь намекнет как такое решать.
#775 #1083950
Пытаюсь решить задачку на рекурсию от ОПа, которую он в прошлом треде постил:

>1) Дан список категорий товаров в виде такого массива:



>$categories = [


>// id, название, parentId, кол-во товаров


>[1, 'Бытовая техника', null, 0],


>[2, 'Телевизоры', 1, 0],


>[3, 'LCD-телевизоры', 2, 20],


>[4, 'Телевизоры с газоразрядным дисплеем', 16],


>[5, 'Стиральные машины', 1, 0],


>[6, 'Холодильники', 1, 0],


>...


>];



>Для каждого товара указан уникальный id категории, >название, id родительской категории или null, если ее >нет, количество товаров в этой категории без учета >категорий-детей. Используя эти данные:



>а) Напиши функцию, которая для любого переданной >id категории вернет массив, содержащий id этой >категории и всех ее предков, начиная от корня >дерева.



>Например, для категории 3 вернет массив [1, 2, 3] >(Бытовая техника -> Телевизоры -> LCD-телевизоры). А >для 1 - массив [1].



>б) Напиши функцию, которая для любой категории >вернет массив id ее потомков. Например для id = 2 >функция должна вернуть массив [3, 4]



>в) Напиши функцию, которая вернет массив >категорий-сестер (то есть категорий, имеющих того >же родителя). Для id = 2 функция должна вернуть >массив [5, 6]



>г) Напиши функцию, которая выведет список >категорий в виде дерева "лесенкой", с указанием >числа товаров с учетом дочерних категорий:



>Бытовая техника (36)


>- Телевизоры (36)


>-- LCD-телевизоры (20)


>-- Телевизоры с газоразрядным дисплеем (16)


>Стиральные машины


>Холодильники


Что-то у меня совсем не получается. М. б. кто-нибудь намекнет как такое решать.
#776 #1084177
Может кто-нибудь на пальцах объяснить, как в yii делается разграничение прав на доступ к страницам для разных групп пользователей?
#777 #1085269
Этот тред закрыт. Не пишите здесь, а идите в новый тред >>1082507 (OP)

>>1083067

Ответ в новом треде >>1085261

>>1083110

Ответ в новом треде.
Тред утонул или удален.
Это копия, сохраненная 5 ноября 2017 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски