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

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

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

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

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

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

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

Еще предыдущие треды в архиве:

- 83: https://2ch.hk/pr/arch/2016-12-26/res/880700.html (М)
- 82: https://2ch.hk/pr/arch/2016-12-01/res/864640.html (М)
- другие: https://www.google.ru/search?q=site:2ch.hk/pr/+клуб+php

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Что почитать

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

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

У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Объясняй

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Объясняй

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

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

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

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

Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
936977
#3 #919076
Кого я пропустил и не ответил в предыдущем треде >>898502 (OP) , напомните тут о себе.

--

Хорошая задача на ООП с собеседования: http://www.cyberforum.ru/php-oop/thread1459985.html

Вы должны решить как минимум Вектор, чтобы взяться за нее. Если вы сделали студентов или файлообменник - эту задачу должны решить легко.
919129
#4 #919129
>>919076
ОПчик, почему тут цикл состоит только из 1 значения?
http://ideone.com/lcS8qQ
Дело в continue? Мысль была такова, что при положительном итоге проверки на наличие купюр, он их просто пропускает и переходит к следующему номиналу.
919233
#5 #919179
>>919068

Я уже начал делать MVC сапера отсюда https://github.com/codedokode/pasta/blob/master/js/minesweeper-mvc.md , смысл делать позер-MVC, когда можно полноценное. Вопрос такой, ты помогал советами анонам писать event dispatcher для паттерна observer? Или они брали готовый код (глянул на гитхабе енота, вроде свой). Можешь ли ты подробней расписать про этот паттерн, а то я пока что не понял как работают его методы и как будет устроен класс, понял только что он будет следить за изменением модели за счет addEventListener. Там вроде есть ссылки на эти классы, но мне кажется если я их посмотрю, это будет как подглядывание.
919227921320
#6 #919227
>>919179

Класс очень простой, он по сути позволяет сделать 2 вещи:

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

Примерно так:

var ed = new EventDispatcher;
ed.addEventListener(SOME_EVENT, function (event) { ... });
ed.addEventListener(SOME_EVENT, function (event) { ... });

ev.triggerEvent(SOME_EVENT, { data: ... });

Есть еще альтернативный подход, когда класс представляет диспетчер только для одного события (то есть на каждое событие создается отдельный объект):

var someEvent = new EventDispatcher;
someEvent.subscribe(function (event) { ... });
someEvent.trigger({ data: ... });

Ты также можешь посмотреть:

- как устроен встроенный в браузер диспетчер событий: https://developer.mozilla.org/ru/docs/Web/Guide/Events/Создание_и_вызов_событий

- обзор разных подходов (англ): https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations

Методы иногда называют немного по-другому (notify/dispatchEvent/raiseEvent/fireEvent), но суть та же.

Также можешь погуглить по словам Observer и Event Emitter/Event Dispatcher.
#6 #919227
>>919179

Класс очень простой, он по сути позволяет сделать 2 вещи:

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

Примерно так:

var ed = new EventDispatcher;
ed.addEventListener(SOME_EVENT, function (event) { ... });
ed.addEventListener(SOME_EVENT, function (event) { ... });

ev.triggerEvent(SOME_EVENT, { data: ... });

Есть еще альтернативный подход, когда класс представляет диспетчер только для одного события (то есть на каждое событие создается отдельный объект):

var someEvent = new EventDispatcher;
someEvent.subscribe(function (event) { ... });
someEvent.trigger({ data: ... });

Ты также можешь посмотреть:

- как устроен встроенный в браузер диспетчер событий: https://developer.mozilla.org/ru/docs/Web/Guide/Events/Создание_и_вызов_событий

- обзор разных подходов (англ): https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations

Методы иногда называют немного по-другому (notify/dispatchEvent/raiseEvent/fireEvent), но суть та же.

Также можешь погуглить по словам Observer и Event Emitter/Event Dispatcher.
#7 #919229
$a = [];
for ($i = 0; $i < 1.02; $i += 0.17) {
$a[$i] = $i;
}
echo count($a);

Господа, поясните, почему получается 1?
919232921320
#8 #919232
>>919229
Все, я понял. Спасибо.
#9 #919233
>>919129
ОП, я разобрался сам, не трать время на тот код. Вот посмотри пожалуйста этот, вроде, как сделал: http://ideone.com/Vl5GJ4
921320
#10 #919288
https://arhivach.org/thread/216627/#899867

>wireshark


>прокси на php


Какие прекрасные подарки вы мне сделали перед НГ, это просто благословение!

https://arhivach.org/thread/216627/#899868

>> .header h1 {


>> font-family: ReklameScriptRegularDEMO, Cambria


>В конце списка шрифтов надо указывать бы стандартный (serif и подобный). Cambria есть только на windows.


Вы кидали сайт где указывались шрифты и статистика использования на разных платформах. Выбрал Кабмрию потому что там было 90%+ и для Эпл и красивенько выглядел.

>> .services .content .box .consectetur::before {


>> background-position: 0px 0px;


>> width: 47px;


>> height: 54px;


>Вот тут проще было для 4 блоков указать одинаковый размер картинки, а не различающиеся на 2-3 пикселя.


В фш так вырезалось что все картинки разных размеров...

>> .services .content .box .fermentum::before {


>я бы убрал тут .content, он выглядит лишним


Как понять 'выглядит'? Разве не нужно соблюдать иерархию дерева? Знаю что не обязательно, но моё субъективное восприятие подсказывает что так выглядит лучше.

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


Исправил: https://www.browserstack.com/screenshots/634b220454c5dd8901b415de1440461f2a47865f/win10_firefox_44.0.jpg

https://github.com/someApprentice/maintaskforlayout/
#11 #919568
Есть массив в котором содержатся хлебные крошки, в формате [id]=>[title]. Необходимо сделать так, чтобы последняя ссылка в хлебных крошках не была ссылкой. Могу реализовать двумя вариантами, либо подчистить довольно сложным регулярным выражением, либо же ввести счётчик ($i) и если это будет последняя итерация, то есть условие переменная счетчика равна количеству элементов в массиве просто не записывать html код, то есть не делать ссылку. Как правильнее и быстрее?
$i=1;
foreach($breadcrumbs_array as $id => $title) {
$string ="<a href='?category=$id'>$title</a> / ";
if($i==count($breadcrumbs_array)) {
$string = $title;
}
$breadcrumbs.= $string;
$i++;
}
921320
#12 #919800
Аноны, почему тут постоянно пишет, что на 12 строке какое-то невыполнимое условие? В итоге он пишет, что не успевает за 30 сек. всё просчитать.

http://ideone.com/3PFkTf
939968
#13 #919968
Изучаю сейчас все подробности создания сайтов каталогов, и хочу уже использовать всё это в каком-нибудь реальном сайте. Подскажите, каталог чего можно создать? Только не товаров с возможностью покупки, как в интернет-магазине, а чего-нибудь другого, например каталог сайтов или что-то такое.
921320
#14 #920065
Получаю с Select формы массив данных со значениями полей. В нём может быть разное количество элементов, от 1 до 8. Далее мне нужно внести эти данные в таблицу, в котором есть условно два столбца id и text, где текст это значение каждого элемента массива. То есть, если в массиве 6 элементов, я должен записать 6 строк в таблицу. Можно ли это как-то сделать, но без использования запроса к базе данных внутри цикла?
921320
#15 #920199
Все, пиздец, не могу решить задачу Опа "Считалочка". http://archive-ipq-co.narod.ru/i/l1/l1-bonus-survivor.png
Логика моего решения примерно такова:
создаем пустой массив длиной в 30 символов
пока длина этого массива больше чем количество слогов:
начинаем считать сначала, находим первый элемент который делится на 5 без остатка ( элемент % 5 == 0)
как только находим его, делаем новый массив в который добавляем все числа которые идут после него и до конца.
затем к этому новому массиву добавляем те элементы которые шли сначала и до этого элемента
в итоге получаем массив начинающийся с числа 6 до 30, а далее 1,2,3,4. Это для того чтобы считать дальше начиная со следующего элемента.
скопировать значения из этого нового массива в финальный, чтобы пройтись по нему таким же алгоритмом снова
как только в массиве остается 4 числа, выводим их в ответ


У меня нихуя не получается переназначить первоначальный массив, он всегда остается таким же как был.
920201921320
#16 #920201
>>920199
Судя по примерному коду ОПа из этой задачи, у него решение четкое логичное и аккуратное, у меня же как говно. Скорее всего сам алгоритм неверен.
#17 #920960
Оп, а можно ли вот так сделать или это неправильно?

http://ideone.com/cWWTRU

Я хочу, чтобы this._field (он представлен в виде массива [{x:1, y:1}, {x:2, y:1} ...etc] остался в таком виде по возрастанию. Если я сделаю на него shuffle, то он пересортируется случайно. Поэтому я делаю неглубокию копию массив и воздействую на элементы массива - объекты, которые соответственно будут меняться и в оригинальном массиве. Вот такой неочевидный абуз. Я получаю, то что мне нужно (минирую поле) и массив по прежнему в порядке возрастания. Наверное надо делать метод setMine и передавать в него элемент скопированного массива, чтобы good code? А этот метод будет минировать поле field.
920988921197921321
#18 #920969
>>919074 (OP)
Спасибо, ОП, за перекат самого годного треда доски. Ради него сюда и захожу еще ради хаскеля
#19 #920973
>>919074 (OP)

>Кто-то хочет научиться программировать


>PHP (а также JS/CSS/HTML/SQL)


/0
#20 #920988
>>920960

И еще я думаю как хранить мины, флажки и открытые клетки. Два варианта. Либо это boolean свойства объекта Cell, либо они хранятся в свойствах-массивах this._flags, this._mines, this._openCells. В последнем случае будет еще существовать мета-массив field, в котором будут все клеточки. Получится так, что элементы этих массивов будут ссылаться на одни и те же объекты Cell. Это нормально или делать глубокое копирование?
920990921321
#21 #920990
>>920988

> либо они хранятся в свойствах-массива



Здесь имеется ввиду свойства модели MinesweeperGame.
#22 #921117
Есть файл, в котором находится скрипт обрабатывающий данные приходящие из формы. Как только происходит их обработка, он автоматически перенаправляет пользователя на другой файл. Как закрыть доступ со стороны браузера к этому файлу? Пока что только приходит, сделать так, что если обязательные данные не заполнены, то есть их нет в массиве ПОСТ вызывать exit; Со стороны формы, которая находится в другом файле пустую строку не будет пропускать яваскрипт. Какие есть лучшие варианты?
921321
351 Кб, 960x1280
#23 #921197
>>920960

Так же вопрос, можно ли данный метод http://ideone.com/8v7B0B вставить в ConsoleController ? Или в модель это пойдет. Суть его в том, чтобы команды вроде 'a2' из консоли переводить в объекты Cell, ведь наверное нельзя передавать аргументы в контроллер вот так game.setFlag(new Cell(1,5), верно?
921321
#24 #921275
анончики, расскажите, сложно ли вкатиться в фриланс на похапе?
я знаю жс(+jquery+react+react-native+ember),html,css на уровне 3-4 месяцев практики, сделал тройку сайтов для себя + игру на андроид, и сейчас выбираю между пхп и питоном. На жс+верстке не въехть из за обилия макак, которые имеют сотни отзывов и опыт на сайте, а мой профиль без рейтинга никому не нужен, поэтому хочу попробовать что-то еще. Ну и типа фуллстак же буду.
921283921305
#25 #921283
>>921275
Пока ты не начнешь выгрызать и находить себе заказы, ты так и будешь выбирать между пхп и питоном, потом еще из какой нить дрочи и везде будут "обилие макак".
921358
#26 #921305
>>921275
В пхп макак еще больше, попробуй java или .net
921307921358
#27 #921307
>>921305
Нельзя просто взять и попробовать Яву.
#28 #921309
Напомню себе, что надо проверить:

https://github.com/masssn/students.loc 29.12 >>903250
https://github.com/anotherCodeMunkey/fileshare (это ведь на проверку?) 07.01 >>907902

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

Также, напомню, что в старом треде опубликованы ответы:

>>919067 - про задачу про ООП и скидки
>>919065 про JS задачу на DOM номер 4
>>919061 клавиша шифт, йода, сумма прописью
>>919060 про сумму прописью
>>919059 про калькулятор
>>919058 про preg_match
922138931331931333
Старые ответы #29 #921310
>>907746

> В каком вашем мануале можно прочитать про организацию роутера для URL, контроллеры по умолчанию, index.php в корне сайта?



У нас такой статьи нет. Но можно оизучать фреймворуи вроде Slim, Yii2, Symfony и посмотреть, как роутинг сделан там.

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

- конфиг, где прописаны шаблоны УРЛ и соответствующие им контроллеры
- шаблоны УРЛ и их обработчики явно прописываются в коде:

$app->get('/about', function () { ... });
$app->get('/help', 'HelpController::indexAction');

- используется какой-то стандартный шаблон URL по умолчанию вроде /контроллер/действие/имя параметра/значение параметра

Ну и процитирую еще пост другого анона с ответом на этот вопрос:

>>908528

> Первый ответ: https://toster.ru/q/321702


> Читать исходники готовых роутеров:


> http://symfony.com/doc/current/routing.html


> https://github.com/auraphp/Aura.Router



>>909285

>>Ты по моему не очень понимаешь, что такое AR. AR это когда класс/объект представляет и строку из базы данных, и содержит методы для ее загрузки/сохранения в БД. Ты уверен, что ничего не перепутал?


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


Нет, наследование тут не при чем. Главная особенность Active Record - то, что класс-модель сам умеет себя сохранять в базу:

$student = new Student;
$student->name = 'Ivan';
$student->save();

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

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


> О, отлично. Только это же все равно логически относится к моделям, правда?



Да, в MVC это модель.

>>безопасность, чтобы нельзя было сохранить файл с расширением php или именем htaccess


> Такие файлы стоит просто запрещать загружать или же менять им расширение?


Удобнее разрешать загружать, но при сохранении менять расширение на безопасное вроде .txt
Старые ответы #29 #921310
>>907746

> В каком вашем мануале можно прочитать про организацию роутера для URL, контроллеры по умолчанию, index.php в корне сайта?



У нас такой статьи нет. Но можно оизучать фреймворуи вроде Slim, Yii2, Symfony и посмотреть, как роутинг сделан там.

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

- конфиг, где прописаны шаблоны УРЛ и соответствующие им контроллеры
- шаблоны УРЛ и их обработчики явно прописываются в коде:

$app->get('/about', function () { ... });
$app->get('/help', 'HelpController::indexAction');

- используется какой-то стандартный шаблон URL по умолчанию вроде /контроллер/действие/имя параметра/значение параметра

Ну и процитирую еще пост другого анона с ответом на этот вопрос:

>>908528

> Первый ответ: https://toster.ru/q/321702


> Читать исходники готовых роутеров:


> http://symfony.com/doc/current/routing.html


> https://github.com/auraphp/Aura.Router



>>909285

>>Ты по моему не очень понимаешь, что такое AR. AR это когда класс/объект представляет и строку из базы данных, и содержит методы для ее загрузки/сохранения в БД. Ты уверен, что ничего не перепутал?


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


Нет, наследование тут не при чем. Главная особенность Active Record - то, что класс-модель сам умеет себя сохранять в базу:

$student = new Student;
$student->name = 'Ivan';
$student->save();

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

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


> О, отлично. Только это же все равно логически относится к моделям, правда?



Да, в MVC это модель.

>>безопасность, чтобы нельзя было сохранить файл с расширением php или именем htaccess


> Такие файлы стоит просто запрещать загружать или же менять им расширение?


Удобнее разрешать загружать, но при сохранении менять расширение на безопасное вроде .txt
Старые ответы #30 #921311
>>909294

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



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

>>909411
>>909412

> Можете подсказать, почему конечный результат отличается?


Ты в последний месяц, когда там остается выплатить около 4000, выплачиваешь их сразу ( else {$paymentTotal = $paymentTotal + $creditBalance; ), а ведь на них сначала должны начислиться проценты и комиссия. И выйдет больше.

>>909492

> Где phpMyAdmin хранит комментарии к ячейкам таблицы?


phpMyAdmin сам их не хранит, а передает на сервер MySQL для хранения. Эти же комментарии можно добавить и без phpMyADmin, через SQL запрос вида:

CREATE TABLE x (
y INT COMMENT 'Примечание'
) COMMENT 'Примечание';

> Участвуют ли они в запросах?


> Есть ли разница в производительности запросов с ними / без?


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

> Какой движок (MyIsam, InnoDb, другой?) подойдет лучше для ситуации:


Почитай про различия между движками, гугли "отличия innodb и myisam"

> Не будут ли тормозить запросы в конце года?


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

Вообще, тебе лучше бы просто сделать таблицу, скрипт выборки и померять время.
Старые ответы #30 #921311
>>909294

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



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

>>909411
>>909412

> Можете подсказать, почему конечный результат отличается?


Ты в последний месяц, когда там остается выплатить около 4000, выплачиваешь их сразу ( else {$paymentTotal = $paymentTotal + $creditBalance; ), а ведь на них сначала должны начислиться проценты и комиссия. И выйдет больше.

>>909492

> Где phpMyAdmin хранит комментарии к ячейкам таблицы?


phpMyAdmin сам их не хранит, а передает на сервер MySQL для хранения. Эти же комментарии можно добавить и без phpMyADmin, через SQL запрос вида:

CREATE TABLE x (
y INT COMMENT 'Примечание'
) COMMENT 'Примечание';

> Участвуют ли они в запросах?


> Есть ли разница в производительности запросов с ними / без?


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

> Какой движок (MyIsam, InnoDb, другой?) подойдет лучше для ситуации:


Почитай про различия между движками, гугли "отличия innodb и myisam"

> Не будут ли тормозить запросы в конце года?


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

Вообще, тебе лучше бы просто сделать таблицу, скрипт выборки и померять время.
Старые ответы #31 #921312
>>912063

$b можно было бы вычислять из $i ($b = длина - $i - 1 или даже просто $b = - $i - 1), но твое решение в общем-то тоже верное.

>>919083

>>Конечно, копирует ссылку на функцию.


> Но функция находиться же в объекте obj! В чём подвох?



var o = {};
o.fn = function() {};

Функция o.fn сама по себе никак к этому объекту не привязана. Объект хранит в себе ссылку на функцию, а функция на объект - нет. Потому если мы копируем ее в отдельную переменную, и вызываем, то она про исходный объект ничего уже не знает и this указывает на window:

var f = o.fn;
f();

А вот если мы пишем

o.fn();

То интерпретатор JS видит, что функция вызвыается на объекте, и подсовывает его в качестве this.

Чтобы она "запомнила" свой объект, мы должны использовать bind:

var f = o.fn.bind(o);
f();

>>Задача 1: написать функцию bindContext(fn, that). Она создает новую функцию, которая при вызове вызывает fn с указанным this и переданным аргументами. То по сути есть привязывает произвольное значение this к функции.


> https://jsfiddle.net/Luubgokx/


Все верно.

>>Задача 2: сделать функцию addProperty(object, name, initialValue) для создания приватных свойств с геттерами и сеттерами на объекте или прототипе объекта.


> https://jsfiddle.net/sh21j4p1/


Тут опечатка в коде:

> addProperty(obj, 'test', 10);


> console.log(obj.getName());


Свойство test, а вызывается getName вместо getTest().

По коду: в общем, верный подход, мы прячем переменную в замыкании, но вот не очень понял, зачем использовать defineProperty. Функции get/set можно просто добавить через obj[funcName] = function ...

> name[0].toUpperCase() + name.slice(1)


Это конечно лучше было вынести в вспомогательную функцию.

Задача про фастфуд

> Почему-то не получается https://jsfiddle.net/y28h2o2b/3/


Там надо открыть отладчик (Ctrl + SHift + I) и включить режим "останавливаться на исключении". И там будет видно, что this.menu не определено, отсюда и ошибка.

Ест статья про отладку: http://learn.javascript.ru/debugging-chrome

Аналогичный отладчик есть и в Фаерфоксе, и в Сафари.

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

Электросеть

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



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

- можно вообще не делать свойств в базовом классе, и в каждом наследнике написать свой метод getPower() со своей логикой. Соответственно, наследник определяет, какие будут свойства (вроде числа квартир) и как из них вычисляется потребление.
- можно сделать в базовом классе свойства dayPower/nightPower и метод getPower, который их возвращает. А логику вычисления этих свойств писать в конструкторах наследников. И не делать свойств вроде числа квартир.

Первый подход наверно гибче.

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


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

> Лучше исключить её из перебора потому, что ЛЭП тоже может вернуть какое-то количество мощности.


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

> С другой стороны электросеть не знает о ценах и о внутреннем устройстве ЛЭП. Моя идея в том, баланс можно просто передать в условный счетчик. Ведь это для ЛЭП свойственно иметь и считать цену.


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

> https://jsfiddle.net/6591a2sL/4/



> this.elements.sort(function (a, b) {


> if (a.price > b.price) {


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

Также, sort меняет порядок следования элементов в this.elements, что может где-то быть нежелательно. Ведь получается что метод с названием get Something фактически изменяет внутреннее состояние объекта, что неожиданно. Лучше получить отдельный массив ЛЭП и сортировать его.

> if (this.elements instanceof PowerLine) {


> price += this.elements.countPrice(balance);


> balance = this.elements.countPower(balance);


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

> function Electrostation(power) {


> if (power >= 1 Math.pow(10, 6) && power <= 100 Math.pow(10, 6)) {


> this.power = power;


> this.nightpower = power;


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

> function PowerLine(power, price) {


> this.power = power;


> this.price = price;


> }


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

> PowerLine.prototype.countPower = function(power) {


> var thispower = this.power;



> for (var i = 0; i < thispower; thispower--) {


> if (power == 0) {


> break;


> }



> power += power / -Math.abs(power);


что-то я не могу толком понять, что тут происходит. Зачем мы power делим саму на себя? Получится ведь либо 1, либо -1. Тут явно ошибка.

Определение типа переменной

> Что подрузумевается здесь под словом 'хеш'?


Хеш, он же словарь, он же ассоциативный массив, он же объект - это вот это:

var x = { 1: 2, 'x': 'y' };

Я просто написал что вместо switch можно было сделать объект, в ключах которого хранятся значения вроде '[object Function]'. И искать тип в этом объекте.

>>Недостаточно, надо бы проверить что там есть свойства от 0 до length - 1.


>>от 0 до length - 1


> А как это выразить в условии


Написать цикл, проверяющий наличие свойств с помощью оператора in.

15. Напиши функцию неглубокого копирования объектов и массивов

> Опять же, не могу понять что с этим не так: Если это клон объекта, то этот клон должен иметь тот же прототип что и "донор"(?).


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

Вообще, в JS не все можно скопировать полностью. Некоторые встроенные объекты, например, массив, функцию-замыкание с захваченными переменными, или исключение, идеально скопировать может не получиться (насчет массива: он ведь мог быть создан в другом ифрейме, тогда копирование через var copy = [] не даст точную копию). Потому в задаче и не требуется все копировать полностью, а только то, что описано в условии.

> Лучше использовать for ... object.length вместо for in?


У объектов нету object.length, length есть только у массивов. Лучше использовать либо for .. of из ES5, либо проверку через hasOwnProperty() из ES3.

> https://jsfiddle.net/uyey3at1/1/


Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы. Иначе тест вроде Array.isArray() не пройдет на копии.

Глубокое копирование

> https://jsfiddle.net/j8pydqsg/2/


> var clone = new object.constructor;


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

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

Тут из-за кучи цитат становится уже трудно понимать некоторые ответы, если что-то непонятно, можно просто задать вопрос отдельно.
Старые ответы #31 #921312
>>912063

$b можно было бы вычислять из $i ($b = длина - $i - 1 или даже просто $b = - $i - 1), но твое решение в общем-то тоже верное.

>>919083

>>Конечно, копирует ссылку на функцию.


> Но функция находиться же в объекте obj! В чём подвох?



var o = {};
o.fn = function() {};

Функция o.fn сама по себе никак к этому объекту не привязана. Объект хранит в себе ссылку на функцию, а функция на объект - нет. Потому если мы копируем ее в отдельную переменную, и вызываем, то она про исходный объект ничего уже не знает и this указывает на window:

var f = o.fn;
f();

А вот если мы пишем

o.fn();

То интерпретатор JS видит, что функция вызвыается на объекте, и подсовывает его в качестве this.

Чтобы она "запомнила" свой объект, мы должны использовать bind:

var f = o.fn.bind(o);
f();

>>Задача 1: написать функцию bindContext(fn, that). Она создает новую функцию, которая при вызове вызывает fn с указанным this и переданным аргументами. То по сути есть привязывает произвольное значение this к функции.


> https://jsfiddle.net/Luubgokx/


Все верно.

>>Задача 2: сделать функцию addProperty(object, name, initialValue) для создания приватных свойств с геттерами и сеттерами на объекте или прототипе объекта.


> https://jsfiddle.net/sh21j4p1/


Тут опечатка в коде:

> addProperty(obj, 'test', 10);


> console.log(obj.getName());


Свойство test, а вызывается getName вместо getTest().

По коду: в общем, верный подход, мы прячем переменную в замыкании, но вот не очень понял, зачем использовать defineProperty. Функции get/set можно просто добавить через obj[funcName] = function ...

> name[0].toUpperCase() + name.slice(1)


Это конечно лучше было вынести в вспомогательную функцию.

Задача про фастфуд

> Почему-то не получается https://jsfiddle.net/y28h2o2b/3/


Там надо открыть отладчик (Ctrl + SHift + I) и включить режим "останавливаться на исключении". И там будет видно, что this.menu не определено, отсюда и ошибка.

Ест статья про отладку: http://learn.javascript.ru/debugging-chrome

Аналогичный отладчик есть и в Фаерфоксе, и в Сафари.

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

Электросеть

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



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

- можно вообще не делать свойств в базовом классе, и в каждом наследнике написать свой метод getPower() со своей логикой. Соответственно, наследник определяет, какие будут свойства (вроде числа квартир) и как из них вычисляется потребление.
- можно сделать в базовом классе свойства dayPower/nightPower и метод getPower, который их возвращает. А логику вычисления этих свойств писать в конструкторах наследников. И не делать свойств вроде числа квартир.

Первый подход наверно гибче.

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


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

> Лучше исключить её из перебора потому, что ЛЭП тоже может вернуть какое-то количество мощности.


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

> С другой стороны электросеть не знает о ценах и о внутреннем устройстве ЛЭП. Моя идея в том, баланс можно просто передать в условный счетчик. Ведь это для ЛЭП свойственно иметь и считать цену.


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

> https://jsfiddle.net/6591a2sL/4/



> this.elements.sort(function (a, b) {


> if (a.price > b.price) {


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

Также, sort меняет порядок следования элементов в this.elements, что может где-то быть нежелательно. Ведь получается что метод с названием get Something фактически изменяет внутреннее состояние объекта, что неожиданно. Лучше получить отдельный массив ЛЭП и сортировать его.

> if (this.elements instanceof PowerLine) {


> price += this.elements.countPrice(balance);


> balance = this.elements.countPower(balance);


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

> function Electrostation(power) {


> if (power >= 1 Math.pow(10, 6) && power <= 100 Math.pow(10, 6)) {


> this.power = power;


> this.nightpower = power;


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

> function PowerLine(power, price) {


> this.power = power;


> this.price = price;


> }


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

> PowerLine.prototype.countPower = function(power) {


> var thispower = this.power;



> for (var i = 0; i < thispower; thispower--) {


> if (power == 0) {


> break;


> }



> power += power / -Math.abs(power);


что-то я не могу толком понять, что тут происходит. Зачем мы power делим саму на себя? Получится ведь либо 1, либо -1. Тут явно ошибка.

Определение типа переменной

> Что подрузумевается здесь под словом 'хеш'?


Хеш, он же словарь, он же ассоциативный массив, он же объект - это вот это:

var x = { 1: 2, 'x': 'y' };

Я просто написал что вместо switch можно было сделать объект, в ключах которого хранятся значения вроде '[object Function]'. И искать тип в этом объекте.

>>Недостаточно, надо бы проверить что там есть свойства от 0 до length - 1.


>>от 0 до length - 1


> А как это выразить в условии


Написать цикл, проверяющий наличие свойств с помощью оператора in.

15. Напиши функцию неглубокого копирования объектов и массивов

> Опять же, не могу понять что с этим не так: Если это клон объекта, то этот клон должен иметь тот же прототип что и "донор"(?).


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

Вообще, в JS не все можно скопировать полностью. Некоторые встроенные объекты, например, массив, функцию-замыкание с захваченными переменными, или исключение, идеально скопировать может не получиться (насчет массива: он ведь мог быть создан в другом ифрейме, тогда копирование через var copy = [] не даст точную копию). Потому в задаче и не требуется все копировать полностью, а только то, что описано в условии.

> Лучше использовать for ... object.length вместо for in?


У объектов нету object.length, length есть только у массивов. Лучше использовать либо for .. of из ES5, либо проверку через hasOwnProperty() из ES3.

> https://jsfiddle.net/uyey3at1/1/


Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы. Иначе тест вроде Array.isArray() не пройдет на копии.

Глубокое копирование

> https://jsfiddle.net/j8pydqsg/2/


> var clone = new object.constructor;


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

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

Тут из-за кучи цитат становится уже трудно понимать некоторые ответы, если что-то непонятно, можно просто задать вопрос отдельно.
931910931914
Старые ответы #32 #921313
>>911927

> Спасибо. Будет интересно для практики сделать статус-бар загрузки контента не НА сервер, а С сервера.


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

> А ещё интересно было бы узнать, как по уму реализовывать хранение конфига системы в базе данных (как у всех популярных cms).


Сделать таблицу вида key | value, то есть 1 строка = 1 настройка. Если данные разных типов, то можно сделать key | int_value | string_value и тд.

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

> отдельная модель UserConfig с отдельной таблицей в БД, сохраняющая при каждом изменении данные в кэш.


Ты усложняешь раньше времени. Кеш можно добавить, но тогда надо решать, как именно его делать: 1 ключ для всех настроек или для каждой настройки свой ключ. И на малонагруженном сайте скорее всего с кешем будет примерно такая же скорость, что и с БД.

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

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


middleware - это в смысле что-то аналогичное middleware в Слиме? Оно явно не для настроек и конфигов предназначно.

> для всех запросов к серверу.


Вообще, логичнее читать конфиг, только если он нужен.
#33 #921320
>>919229

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

>>919179

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

>>919233

> while (($amount >= $value) and ($count > 0)) {


> $amount -= $value;


> $countBills += 1;


Цикл с вычитанием нужно заменить на деление. Учесть ограничение на число имеющихся банкнот можно с помощью min/max.

>>919568

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

Также тут есть еще идеи:

http://stackoverflow.com/questions/1070244/how-to-determine-the-first-and-last-iteration-in-a-foreach-loop

> end($array);


> $lastKey = key($array);


...

> if ($key === $lastKey)



Ну и я бы советовал вынести HTML в шаблон. И не писать array в названии переменной.

>>919968

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

>>920065

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

>>920199

Тут надо правильно выбрать формат массива. Например, можно сделать так:

- ключ обозначает текущий порядковый номер девочки от 0 до N (и ключи пересчитываются заново при удалении с помощью array_values/array_splice), а значение - исходный номер (когда еще все были в круге). На определенном шаге мы имеем такой массив:

[0] => [2]
[1] => [3]
[2] => [5]
[3] => [7]
...

Тогда нам достаточно иметь просто счетчик, который мы увеличиваем на X с переполнением, и удаляем девочку с таким индексом (например, через unset или array_splice). Переполнение счетчика делается через взятие остатка от деления на текущий размер массива.

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

И изучи функцию array_splice, она может быть полезна.
#33 #921320
>>919229

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

>>919179

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

>>919233

> while (($amount >= $value) and ($count > 0)) {


> $amount -= $value;


> $countBills += 1;


Цикл с вычитанием нужно заменить на деление. Учесть ограничение на число имеющихся банкнот можно с помощью min/max.

>>919568

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

Также тут есть еще идеи:

http://stackoverflow.com/questions/1070244/how-to-determine-the-first-and-last-iteration-in-a-foreach-loop

> end($array);


> $lastKey = key($array);


...

> if ($key === $lastKey)



Ну и я бы советовал вынести HTML в шаблон. И не писать array в названии переменной.

>>919968

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

>>920065

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

>>920199

Тут надо правильно выбрать формат массива. Например, можно сделать так:

- ключ обозначает текущий порядковый номер девочки от 0 до N (и ключи пересчитываются заново при удалении с помощью array_values/array_splice), а значение - исходный номер (когда еще все были в круге). На определенном шаге мы имеем такой массив:

[0] => [2]
[1] => [3]
[2] => [5]
[3] => [7]
...

Тогда нам достаточно иметь просто счетчик, который мы увеличиваем на X с переполнением, и удаляем девочку с таким индексом (например, через unset или array_splice). Переполнение счетчика делается через взятие остатка от деления на текущий размер массива.

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

И изучи функцию array_splice, она может быть полезна.
#34 #921321
>>920960

> Поэтому я делаю неглубокию копию массив и воздействую на элементы массива - объекты, которые соответственно будут меняться и в оригинальном массиве


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

И в коде конечно ошибки, например:

> if (typeof x != "number" || y != "number") {


Должно быть typeof y

Также, не уверен, что нужно свойство nearMines у Cell. Зачем оно там?

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

>>920988

Ну тут надо думать, какой подход будет удобнее. Оба подхода имеют право на жизнь. Главное отличие, что в случае массивов this._mines, this._flags информация хранится в классе Field, а не в объектах Cell.

Тут надо сравнивать такие вещи:

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

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

>>921117

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

Яваскрипт-проверка легко обходится злоумышленником.

>>921197

Можно в контроллер, можно в вспомогательный utility класс.

> var regex = new RegExp("^\\w(\\d){1," + Util.getNumberLength(this._minesweeperGame.MAX_HEIGHT) + "}$", "i");


Это уже переулсожнение, проще просто потом проверить значение числа.

> ведь наверное нельзя передавать аргументы в контроллер вот так game.setFlag(new Cell(1,5), верно?


Да, в условиях задачи требуется передавать человекопонятные обозначения.
#34 #921321
>>920960

> Поэтому я делаю неглубокию копию массив и воздействую на элементы массива - объекты, которые соответственно будут меняться и в оригинальном массиве


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

И в коде конечно ошибки, например:

> if (typeof x != "number" || y != "number") {


Должно быть typeof y

Также, не уверен, что нужно свойство nearMines у Cell. Зачем оно там?

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

>>920988

Ну тут надо думать, какой подход будет удобнее. Оба подхода имеют право на жизнь. Главное отличие, что в случае массивов this._mines, this._flags информация хранится в классе Field, а не в объектах Cell.

Тут надо сравнивать такие вещи:

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

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

>>921117

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

Яваскрипт-проверка легко обходится злоумышленником.

>>921197

Можно в контроллер, можно в вспомогательный utility класс.

> var regex = new RegExp("^\\w(\\d){1," + Util.getNumberLength(this._minesweeperGame.MAX_HEIGHT) + "}$", "i");


Это уже переулсожнение, проще просто потом проверить значение числа.

> ведь наверное нельзя передавать аргументы в контроллер вот так game.setFlag(new Cell(1,5), верно?


Да, в условиях задачи требуется передавать человекопонятные обозначения.
921447
#35 #921358
>>921283

как я тебе выгрызу заказ, куда уже 30 мухамедов постучалось, которые имеют рейтинг ~500 и говорят, что сделают не за 100$ а за 10?

>>921305
так и заказов дохуя, вот и спрашиваю.
#36 #921447
>>921321

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



Это связано что я выбрать подход с объектом Cell, а не с двумерным массивом поля? Если да, то ты же сам в задаче предлагаешь такой вариант.
921453924496
#37 #921453
>>921447

И еще, я так понял, ты намекаешь, что все таки надо делать глубокое копирование объектов.
#38 #922034
Нужно ли проверять переданные параметры в js функциях? В некоторых проектах этого не делают, а пишут перед методами/функциями комментарий для jsdoc с текстом вроде @param {number} [value]. Разве он что-то сделает если туда передать допустим строку?
924484
#39 #922117
Нашел неплохую книгу по PHP
Написана может не очень хорошо, но неплохие практики, перед прочтением пройдите туториал от ОПа.

>Бретт Маклафлин - PHP & MySQL. The Missing Manual, 2nd Edition / PHP и MySQL. Исчерпывающее руководство, 2-е издание

922237
2881 Кб, Webm
#40 #922138
>>921309

>>это ведь на проверку?


Возможно. Кажется, я как-то неправильно использую кастомные ограничители в валидаторе. Получается гораздо запутанней, чем если бы я написал свой класс валидатор. Стандартные ассерты, определенные аннотациями не работают, возможно из-за кастомного constraint validator. Я так понимаю, что нужно использовать для создания формы entity класс, но в форме всего 2-3 поля, а в классе их больше, к тому-же хочется проверять сразу класс, а не поля отдельно друг от друга. Я создал отдельные классы форм, это выглядит как костыль. По какой-то причине ошибки, выдаваемые валидатором при использовании метода getMessage() не имеют ключей и просто выдают месседжи об ошибке без привязки к полю объекта формы. Если тянуть ошибки из формы, то там их вообще нет. Я где-то накосячил и не пойму где.
В общем нужны советы и мб какието пояснения по коду. Про то, что нужно сделать бутстрап файл, я уже догадался. И возникла странная проблема: если поместить сонфиг подключения к бд в ини файл и сделать parse_ini_file, вставив значения в DoctrineServiceProvider(), то консоль не может подключиться к базе данных, хотя приложение ее видит и сайт работает.
924484
#41 #922237
>>922117

>mysql_connect, ни слова про ООП, html+php в одну кучу в 2k17


>неплохие практики


Это ты так пытаешься конкуренцию на рынке труда снизить?
922351
#42 #922276
Поясните за yii2, какие-нибудь годные ресурсы для изучения?
924484
#43 #922351
>>922237
kek. Если бы я нашел что-то лучше...
Просто того же Робина читал, у него вперемешку представление и код, тут хотя бы разделение, обрезание пробелов, что-то еще, что довольно неплохо. Нет ООП, да, это плохо, но хотя бы учат писать код правильно (до того места, где я дочитал).

Есть еще книга украинского программиста, но такое ощущение, что она писалась в разное время разными людьми, он более-менее кода, до вырвиглазного.
Из нормального мне понравилась только книга с рецептами, но там же не учат с нуля. Да и вообще актуальных книг не могу найти.
#44 #922390
>>922357

Значит стоит смириться и не ставить ифы для проверки типа переданных аргументов и выброса исключения?
924484
#45 #922684
Дорогой ОП, сделал калькулятор - http://ideone.com/PBnVRM
Это первая задача (не считая самые базовые), которую сделал полностью сам, не подсматривая код вообще нигде. Приятное чувство )
924484
#46 #922738
как же уничтожает мозг $ в имени переменных и отсутствие объявления. раньше писал на жс
все задачки переделываю раза по два, потому что по привычке ебашу var/let и без $, особенно в цикле фор.
922743922753
61 Кб, 200x200
#47 #922743
>>922738

> и отсутствие объявления


Это реально пиздец. Даже в древнем бейсике (Visual Basic 6 1998-го года) можно было включить режим обязательного объявления. А вот в PHP 2017-го года - нет. Воистину СЛАДКИЙ ХЛЕБУШЕК
922760
#48 #922753
>>922738

>как же уничтожает мозг $ в имени переменных


>раньше писал на жс


>жс


Чья бы корова мычала.

>>922738

>отсутствие объявления


Объявления чего?
922760922761
#49 #922760
>>922753

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

Человеческого объявления переменных с областями видимости и все такое. Сразу писать х = "оп-хуй" - неприятно и >>922743 согласен.

еще не очень нравится, что СКЛАДЫВАНИЕ строк происходит ТОЧКОЙ, но это уже хуй с ним.
язык как язык, не знаю, чому его критикой до уровня 1С опускают
922762922768
#50 #922761
>>922753

и да, если ты подразумеваешь, что все жс-юзеры дрочат $$$$$$ в жквери, то ты ошибаешься. У нас там уже реакт, нода, и куча всего, чем успешный говнокодер может лепить говносайты и взламывать глаза и логику хороших кодеров.
#51 #922762
>>922760
потому что код превращается в этот самый хлебушек
922764922768
#52 #922764
>>922762
я покушать принес:
http://uglycode.com/tag/php/
#53 #922768
>>922760

>Человеческого объявления переменных


>>php


$ti = 'loh';

>>js


var ti = 'loh';

>>с областями видимости и все такое.


Что с ними не так? По существу можешь сказать?

>>922762

>потому что код превращается в этот самый хлебушек


Это проблема программиста, а не языка.
922770922771
#54 #922770
>>922768

for (let i = 0; i < array.length; i++) {}
for ($i = 0; $i < $length; $i++) {}
1. читабельно без $$$$, переменная i создается на время действие цикла и выгружается из памяти после его конца, есть отдельный метод, читающий длинну строки, массива, аллаха.
2. я очень люблю доллары, но тут они не настоящие, чтоб читать длинну массива, надо ее записать в переменную, либо делать огромное условие.

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

и да, foreach применяется не везде, так что .length - важная фича.
922773924460
#55 #922771
>>922768

еще в пхп ругается интерпретатор, если я задаю переменную внутри чего-то, того же цикла. Надо как дебилу сначала до него написать $x = 0 или "".
922773924460
#56 #922773
>>922770

> читабельно без $$$$


Исключительно вкусовщина.

>for ($i = 0; $i < count($array); $i++) {// переменная доступна только в теле цикла, после его завершения память освобождается.}



Проблемы?

> foreach применяется не везде


В php 99% это foreach.

>>922771

>еще в пхп ругается интерпретатор, если я задаю переменную внутри чего-то, того же цикла. Надо как дебилу сначала до него написать $x = 0 или "".


Шо? Это как?.
922779
#57 #922779
>>922773

ну, типа я пишу тот де форич иии { $буква = значение... }, и потом смотрю, что это надо было вынести и поставить до начала функции.
В общем, забей, это просто мои барибухи с непривычки, вот и все.
922781
#58 #922781
>>922779
Это не баг, а фитча.
Область видимости переменной не может выходить за рамки контекста в котором она определена.( локальные переменные )
Можно конечно продлить жизнь временным данным, но это уже другая история
#59 #922793
Есть что почитать клевое по паттернам и ооп? Пробовал Зандстру и дропнул как раз на той главе где начинаются шаблоны, тупо льет воду, не могу читать такое.

Мне надо не рассусоливать о том как круты паттерны проектирования, а что: вот есть у нас проблема, и вот смотри какой есть элегантный способ её решить, го расскажу!
922795924460
#60 #922795
>>922793
Kristopher Wilson - The Clean Architecture in PHP
922799
#61 #922799
>>922795

>Kristopher Wilson - The Clean Architecture in PHP


только на английском бывает?
#62 #922856

>Кевин Янк - PHP и MySQL. От новичка к профессионалу - 2013



Тут вместо mysql_connect ПДО.
#63 #923235
Опытные аноны, поясните: почему свойство-лямбду нельзя вызвать?

Типа такого кода:

> $obj = array('show' => function() { echo 'test'; });


> $obj = (object) $obj;


> $obj->show(); // кидает ошибку `Call to undefined method stdClass::show`


.

Зачем? Почему? Там ведь даже контекст не нужен (`$this` не используется), так почему в языке так нельзя?
924460
#64 #923274
>>923261

>ты из руби?


Нет, из JS, лол.

>У нас тут не принято манкипатчить


Дык я не собирался.
Пришлось в коде конвертировать объект в массив, вспомнил о том, как когда-то давно с этим экспериментировал и как обнаружил эту странность. Решил спросить.

>сall_user_func


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

Короче, как я понял, эта дрянь формируется где-то на уровне транслятора, а потом можно только "вызвать метод strClass::show в контексте объекта obj", но не "получить свойство show объекта obj и вызвать его".
Видимо, я мыслю слишком "по-JSному". Охуевал когда узнал, что, по сути, в PHP нет большой разницы между статичными методами и обычными.

В любом случае, лучей добра тебе ^_^
924460
#65 #923288
>>923286
Я об этом-же.
PHP позволяет

>"вызвать метод strClass::show в контексте объекта obj"


вместо

>"получить свойство show объекта obj и вызвать его"


. Хрен знает почему, но так, видимо, нужней. Ну и хуй с ним.
52 Кб, 750x499
#66 #923333
При запуске скрипт показывает процесс импорта – номер позиции и количество использованной PHP-памяти. Когда количество памяти приближается к 350 Мб – импорт замедляется. Первые 11000 позиций обновляются приблизительно минут за 10-15. Затем доходит до 1 позиции за 3 секунды.

Анончик там лимит на оперативку и свопится начинает? Оперативки на сервере 8 гигов
923513924460
#67 #923336
Анон, все мое программирование закончилось на первом курсе универа на паскале. В школе в блокноте писал какие то одностраничный примитивные сайты. И венец творения калькулятор, возводящий в степень и производящий выделения корня, написаный в паскале. И тут в 25 решил вкатиться в программирование. Собственно прочитал гайд и понял, что нужно пошагово как в гайде учиться.верно? И сильно я сосну с маком? Надо ли накатывать винду на него?
923339923924
#68 #923339
>>923336

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


Да.

>И сильно я сосну с маком? Надо ли накатывать винду на него?


С ним даже удобнее будет.
#69 #923499
Поясните кто-нибудь за побитовые операторы.
То есть смещается вправо или влево? Это про запятую, то есть было 1, стало 100?
923502924455
#70 #923502
>>923499
Нет, это про биты.
Почитай об этом лучше в учебнике по JS: learn.javascript.ru/bitwise-operators - там намного лучше описано что это и где применяется, нежели в документации PHP.
#71 #923513
>>923333
Похоже здесь какие-то циклы разрастаются, в результате этот единственный процесс как было 90% процессорного времени занимал, так и сейчас занимает, но скорость обновления товара все сильнее падает. Анончик помоги это выше моего уровня

foreach($rows as $r => $row){

$i++;
if($i < 0) {
// continue;
}

print $r.' - '.round(memory_get_peak_usage()/1024/1024) . PHP_EOL;

$item = explode(';',$row);
foreach($item as $k=>$v){
$v = ltrim($v, '"');
$v = rtrim($v, '"');
$item[$k] = $v;
}
if(is_numeric($item[0])){
import_product($item);
}

$row = null;
$item = null;
}
923519924455
#72 #923519
>>923513
Ну и что это за хуйня?
923548
#73 #923548
>>923519
В общем путем расставления микротаймов выявил тормоз в левой функции, а конкретнее в этом участке,

if(!$product){
$product = commerce_product_new('product');
$product->status = '1';
$product->uid = '1';
$product->created = $product->changed = time();
$product->is_new = TRUE;
//print 'Creating new product!'.PHP_EOL;

}
923565
#74 #923565
>>923548

> if(!$product){


Вот в этой суке. Что означает восклицательный знак? == "" ?
923573924455
#75 #923573
>>923565

>>Что означает восклицательный знак?


ой, лооооооооооооооооооооол
923578
77 Кб, 1126x547
#76 #923578
>>923573
Вот какого хуя антош? какого хуя? Исполнение функции дальше не проходит! все стопается на этапе сравнения!
923602924455
#77 #923602
>>923578

>стопается на этапе сравнения!


После какого сравнения?
923604923605
#78 #923604
>>923602
UPD. Если у тебя $product - это строка, то выводится его длина и выполнение программы прекращается.
#79 #923605
>>923602
Уже нашел. Теперь ищу фукцию, она где-то в другом файле, в подключаемых нет
923606
#80 #923606
>>923605
Сделай отступы и переходы строки нормальные, а то как долбоеб.
31 Кб, 1351x381
#81 #923725
В общем методом дедукции и расставлением микротаймов было выяснено, что скрипт в основном тратит время чтобы пройти участок кода return $controllers[$entity_type];

$entity_type - это commerce_product
$controllers[$entity_type]; - не содержит ничего
count ($controllers[$entity_type];) - не содержит ничего

Не знаю почему участок тормозит.
Вот вся цепочка которую я раскручивал:
---------------

function import_product($item){
$product = commerce_product_load_by_sku($item[14]);

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

function commerce_product_load_by_sku($sku) {
$start = microtime(true); //начало измерения
print "^^^^ 0 $start ";
$products = commerce_product_load_multiple(array(), array('sku' => $sku));

$end3 = microtime(true); //конец измерения
print "3 $end3 !!!";

return $products ? reset($products) : FALSE;
}

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

function commerce_product_load_multiple($product_ids = array(), $conditions = array(), $reset = FALSE) {

$end2 = microtime(true); //конец измерения
print "2 $end2 !!!";

if (empty($product_ids) && empty($conditions)) {
return array();
}

return entity_load('commerce_product', $product_ids, $conditions, $reset);
}

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

function entity_load($entity_type, $ids = FALSE, $conditions = array(), $reset = FALSE) {
$start = microtime(true); //начало измерения
print "^^^^ 5 $start ";
if ($reset) {
$end2 = microtime(true); //конец измерения
print "6 $end2 !!!";

entity_get_controller($entity_type)->resetCache();

$end3 = microtime(true); //конец измерения
print "7 $end3 !!!";
}

$end8 = microtime(true); //конец измерения
print "8 $end8 !!!";

return entity_get_controller($entity_type)->load($ids, $conditions);
}
31 Кб, 1351x381
#81 #923725
В общем методом дедукции и расставлением микротаймов было выяснено, что скрипт в основном тратит время чтобы пройти участок кода return $controllers[$entity_type];

$entity_type - это commerce_product
$controllers[$entity_type]; - не содержит ничего
count ($controllers[$entity_type];) - не содержит ничего

Не знаю почему участок тормозит.
Вот вся цепочка которую я раскручивал:
---------------

function import_product($item){
$product = commerce_product_load_by_sku($item[14]);

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

function commerce_product_load_by_sku($sku) {
$start = microtime(true); //начало измерения
print "^^^^ 0 $start ";
$products = commerce_product_load_multiple(array(), array('sku' => $sku));

$end3 = microtime(true); //конец измерения
print "3 $end3 !!!";

return $products ? reset($products) : FALSE;
}

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

function commerce_product_load_multiple($product_ids = array(), $conditions = array(), $reset = FALSE) {

$end2 = microtime(true); //конец измерения
print "2 $end2 !!!";

if (empty($product_ids) && empty($conditions)) {
return array();
}

return entity_load('commerce_product', $product_ids, $conditions, $reset);
}

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

function entity_load($entity_type, $ids = FALSE, $conditions = array(), $reset = FALSE) {
$start = microtime(true); //начало измерения
print "^^^^ 5 $start ";
if ($reset) {
$end2 = microtime(true); //конец измерения
print "6 $end2 !!!";

entity_get_controller($entity_type)->resetCache();

$end3 = microtime(true); //конец измерения
print "7 $end3 !!!";
}

$end8 = microtime(true); //конец измерения
print "8 $end8 !!!";

return entity_get_controller($entity_type)->load($ids, $conditions);
}
923730924446
#82 #923730
>>923725

> $controllers[$entity_type]; - не содержит ничего


Ошибся. Там единица. Сраная единица!
#83 #923731
Я только вкатываюсь в пхп, полностью с нуля. Мне вообще ничего не понятно. Это нормально ?
#84 #923743
>>923731
Нет, иди лучше кричать "свободная касса", там тебе понятней все будет.
923762
#85 #923762
>>923743
Какой добряк, ты наверное на концертах Петросяна кричать любишь
923779
#86 #923769
>>923731
Лучше спросить что непонятно, чем дожидаться поддержки здесь
#87 #923779
>>923762
Да, ухахатываюсь просто.
#88 #923817
API может быть сделано только посредством JS?
923824
#89 #923824
>>923817

А ты вообще понимаешь, что такое API?
923835
#90 #923835
>>923824
По своей сути это что-то что позволяет общаться друг с другом различным программам и не только...

Я точнее хотел спросить -API можно предоставить только посредством JS или есть ещё какие-то другие варианты?
923894923921
#91 #923894
>>923835

API обычно это либо набор функций в библиотеке, либо (в случае веб-сервисов) набор URL, к которым можно обратиться. Яваскрипт тут вообще не при чем. Это можно делать на любом языке программирования.
924019
#92 #923921
>>923835

>Я точнее хотел спросить -API можно предоставить только посредством JS или есть ещё какие-то другие варианты?


Твое API что должно делать? Ты знаешь различия между front end и back end? Твоему API нужны какие данные, которые необходимо формировать на стороне сервера?
924019
#93 #923922
>>923731
Вообще ничего? Вот открыл книгу для самых новичков и с первой же страницы ничего не понял? Нет, это ненормально.
#94 #923924
>>923336
Я маки терпеть не могу, но стоит признать, что как ОС она в чем-то намного более прямая и правильная. Возможно, будут проблемы с выбором инструментария разного рода - на винде арсенал шире в разы.
923937924446
#95 #923937
>>923924
вряд ли будут у него проблемы с этим, лол.
Все хорошие IDE и редакторы кода прекрасно там работают + есть терминал.
#96 #923981
Есть кто? Нужна помощь, я года 3 назад работал на пхп, всё забыл.
924446
#97 #924019
>>923894
Сам себя запутал. Я видел пример как подключают js файл в шапке html документа по ссылке, и подумал что уже этот js файл взаимодействует с сервером где находиться этот файл.

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

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

Допустим я хочу воспользоваться API от сайта example.com на своем сайте mysite.org
Что должен предоставить сайт example.com чтобы предоставить свой функционал для моего сайта?

>(в случае веб-сервисов) набор URL, к которым можно обратиться


Этим пользуются с помощью html-тэга iframe? Есть ещё какие-нибудь варианты?

>>923921
У меня не какой-то конкретный случай. Пытаюсь разобраться как работает любое API.
924046924077
#98 #924046
>>924019
Какие ЯП ты изучал/знаешь?
#99 #924077
>>924019

Реализовать доступ к API можно по-разному. Кто-то подключает js-файл на веб-страницу и скрипты на странице вызывают функции в том файле. А кто-то обращается к API со своего сервера или из мобильного приложения, и там они могут использовать любой язык программирования.

Если ты хочешь выполнять код в браузере пользователя то да, нужен яваскрипт (API тут не при чем, просто большинство браузеров поддерживают только JS). Если ты не ограничен браузером, то можно использовать любые языки.
924121
#100 #924085
Дали тестовое - написать свой парсер для html тегов на пыхе. Что-то я залип на этой теме. Это же дохуя объёмна работа, не?
924097924104924446
#101 #924097
>>924085
А что твой парсер делать в итоге должен то?
924112
#102 #924104
>>924085
Смотря что подразумевается под "парсером для html тегов".
924112
#103 #924112
>>924097
>>924104
типа считать теги на странице, которую ему дадут. Вроде реализуемо и даже прогресс есть, но я ебал такие тестовые делать для каждой вакансии, блядь (это не единственный вопрос, как вы, наверное, уже догадались)
924117
#104 #924117
>>924112

>типа считать теги на странице, которую ему дадут.


Просто получить количество тегов на страничке? А какие-то требования были дополнительные? Ну потому что вроде тут из сложнго только подумать в каком виде представить базу данных с тегами. Я конечно не делал, но так вроде с помощью парочки регулярок и циклов можно сделать.
924128
#105 #924121
>>924077

>А кто-то обращается к API


Но как можно обратиться к нему, если оно находиться на стороннем сервере? Как, например, посредством php получить доступ к функции, например, getAllPost(...) из этого API, которое находиться на другом сервере? Или как это делается. Я это понять не могу.
924424
#106 #924128
>>924117
Это я как раз уже сделал, но из требований: оформить всё в правильный ООП, чтобы решение было расширяемым, мать его. Ну и всякие по мелочи отдать в виде xml и html (не понимаю, как можно отдать результаты поиска тегов в виде хтмл?) короче, не имея опыта с этой хуйнёй чувствую, что написал полное дерьмо
924133924446
#107 #924132
Продолжаю изучать книгу

>Кевин Янк - PHP и MySQL. От новичка к профессионалу - 2013



Что хорошо:
пхп код отделен от HTML;
Рассказывают о том, данные от пользователя не безопасны;
Для полдключения к бд используется PDO, как им пользоваться, основные команды.
Например по книге делаем сборник анекдотов: создаем таблицы с шутками, авторами, у шуток есть категории. Все это вместе соединяем, создаем, редактируем и тому подобное.

В книге не разъясняется синтаксис html и css, азовые вещи скорее всего тоже пропущены, но я сам начал смотреть книгу где-то с 3 главы.

По беглому взгляду не нашел MVC, паттерны, продвинутое ООП и так далее.
Книга подойдет начинающим, если вы до этого что-то читали.
924446
#108 #924133
>>924128

>оформить всё в правильный ООП


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

>чтобы решение было расширяемым, мать его.


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

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


В смысле? Тебе список тегов надо вернуть в итоге? Ну так почитай как сохранять инфу в виде хмл.
924135
#109 #924135
>>924133
Ну я правильно понимаю, что если мне надо вернуть список "тег" - "колво" в HTML формате, то я внутри php скрипта генерю html страницу в виду гигансткого string'a и в него в <table> загоняю свои значения? Или это не так делается?
924136924138924429
#110 #924136
>>924135
и если правильно понимаю, то надо ли отдавать только <table>куча инфы</table> или надо отдавать строку аж с !DOCTYPE ?
#111 #924138
>>924135
Запости лучше саму задачу.
924144
#112 #924144
>>924138
да не хотелось бы палить текст задачи, гуглиться же на раз будет, поймут сразу, что я на форуме для девочек ответы спрашивал
#113 #924166
>>919074 (OP)
Привет, аноны.
Какой лучше всего способ использовать для подключения к дб?
<?php
require_once 'login.php';
$conn = new mysqli($hn, $un, $pw, $db);
if ($conn->connect_error) die($conn->connect_error);
?>


Или $connect = mysqli_connect('localhost', 'root', '12345', 'mydb');
Вообще будет ли это юзаться где или же сразу надо копать какой-нибудь нетбим ОРМ?
#114 #924168
>>924166
Лучше юзай PDO.
924170
#115 #924170
>>924168

>PDO


Есть какой самоучитель хороший или прямо http://phpfaq.ru/pdo тут начинать? Почему не стоит через ORM?
924177
#116 #924171
>>924166
глянь книгу

>Кевин Янк - PHP и MySQL. От новичка к профессионалу - 2013



Тут расписано.
924173
#117 #924173
>>924171

>Кевин Янк - PHP и MySQL


Благодарю, анон, сейчас гляну. Много книг смотрю и одна хуйня, ей богу
#118 #924177
>>924170
Причем тут ORM? ORM это уже архитектурные изыски. Ты явно путаешь это с драйвером БД. PDO это просто самая удобная на данный момент обвязка драйвера БД.
924188
#119 #924188
>>924177
Как причем? Коннектиться с помощью орм, через её код, и всё, самое безопасное подключение с помощью ретбин настолько я знаю
924215924446
#120 #924203
Аноны, тупой я, что значит этот -> оператор?
и die
Я так понял это что-то типа break?
924212924246924429
#121 #924207
Поясните пожалуйста, зачем нужно делать отдельно файл для каждого класса если можно сделать библитеку и её инклудить? Помогите дауну
924357939968
#122 #924212
>>924203
-> вызов свойства или метода объекта
а вообще php.net
#123 #924215
>>924188
Ты все таки хуиты где-то нахватался. Тот же mysqli это просто расширение для работы с бд в пхп, это еще не ORM в полном виде. ORM в целом это уже нечто посложнее, погугли что такое active record, data mapper и т.п, освоишь это а там уже до доктрины какой-нибудь дорастешь. Если же тебе интересно какое расширение лучше - сейчас почти все юзают пдо.
#124 #924227
Анончики, особенно кто делал задачу про файлообменник, возникла у меня проблемка, а именно - про сохранении файлов на сервер с кирилическими названиями вместо оных появляются кракозябры, т.е. понятное дело проблемы с кодировкой.
public function upload(\Slim\Http\UploadedFile $file)
{
$params = $this->getFileParams($file);
$file->moveTo($params['link']);
}
В парамсе у меня хранятся данные о файле, но не суть. Что интересно, кириличные имена файлов с помощью mb_detect_encoding() определяются как ютф-8, а латинца - асц2. Как решить проблему? В гугле все советуют не париться и латинизировать названия, но мне бы хотелось все таки сохранять в кирилице. Алсо в БД имена сохраняются как положено.
924429
#125 #924245
>>924166
Юзай ООП.
#126 #924246
>>924203

>что значит этот -> оператор?


То же самое, что точка в псевдокоде.
#127 #924249
Аноны, не нашёл SQL-треда, поэтому пишу сюда. Не могу найти нормальную статью по этому вопросу.

>tinyint(1)


значит, что я могу хранить только 1 или 0 в этой колонке, или что могу хранить числа 0-9?

Логично было бы предположить, что 1/0, но всё-таки.
924253924446
#128 #924253
>>924249
Можешь хранить числа в ренже -128..127. И ничего не спрашивай больше, храни просто и все.
924256924263924446
#129 #924256
>>924253
Стоп, а если я напишу

>tinyint(3)


, например?
924263
#130 #924263
Всё, уже разобрался. Параметр size нужен для всяких ZEROFILL.

>>924253
Спасибо :з

>>924256-кун
#131 #924306
где взять опыт разработки проектов? начал изучать yii2
924308924446924676
#132 #924308
>>924306
сделать свой
#133 #924341
Сап. Изучаю Symfony 3, хочу сделать магазин на нем для закрепления знаний.
Но так как мне немного лениво и от крудов тошнит, да и с php я хорошо знаком, писал уже на Yii, то реквестирую более-менее готовый каркас для создания магазинов или crm на симфони. Есть же, наверное, какой-то открытый компонент такой на гитхабе с базовым функционалом магазина? Чтобы можно было доделать его, добавить какую-то фичу по желанию, управление акциями, например.
924385924446924676
#134 #924357
>>924207
Так намного удобней код редактировать.
39 Кб, 857x492
#135 #924374
Я только что вкотился, поясните как сделать в нетбинсе, чтоб результат сразу показывало в браузере? В настройках выбираю пикрел, когда пытаюсь запустить, в браузере нихуя. Надо похапе установить или что? Если что я на убунте.
924446
#136 #924385
>>924341
Уебище, ты даже загуглить не в состоянии, какой crm???
Возьми cms и уебывай.
#137 #924424
>>924121

А как по-твоему браузер загружает страницы? И как яваскрипт обращается к API на удаленном сервере?

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

Вот пример АПИ, которое предоставляют Яндекс-карты (API геокодера). Оно позволяет определить по адресу координаты точки или наоборот: https://tech.yandex.ru/maps/doc/geocoder/desc/concepts/input_params-docpage/

Там в самом начале написано:

> Запрос к геокодеру представляет собой обращение по протоколу HTTPS к URL https://geocode-maps.yandex.ru/1.x/.



То есть необходимо установить сетевое соединение с узлом geocode-maps.yandex.ru и далее отправить по нему HTTPS-запрос.

Я тебе советую почитать про такие темы:

- протокол TCP/IP
- протокол HTTP
- сокеты (не вебсокеты, а сокеты Беркли)
924586
#138 #924429
>>924135

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

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

>>924203

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

Про die можно прочесть в мануале.

>>924227

> Что интересно, кириличные имена файлов с помощью mb_detect_encoding() определяются как ютф-8, а латинца - асц2.


Эта функция не работает и возвращает случайные значения. Почитай например мой урок про кодировки и сам поймешь, почему в принципе невозможно 100% точно определить кодировку (можно только угадывать с какой-то вероятностью): https://github.com/codedokode/pasta/blob/master/cs/strings.md

Насчет имен файлов - тут такая ситуация:

Имена файлов скорее всего приходят в $_FILES в той кодировке, которая исользовалась на HTML-странице. Насколько я знаю, браузер вообще все данные форм ($_POST, $_FILES) кодирует кодировкой страницы, где эта форма расположена. Данные в _GET - не уверен, то ли кодировкой страницы, то ли всегда utf-8

Функции работы с файлами вроде fopen, file_put_contents, move_uploaded_file принимают имена в той кодировке, которая определяется ОС и ее настройками:

- в Windows они принимают имена в 8-битной кодировке, зависящей от языка системы. Для русского языка это Windows-1251
- в Mac они принимают имена в utf-8
- в Linux имена файлов не имеют определенной кодировки. Но отображение имен файлов использует заданную в системе кодировку, как правило, это utf-8. То есть в linux скорее всего надо передавать имена в utf-8

Теперь у тебя есть понимание, как решить проблему?
#138 #924429
>>924135

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

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

>>924203

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

Про die можно прочесть в мануале.

>>924227

> Что интересно, кириличные имена файлов с помощью mb_detect_encoding() определяются как ютф-8, а латинца - асц2.


Эта функция не работает и возвращает случайные значения. Почитай например мой урок про кодировки и сам поймешь, почему в принципе невозможно 100% точно определить кодировку (можно только угадывать с какой-то вероятностью): https://github.com/codedokode/pasta/blob/master/cs/strings.md

Насчет имен файлов - тут такая ситуация:

Имена файлов скорее всего приходят в $_FILES в той кодировке, которая исользовалась на HTML-странице. Насколько я знаю, браузер вообще все данные форм ($_POST, $_FILES) кодирует кодировкой страницы, где эта форма расположена. Данные в _GET - не уверен, то ли кодировкой страницы, то ли всегда utf-8

Функции работы с файлами вроде fopen, file_put_contents, move_uploaded_file принимают имена в той кодировке, которая определяется ОС и ее настройками:

- в Windows они принимают имена в 8-битной кодировке, зависящей от языка системы. Для русского языка это Windows-1251
- в Mac они принимают имена в utf-8
- в Linux имена файлов не имеют определенной кодировки. Но отображение имен файлов использует заданную в системе кодировку, как правило, это utf-8. То есть в linux скорее всего надо передавать имена в utf-8

Теперь у тебя есть понимание, как решить проблему?
924502
#139 #924446
>>924374

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

Разберись с тем, какие варианты есть. Если что, они тут на англ. описаны: https://netbeans.org/kb/docs/php/project-setup.html#runConfiguration

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

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

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

>>924341

Я знаю, что есть фреймворк Magento, но он не на Симфони.

>>924306

В ОП посте есть задачи на разработку файлообменника, сайта TestHub.

>>924249

Цифра задает рекомендуемую ширину колонки для вывода чисел. На хранение в базе данных это никак не влияет.

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

Вот офиц. мануал на англ, проясняющий этот вопрос:

- https://dev.mysql.com/doc/refman/5.7/en/integer-types.html
- https://dev.mysql.com/doc/refman/5.7/en/numeric-type-attributes.html

Обрати внимание, что для дробных чисел цифры в скобках имеют другой смысл:

- https://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html
- https://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html

>>924253

Что значит "не спрашивай"? Как раз надо спрашивать, если что-то непонятно.

>>924188

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

>>924166

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

>>924128

Проверяют, знаешь ли ты ООП.

>>924132

> Рассказывают о том, данные от пользователя не безопасны;


А что с этим делать и как решать эту проблему, рассказывают?

> В книге не разъясняется синтаксис html и css,


Предполагается что ты уже их знаешь.

>>924085

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

>>923981

Ну смотри сколько постов тут нафлудили. Конечно, есть.

>>923924

Ну не знаю, я использовал когда-то хакинтош и у меня осталось ощущение, что он тормозной. Конечно, может это из-за того, что это хакинтош, но у меня ощущение, что оно рассчитано на мощное железо и например на стареньком Core 2 duo с медленным HDD быстро не заработает. А Windows XP - заработает.

И там вроде до сих пор не научились раскрывать окна на весь экран?

>>923731

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

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

>>923725

Видимо, ты что-то считаешь неправильно. Также, надо учесть что под виндой точность функции microtime(true) составляет около 15 мс, то есть время может получиться либо 0 либо 15 мс, но не 1 или 2 мс например. И если ты попадешь на границу между 2 интервалами то вернется 15 мс даже если в реальности там было намного меньше.

Лучше бы использовать профайлинг в xdebug.

> return $controllers[$entity_type];


Если $controllers - это массив, то это мнговенно выполнится, но если это объект с магическими методами или ArrayAccess, то конечно возможны варианты.
#139 #924446
>>924374

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

Разберись с тем, какие варианты есть. Если что, они тут на англ. описаны: https://netbeans.org/kb/docs/php/project-setup.html#runConfiguration

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

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

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

>>924341

Я знаю, что есть фреймворк Magento, но он не на Симфони.

>>924306

В ОП посте есть задачи на разработку файлообменника, сайта TestHub.

>>924249

Цифра задает рекомендуемую ширину колонки для вывода чисел. На хранение в базе данных это никак не влияет.

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

Вот офиц. мануал на англ, проясняющий этот вопрос:

- https://dev.mysql.com/doc/refman/5.7/en/integer-types.html
- https://dev.mysql.com/doc/refman/5.7/en/numeric-type-attributes.html

Обрати внимание, что для дробных чисел цифры в скобках имеют другой смысл:

- https://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html
- https://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html

>>924253

Что значит "не спрашивай"? Как раз надо спрашивать, если что-то непонятно.

>>924188

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

>>924166

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

>>924128

Проверяют, знаешь ли ты ООП.

>>924132

> Рассказывают о том, данные от пользователя не безопасны;


А что с этим делать и как решать эту проблему, рассказывают?

> В книге не разъясняется синтаксис html и css,


Предполагается что ты уже их знаешь.

>>924085

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

>>923981

Ну смотри сколько постов тут нафлудили. Конечно, есть.

>>923924

Ну не знаю, я использовал когда-то хакинтош и у меня осталось ощущение, что он тормозной. Конечно, может это из-за того, что это хакинтош, но у меня ощущение, что оно рассчитано на мощное железо и например на стареньком Core 2 duo с медленным HDD быстро не заработает. А Windows XP - заработает.

И там вроде до сих пор не научились раскрывать окна на весь экран?

>>923731

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

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

>>923725

Видимо, ты что-то считаешь неправильно. Также, надо учесть что под виндой точность функции microtime(true) составляет около 15 мс, то есть время может получиться либо 0 либо 15 мс, но не 1 или 2 мс например. И если ты попадешь на границу между 2 интервалами то вернется 15 мс даже если в реальности там было намного меньше.

Лучше бы использовать профайлинг в xdebug.

> return $controllers[$entity_type];


Если $controllers - это массив, то это мнговенно выполнится, но если это объект с магическими методами или ArrayAccess, то конечно возможны варианты.
924525
#140 #924455
>>923578

У тебя в коде ошибка. Переменная $size создается внутри блока if, но используется снаружи, и возможно, что она в некоторых случаях даже не создается (или выводится старое значение). То есть тебе стоило бы язык PHP подучить для начала.

>>923565

Открой мануал http://php.net/manual/ru/language.operators.logical.php

>>923513

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

>>923499

Битовые операторы работают с представление числа в двоичном виде (из нулей и единиц). Сдвигается именно число в двоичном представлении. Начни с изучения двоичной системы счисления:

- https://ru.wikipedia.org/wiki/Двоичная_система_счисления
- https://ru.wikipedia.org/wiki/Битовые_операции

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

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

Когда-то их еще использовали для оптимизации (сдвиг влево на 1 разряд равносилен умножению на 2, только выполнялся быстрее), но это неактуально для высокоуровневых языков вроде PHP/JS и не дает никакой выгоды.
#141 #924460
>>923333

Проверить, свопится или нет, можно так:

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

>>923235

Можно, только надо использовать синтаксис, не похожий на вызов метода:

$fn = $obj->fn;
$fn();

или ($fn->obj)();

То, что ты пишешь, $obj->fn() - это вызов метода fn, которого у тебя нет, отсюда ошибка.

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

>>923274

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

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


Разница есть, они работают как и принято в ООП.

>>922793

Для ООП есть глава в нашем учебнике из ОП поста.

Для паттернов надо взять код, где они используются, например, компоненты Symfony Forms, Symfony Validation, Doctrine, и изучать их параллельно с паттернами. Так, просто в теории их изучать смысла нет.

>>922771

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

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

>>922770

Если ты хочешь тут поискать претензии к PHP, советую сразу брать статью https://habrahabr.ru/post/315152/

Ты к ерунде придираешься, а реальных проблем не видишь. Ну и в JS их не меньше, кстати. Чего стоит только отсутствие нормального ООП.

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


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

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



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


Так в PHP даже короче получается.
#141 #924460
>>923333

Проверить, свопится или нет, можно так:

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

>>923235

Можно, только надо использовать синтаксис, не похожий на вызов метода:

$fn = $obj->fn;
$fn();

или ($fn->obj)();

То, что ты пишешь, $obj->fn() - это вызов метода fn, которого у тебя нет, отсюда ошибка.

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

>>923274

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

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


Разница есть, они работают как и принято в ООП.

>>922793

Для ООП есть глава в нашем учебнике из ОП поста.

Для паттернов надо взять код, где они используются, например, компоненты Symfony Forms, Symfony Validation, Doctrine, и изучать их параллельно с паттернами. Так, просто в теории их изучать смысла нет.

>>922771

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

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

>>922770

Если ты хочешь тут поискать претензии к PHP, советую сразу брать статью https://habrahabr.ru/post/315152/

Ты к ерунде придираешься, а реальных проблем не видишь. Ну и в JS их не меньше, кстати. Чего стоит только отсутствие нормального ООП.

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


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

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



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


Так в PHP даже короче получается.
926674
#142 #924484
>>922684

Молодец, решено правильно.

>>922454

Справедливости ради, NaN это разновидность дробного числа в стандарте IEEE https://habrahabr.ru/post/112953/

>>922034

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

>>922390

Можно ставить, хуже не будет.

>>922276

Документация.

>>922138

> Стандартные ассерты, определенные аннотациями не работают, возможно из-за кастомного constraint validator.


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

Вот тут в документации, например, ограничения задаются статическим методом, а не аннотациями: http://symfony.com/doc/current/components/validator/metadata.html

А вот тут описывается, какие способ загрузки аннотаций есть: http://symfony.com/doc/current/components/validator/resources.html

Ты используешь AnnotationLoader?

Далее ты должен передать правильно настроенный Валидатор в FormFactoryBuilder как в примере тут: http://symfony.com/doc/current/components/form.html#validation

Я вижу, ты используешь SilexFormProvider. Выясни, как именно он настраивает компонент форм и валидатор.

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



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

Такая штука есть во всех фреймворках, в Юи например ограничения описываются массивом: https://yiiframework.com.ua/ru/doc/guide/2/input-validation/

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

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

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

Либо же разобраться с аннотациями и как-то брать описание формы из класса модели формы.

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

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

> Я так понимаю, что нужно использовать для создания формы entity класс, но в форме всего 2-3 поля, а в классе их больше, к тому-же хочется проверять сразу класс, а не поля отдельно друг от друга


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

Насчет этого: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Validator/ValidatorServiceProvider/LoginValidatorServiceProvider.php

Не очень понял, а зачем тут провайдер? Почему нельзя записать что-то в контейнер $app напрямую? Провайдеры обычно используют для каких-то библиотек, чтобы достаточно было добавить в прилоежние один провайдер и не надо было описывать инициализацию библиотеки, и каждый сервис из библиотеки прописывать в DI контейнер вручную. Но у тебя там всего один сервис и объявляется (validator.login), и он не универсальный, его нельзя использовать в другом приложении.

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

В документации написано: http://silex.sensiolabs.org/doc/2.0/providers.html

> Providers allow the developer to reuse parts of an application into another one.



Вот видишь, "reuse parts of an application".

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

Насчет вот этого: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Validator/Constraints/LoginConstraintValidator.php

Я все же думаю, что это уже не задача формы - проверять логин. Задача формы:

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

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

Должно быть примерно так:

if ($form->validate()) {
$email = $form->email;
$password = $form->password;

if (!validateEmail($email, $password)) {
$form->addViolation('неправильный логин или пароль');
}
}

Насчет этого: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Validator/Constraints/RegisterConstraint.php

Я думаю, тут должно быть 2 класса-ограничения: одно для проверки логина, другое для email. А может какое-то более уникальное ограничение для проверки уникальности любого поля. Так как по задумке Constraint - это одно ограничение, а не много.

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

if ($form->password == ...) {
$form->addViolation(..);
}

if ($model->email == ....) {
return new ValidationError(....);
}

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

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

- свой constraint
- использовать CallbackConstaint
- попробовать использовать события https://symfony.com/doc/current/form/events.html

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

Тут вообще HTML-код в контроллере вместо использования шаблона: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Controller/CommentController.php#L39

Я предлагаю для начала разобраться с формами, моделями и валидацией, а дальше посмотрим остальные проблемы в коде. Я тут написал много текста, так что уточняй, если что-то неясно.
#142 #924484
>>922684

Молодец, решено правильно.

>>922454

Справедливости ради, NaN это разновидность дробного числа в стандарте IEEE https://habrahabr.ru/post/112953/

>>922034

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

>>922390

Можно ставить, хуже не будет.

>>922276

Документация.

>>922138

> Стандартные ассерты, определенные аннотациями не работают, возможно из-за кастомного constraint validator.


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

Вот тут в документации, например, ограничения задаются статическим методом, а не аннотациями: http://symfony.com/doc/current/components/validator/metadata.html

А вот тут описывается, какие способ загрузки аннотаций есть: http://symfony.com/doc/current/components/validator/resources.html

Ты используешь AnnotationLoader?

Далее ты должен передать правильно настроенный Валидатор в FormFactoryBuilder как в примере тут: http://symfony.com/doc/current/components/form.html#validation

Я вижу, ты используешь SilexFormProvider. Выясни, как именно он настраивает компонент форм и валидатор.

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



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

Такая штука есть во всех фреймворках, в Юи например ограничения описываются массивом: https://yiiframework.com.ua/ru/doc/guide/2/input-validation/

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

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

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

Либо же разобраться с аннотациями и как-то брать описание формы из класса модели формы.

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

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

> Я так понимаю, что нужно использовать для создания формы entity класс, но в форме всего 2-3 поля, а в классе их больше, к тому-же хочется проверять сразу класс, а не поля отдельно друг от друга


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

Насчет этого: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Validator/ValidatorServiceProvider/LoginValidatorServiceProvider.php

Не очень понял, а зачем тут провайдер? Почему нельзя записать что-то в контейнер $app напрямую? Провайдеры обычно используют для каких-то библиотек, чтобы достаточно было добавить в прилоежние один провайдер и не надо было описывать инициализацию библиотеки, и каждый сервис из библиотеки прописывать в DI контейнер вручную. Но у тебя там всего один сервис и объявляется (validator.login), и он не универсальный, его нельзя использовать в другом приложении.

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

В документации написано: http://silex.sensiolabs.org/doc/2.0/providers.html

> Providers allow the developer to reuse parts of an application into another one.



Вот видишь, "reuse parts of an application".

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

Насчет вот этого: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Validator/Constraints/LoginConstraintValidator.php

Я все же думаю, что это уже не задача формы - проверять логин. Задача формы:

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

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

Должно быть примерно так:

if ($form->validate()) {
$email = $form->email;
$password = $form->password;

if (!validateEmail($email, $password)) {
$form->addViolation('неправильный логин или пароль');
}
}

Насчет этого: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Validator/Constraints/RegisterConstraint.php

Я думаю, тут должно быть 2 класса-ограничения: одно для проверки логина, другое для email. А может какое-то более уникальное ограничение для проверки уникальности любого поля. Так как по задумке Constraint - это одно ограничение, а не много.

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

if ($form->password == ...) {
$form->addViolation(..);
}

if ($model->email == ....) {
return new ValidationError(....);
}

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

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

- свой constraint
- использовать CallbackConstaint
- попробовать использовать события https://symfony.com/doc/current/form/events.html

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

Тут вообще HTML-код в контроллере вместо использования шаблона: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Controller/CommentController.php#L39

Я предлагаю для начала разобраться с формами, моделями и валидацией, а дальше посмотрим остальные проблемы в коде. Я тут написал много текста, так что уточняй, если что-то неясно.
924780927560929712
#143 #924496
>>921447

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

- хранить их в словаре вроде cells[y][x]
- хранить их в массиве в определенном порядке, чтобы их можно было найти по формуле вроде cells[y * columns + x]

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

Ну вот смотри, сколько тут опций:

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

Ты должен как-то взвесить все эти варианты и выбрать наиболее подходящий. Если совсем не уверен, что взять, выбери какой-то вариант, набросай несколько функций для работы с клеточками, и покажи, а я напишу, какие получаются недостатки.
#144 #924502
>>924429

>Теперь у тебя есть понимание, как решить проблему?


Т.е. надо на стороне винды поменять кодировку?
924523
#145 #924523
>>924502

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

Вообще, конечно, это большая проблема. Ведь в русской версии винды используется одна 8-битная кодировка, а в американской - другая. Почему разработчики PHP не хотят использовать юникодные функции или хотя бы сделать дополнительные функции для юникода (в идеале для utf-8)? PHP формально кроссплатформенный, но от решения этой проблемы он самоустранился.
924545
#146 #924525
>>924446

>А что с этим делать и как решать эту проблему, рассказывают?



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

На странице данные выводятся через htmlspecialchars, с константами (потом пишется обертка для нее).
В mysql данные передаются через псевдо-переменные PDO
#147 #924545
>>924523

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


Я нихуя не понял. И вообще, это в пхп работа с кодировками адов труд, или я слишком неофит?
924570
#148 #924570
>>924545

Вместо того, чтобы вызывать функцию вроде file_put_contents напрямую, сделай свою функцию, которая проверяет ОС и если надо, перекодировывает имя файла.
#149 #924586
>>924424
Я догадывался что это выполняется посредством http-запроса, но мне не понятно как отправить его посредством, к примеру, php. Я видел как обрабатываются http запросы, но не разу не видел чтобы они отправлялись.

Хорошо знаком только с php.
#150 #924602
мой код - http://pastebin.com/DuUKpSvz
код автора - http://pastebin.com/VJc7w0tp

страница управления авторами.
/admin/authors/
[Новый автор]
имя-фамилия [редактировать] [удалить]
Кнопка удалить работает.

Создать нового и редактировать - не работает.
При создании нового - переходит в admin/authors/?add
Открывается форма
label+input
[Добавить автора]

Ввожу данные, жму, попадаю на страницу admin/authors/addform
с ошибкой 404.

С редактированием аналогично, только переход на /editform

Код автора работает, книга Кевин Янк - PHP и MySQL. От новичка к профессионалу - 2013

7 глава.
Некоторые данные под себя делал, поэтому вариант скопировать код у автора не подходит, 3 раза прочитал, все нормально, не могу найти ошибки.
924607924708
#151 #924607
>>924602
у автора книги скрипт не перенаправляет на /addform или /editform
#152 #924676
>>924306
>>924341

Не страдайте хуйней, напишите годную САМОСТОЯТЕЛЬНУЮ библиотеку и залейте ее на гитхаб. (генератор чартов, например)
0 Кб, 512x512
#153 #924708
>>924602
Нашел баг.

Моих эмоцией не описать словами
1892 Кб, 500x281
#154 #924780
>>924484

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


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

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


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

>>То есть как я понял, провайдер используется как этакий "мост" для простого подключения сторонней библиотеки в Silex.


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

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


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

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


Что значит использовать сервисы? У тебя есть уроки использования или примеры таких сервисов?
1892 Кб, 500x281
#154 #924780
>>924484

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


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

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


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

>>То есть как я понял, провайдер используется как этакий "мост" для простого подключения сторонней библиотеки в Silex.


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

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


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

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


Что значит использовать сервисы? У тебя есть уроки использования или примеры таких сервисов?
#155 #924834
>>919074 (OP)
Привет аноны.
Решил учить PHP, пока для себя, потом как получится. Несмотря на ококолоайтишную вышку, последний раз пытался погромировать в школе, на делфи.
Ну да ладно, делаю сейчас по вот этой ссылке - http://archive-ipq-co.narod.ru/, и такое чувство возникает странное, я вроде не совсем идиот, но в этих задачках больше сижу и думаю как как это реализовать в коде, а как хотя бы понять что вообще требуется и как бы я делал это допустим вручную. (например считал каждый месяц на калькуляторе в задачке про школьника). Я совсем конченый или еще нет? Что это? Проблема с воображением или что? С этим можно жить?
вот и задачка, мож кто посмотрит
http://ideone.com/TKF4VQ


Наверняка и тут хуйни понаписал, всмысле в посте.
924838925028939968
#156 #924838
>>924834
Ну я же говорил.

Пофиксил

> думаю не как это реализовать в коде

#157 #924874
https://www.work.ua/jobs/2404619/
В копилку про забавные вакансии.
#158 #925011
за день пролистал весь сайт ОПа на народе, вроде все более-менее разжевали и в рот положили, хотя некоторые задачки можно укоротить, если не читать начало решения.
Постарался еще сделать красивый вариант калькулятора. :З
http://ideone.com/q71hdO
интересная штука, оказалось, планирую прикрутить еще скобочки туда, а потом последовательность действий человеческую
925607939968
#159 #925028
#160 #925109
Объясните:

Я зеленый нуб, пошел качать php для Windows для обучения и увидел вот такое:

Thread Safe и Non Thread Safe.
Начал искать информацию о разницы, на русском ничего не нашел. На англ не понял, ибо база знань информатики желает быть лучше.

Прошу совета.
925131
#161 #925115
И да, учиться по этому http://www.denwer.ru
Смысла нет?
925125925136
#162 #925120
Может кто знает нормальный проект(репозиторий) на ларавел для ознакомления с фреймворком, чтобы поковырять и приступить к реальной работе на бирже? Буду благодарен
925136
#163 #925125
>>925115
1. Там старый софт.
2. Помогать тебе если что то не будет там работать не будут. Т.к. Что там авторы намутили всем лень разбираться.

Если ты почитаешь ссыли из шапки, то там есть гайд от ОПа по установке PHP и прочее в Windows. Вообще, там есть все что нужно человеку для начала изучения. + Мы всегда поможем. Только учти, что тред медленный.
925132
#164 #925131
>>925109

Для использования вместе с Апачом под виндой нужен ThreadSafe. Для использования без Апача или под линуксом можно и Non-Thread-Safe. Это поддержка многопоточности.
#165 #925132
>>925125
Да, я видел шапку и внимательно ее прочитал, но все равно туго доходило. В общем, я пока прохожу:
1. на этом сайте php https://www.codecademy.com/ - немного сложновато в понимании информации и поэтому сижу со словарем. Но, главный минус - это примитивные задания.
2. ну и скачал книжку PHPTheRightWay.
3. сервер скачал отсюда http://www.wampserver.com (вроде уже не старые технологии), или это плохая идея и мне таки лучше всего уже самому учиться ставить апачи, пхп, mysql?

чем-то манить работать в направлении back end.
939968
#166 #925136
>>925120
https://github.com/laravel/laravel/graphs/contributors

>>925115
Йобаный буллшит. Просто поставь себе Linux и caddyserver.
#167 #925165
есть ли хороший и приятный гайд, где тебе разжевывают создание вебсервиса на похапе с нуля?
типа рейлс фор зомбиз. Там тебе и про руби, и про рейлс, и про архитектуру, а пока рассказывают, ты делаешь свой твиттер.
Большую часть книг и сайтов что я нашел можно выкинуть, т.к они втирают про сам язык и программирование, а я хочу про его применение в вебе - написать сайт с формами етц, опыт набивать короче.
Заранее спасибо большое. :3
925338
#168 #925172
Кто-то из анонов может запостить свои проекты\проект?
Мне чисто из интереса.

\тот самый нуб-анон, который спрашивал про Thread Safe и Non Thread Safe, и про denwer\
#169 #925277
У меня одного на идеоне когда пишу строки русского текста каретка сдвигается в ебеня?
939968
#170 #925338
>>925165
Веб-сервис это что у тебя? Сделай задачку про студентов, а там уже можешь аналог твиттора пробовать пилить.
925605
#171 #925387
Извините, что беспокою.
Помогите, пожалуйста, понять этот эльфийский:
preg_match('/^['.$Line['text'][0].']{3,}[ ]([\w-]+)?[ ]$/', $Line['text'], $matches)

Я вот почитал статью: http://archive-ipq-co.narod.ru/l1/regexp.html и расшифровал фразу как-то так:
Ищется точное совпадение шаблона в строке $Line['text'] (символы ^ в начале и $ в конце строки). В начале ищется повторение три и больше раз строки, которая находится в $Line['text'][0]. Потом идет много пробелов. Потом идет строка из одного или нескольких буквенных символов, которые могут встретиться или не встретиться. Потом идет один или несколько пробелов
925573939968
2 Кб, 620x20
#172 #925388
Абу съел звездочки. Спасибо, Абу.
#173 #925461
Сапер MVC. Оп, я правильно работаю со словарями? http://ideone.com/petHF7 Решил отказаться от объектов Cell. Теперь везде появился вложенный цикл, там где раньше был простой перебор массива с объектами, что меня смущает.
#174 #925484
>>925461

И еще, стоит ли писать вот такую обертку вокруг метода реализации чтобы не кидать каждый раз свойства объекта ему в аргументы http://ideone.com/Bom4oP ?
925772930814931338
#175 #925554
Объясните мне на живом примере, где круто использовать switch-case. Spasibo.
925573925607
#176 #925573
>>925461
JS в пхптреде(9((9((9
Вложенный цикл - это норма.

>>925554
Там, где у тебя много if'ов получается.
Раньше в DLE так роутинг работал:
switch ($route) { case "/home": ....

>>925387
Я не понимаю, тебе за это платят? Попробуй доверить это дело regex101.com
#177 #925605
>>925338

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

>>925572

> Ну а применить знания из "рейлс фор зомбиз" в PHP нельзя? Там наверное рассказывают про HTTP, ну и в рельсах есть MVC, ActiveRecord, ServiceObjects. Всё это используется в PHP, просто открываешь доку по заинтересовавшему тебя фреймворку и пишешь приложение.



проблема в том, что я их не проходил, просто знаю, что там вот так, а не иначе. В серверном программировании я ноль полный.
#178 #925607
>>925554
я вот тут прикрутил, например. >>925011
Свитч повышает читаемость кода, а так можешь и ифы пихать.
925646
#179 #925646
>>925607
Я что-то даже не понял, что твой код делает, а значить и не понял, почему там прикрутили switch-case. Можешь объяснить?

/я только, как 2 изучаю php/
925964
#180 #925772
>>925484

Оп, а вот в этой строке здесь https://github.com/codedokode/pasta/blob/master/js/minesweeper-mvc.md :

> Тут есть 2 варианта, как это хранить: в виде 2-мерного массива, например this.openCells[y][x] = true помечает клеточку открытой ...



...ты имел ввиду действительно двумерный массив ([ [true, false], [false, false], [false, true], [true, false]) или словарь ( {1: {1: true, 2:false}, 2: {1: false, 2: false}, 3: {1:false, 2: true})? Мне кажется, ты имел ввиду первое, а я делаю через второе и в некоторых местах трудности (например мучаюсь как создать мины при такой структуре чтобы не было вечного рандома. Когда у меня был массив объектов Cell я просто делал на него shuffle и превращал в мины n-ое количество равное числу мин).
926675930814931338
#181 #925964
>>925646

не хочу смущать тут всех своим вариантом, потому что я либо подскажу новичкам развернутое и полное решение, либо задурю им мозги. Напиши мне в телеграмм? Да и учить вместе веселее будет.@Kyooni
#182 #926076
Блин ребят , может кто ссылку кинуть на урок или гайд ?
Я просто вообще не вдупляю как пэхапэ в общем связывается в коде с html и как его туда вставлять
939968
#183 #926077
Интересный пост для тех, кто изучает JS, о тонкостях и возможностях языка: https://m.habrahabr.ru/post/321078/

А вот еще интересный список, на который я наткнулся в сети: http://reestr.rublacklist.net/distributors/
926153
#184 #926132
>>919074 (OP)
Посоветуйте пожалуйста книжку почитать, желательно современную, но на русише.
В программировании не новичок, с php уже дело имел, сейчас нужно все это вспомнить.
927488
someApprentice #185 #926153
>>926077
Картинка в посте очень правдоподобная :>
someApprentice #186 #926219
>>916131

>Тут (англ) есть сложные пояснения: http://dev.mysql.com/doc/refman/5.7/en/charset-unicode-sets.html


>Тут немного на русском: http://gahcep.github.io/blog/2013/01/05/mysql-utf8/


А какие проблемы могут решить эти пояснения?

>https://github.com/someApprentice/Students/blob/master/app/init.php#L10


>> use App\Model\Helper\LoginHelper;


>> use App\Model\Helper\LoginHelper as Authorizer;


>Тут зачем-то класс 2 раза импортирован


Хотел задать пространство имен для ЛогинХелпера. Ведь это же и Авторайзер в то же время.

>https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php


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


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

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


Не совсем понимаю как это сделать - согласен, и там и там есть общий код, но он минимален, и ведет себя как свойственно контроллеру:
1. получаем запросы\конфигурацию.
2. создаем паджер, обращаемся к БД.
3. выводим шаблон

Общие в этом только получение конфигураций и создание паджера. Конечно, я мог бы объеденить ещё объеденить метод обращения к БД, отправляя пустой запрос в метод поиска чтобы получить все записи, но помимого этого для шаблона нужен и паджер и записи, к тому же ему могут понадобиться и запросы. Получается замкнутый круг.
Или стоит как-то исхитриться? Ради чего?

>https://github.com/someApprentice/Students/blob/master/app/Controller/SearchAction.php#L19


>> if ($_GET) {


>Я бы не советовал так проверять, так как в теории в GET могут быть какие-то неотносящиеся к поиску параметры (их могут добавить позже). Лучше проверять, например, что $_GET['query'] не пуст.


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

https://github.com/someApprentice/Students/commit/25476b949c720cc75eb8b3c8f03edb0b827ae196#diff-f2d1af9c4ccbbb1fb81e9cd1a194f5e3L19

>> $this->render('templates/search.phtml', compact('query', 'pager'));


>> } else {


>> $this->render('templates/search.phtml');


>Вот это тоже странно. Один и тот же шаблон может вызываться как с переменными, так и без. Как писать надежный код, если ты даже не знаешь, передана такая переменная или нет? Да и неудобно, перед любым использованием переменной надо писать if (isset()). Не стоит так делать, тут стоит оставить единственный вызов render, в который передаются все нужные переменные.


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

>Теперь посмотрим на использование класса Pager. Это класс, в котором много неудачных решений:


>


>Во-вторых, почему-то для передачи аргументов в конструктор используется массив. Причем вместе идут как параметры, которые не зависят от номера страницы (query, sort), так и номер текущей страницы. Тоже нелогично, мне кажется, что номер страницы должен идти отдельно.


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


Это не просто массив а массив запросов - $queries. По моему, по названии перемной должно быть понятно что это запросы. Я использовал такой подход в попытке сразу передать этот массив в метод http_build_query($queries) на практике ничего не получилось и, к тому же, не всегда известно какие запросы понадобиться передать ещё для формирования ссылок.
someApprentice #186 #926219
>>916131

>Тут (англ) есть сложные пояснения: http://dev.mysql.com/doc/refman/5.7/en/charset-unicode-sets.html


>Тут немного на русском: http://gahcep.github.io/blog/2013/01/05/mysql-utf8/


А какие проблемы могут решить эти пояснения?

>https://github.com/someApprentice/Students/blob/master/app/init.php#L10


>> use App\Model\Helper\LoginHelper;


>> use App\Model\Helper\LoginHelper as Authorizer;


>Тут зачем-то класс 2 раза импортирован


Хотел задать пространство имен для ЛогинХелпера. Ведь это же и Авторайзер в то же время.

>https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php


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


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

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


Не совсем понимаю как это сделать - согласен, и там и там есть общий код, но он минимален, и ведет себя как свойственно контроллеру:
1. получаем запросы\конфигурацию.
2. создаем паджер, обращаемся к БД.
3. выводим шаблон

Общие в этом только получение конфигураций и создание паджера. Конечно, я мог бы объеденить ещё объеденить метод обращения к БД, отправляя пустой запрос в метод поиска чтобы получить все записи, но помимого этого для шаблона нужен и паджер и записи, к тому же ему могут понадобиться и запросы. Получается замкнутый круг.
Или стоит как-то исхитриться? Ради чего?

>https://github.com/someApprentice/Students/blob/master/app/Controller/SearchAction.php#L19


>> if ($_GET) {


>Я бы не советовал так проверять, так как в теории в GET могут быть какие-то неотносящиеся к поиску параметры (их могут добавить позже). Лучше проверять, например, что $_GET['query'] не пуст.


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

https://github.com/someApprentice/Students/commit/25476b949c720cc75eb8b3c8f03edb0b827ae196#diff-f2d1af9c4ccbbb1fb81e9cd1a194f5e3L19

>> $this->render('templates/search.phtml', compact('query', 'pager'));


>> } else {


>> $this->render('templates/search.phtml');


>Вот это тоже странно. Один и тот же шаблон может вызываться как с переменными, так и без. Как писать надежный код, если ты даже не знаешь, передана такая переменная или нет? Да и неудобно, перед любым использованием переменной надо писать if (isset()). Не стоит так делать, тут стоит оставить единственный вызов render, в который передаются все нужные переменные.


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

>Теперь посмотрим на использование класса Pager. Это класс, в котором много неудачных решений:


>


>Во-вторых, почему-то для передачи аргументов в конструктор используется массив. Причем вместе идут как параметры, которые не зависят от номера страницы (query, sort), так и номер текущей страницы. Тоже нелогично, мне кажется, что номер страницы должен идти отдельно.


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


Это не просто массив а массив запросов - $queries. По моему, по названии перемной должно быть понятно что это запросы. Я использовал такой подход в попытке сразу передать этот массив в метод http_build_query($queries) на практике ничего не получилось и, к тому же, не всегда известно какие запросы понадобиться передать ещё для формирования ссылок.
someApprentice #187 #926220
>>916132

>https://github.com/someApprentice/Students/blob/master/templates/index.phtml#L10


>> <a href="logout.php?token=<?= $token ?>&go=/public/index.php">logout?</a>


>LogOut лучше бы делать отправкой POST-запроса (например, пустой формы с одной кнопкой). Это ведь изменяет состояние залогиненности, а GET запросы обычно не меняют состояние сервера.


А я спрашивал почему в популярных соц.сетях разлогинивание сделано через форму.

Нужно делать сущность LogoutForm со всеми вытекающими для этого?

Есть какой-нибудь css хинт чтобы форма с кнопкой выглядела как ссылка или как любой другой элемент?

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


А можно по подробней на этот моменте? Чем POST-запросы лучше GET-запросов? Ведь по сути они оба просто массивы.
И как разлогинивание меняет сосотяние сервера? Мы же не используем локальные кукисы и не добавляем ничего нового например в БД.

>Могу предложить посмотреть вот такую реализацию класса авторизации: https://github.com/kubk/students/blob/master/src/AuthService.php


https://github.com/kubk/students/blob/11bc17f3b87e48f04cebc2715dd415af89d2332b/src/AuthService.php
Там на Симфони написано - сложно определить в чём кардинальное различие. Подозреваю что там то же устройство, только другая технология. Можно подсказку на что мне нужно обратить внимание?

>use Symfony\Component\HttpFoundation\{ParameterBag, Cookie, ResponseHeaderBag};


Что означает тут синтаксис в литералах? Это перечисление разных классов в одной и той же директории?

>public function registerStudent(Student $student): Student


И тут, что означает : Student в объявлении функции?

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

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


У меня тоже можно написать такой тест, у меня есть функция которая возвращает пользователя по кукисам: https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L16

>Далее, тут https://github.com/someApprentice/Students/blob/master/app/Controller/RegisterAction.php#L58 мы не завершаем контроллер после редиректа.


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

>https://github.com/someApprentice/Students/blob/master/app/Model/Validators/StudentValidations.php


>Константы вроде const GENDER_MALE = "Man"; логичнее поместить в студента. Это ведь его свойства, а не свойства валидатора. В валидатор можно поместить константы вроде VALIDATE_MIN_LENGTH, относящиеся к валидации. Представь, что нам не нужна валидация и мы удалим этот класс. И вместе с ним удалятся константы, обозначающие пол, хотя они-то нам еще нужны.


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

>https://github.com/someApprentice/Students/blob/master/app/Model/Validators/RegisterStudentFormValidations.php


>А интересно, почему здесь StudentValidations передается как зависимость, а не наследуется? По идее ведь RegisterFormValiadtions мог бы расширять StudentValidations, или это неудобно?


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

>И тут получается похожий код:


>


>- https://github.com/someApprentice/Students/blob/master/app/Model/Validators/RegisterStudentFormValidations.php#L32


>- https://github.com/someApprentice/Students/blob/master/app/Model/Validators/StudentValidations.php#L58


>


>Может стоит сделать метод validateByRules($entity, $rules, $errorList) в базовом классе?


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

>Хотя, конечно, не очень понятно, как тогда там вставить код, меняющий правила проверки пароля:


Мне вообще кажется, что смена пароля должна осуществляться отдельно.

https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L11
Это ошибка отправлять пустую строку если нет запроса? А если бы это было отдельный случай к примеру получение запроса поиска?

https://github.com/someApprentice/Students/

>Ну и дальше стоит начинать изучать фреймворки, хотя бы микрофреймворки для начала, так как тут мы писали все с нуля, и на практике конечно эффективнее учиться использовать готовый код. Также потом стоит глянуть шаблонизатор twig и, может быть, библиотеку-data mapper для работы с БД под названием Doctrine.


Не терпиться уже начать!

>Doctrine


Даже после прочтения сложных определений в гугле не до конца понимают что это такое. Оно заменяет Mysql или любую другу БД?

....

Это нормально отвлекаться на постороние вещи во время изучения? Хоть я и настроен на продуктивную работу, всё равно, сложно сконцентрироваться на каком-то сложном вопросе. Я подумал, что мозг может работать в пассивном режиме, например, как ты когда что-то пытаешься вспомнить, и это потом сомо, через какое-то время, вспыхивает у тебя в голове. Ведь, в конце концов я самостоятельно решаю этот вопрос.
С этим всё нормально? Я хорошо справляюсь?
someApprentice #187 #926220
>>916132

>https://github.com/someApprentice/Students/blob/master/templates/index.phtml#L10


>> <a href="logout.php?token=<?= $token ?>&go=/public/index.php">logout?</a>


>LogOut лучше бы делать отправкой POST-запроса (например, пустой формы с одной кнопкой). Это ведь изменяет состояние залогиненности, а GET запросы обычно не меняют состояние сервера.


А я спрашивал почему в популярных соц.сетях разлогинивание сделано через форму.

Нужно делать сущность LogoutForm со всеми вытекающими для этого?

Есть какой-нибудь css хинт чтобы форма с кнопкой выглядела как ссылка или как любой другой элемент?

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


А можно по подробней на этот моменте? Чем POST-запросы лучше GET-запросов? Ведь по сути они оба просто массивы.
И как разлогинивание меняет сосотяние сервера? Мы же не используем локальные кукисы и не добавляем ничего нового например в БД.

>Могу предложить посмотреть вот такую реализацию класса авторизации: https://github.com/kubk/students/blob/master/src/AuthService.php


https://github.com/kubk/students/blob/11bc17f3b87e48f04cebc2715dd415af89d2332b/src/AuthService.php
Там на Симфони написано - сложно определить в чём кардинальное различие. Подозреваю что там то же устройство, только другая технология. Можно подсказку на что мне нужно обратить внимание?

>use Symfony\Component\HttpFoundation\{ParameterBag, Cookie, ResponseHeaderBag};


Что означает тут синтаксис в литералах? Это перечисление разных классов в одной и той же директории?

>public function registerStudent(Student $student): Student


И тут, что означает : Student в объявлении функции?

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

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


У меня тоже можно написать такой тест, у меня есть функция которая возвращает пользователя по кукисам: https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L16

>Далее, тут https://github.com/someApprentice/Students/blob/master/app/Controller/RegisterAction.php#L58 мы не завершаем контроллер после редиректа.


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

>https://github.com/someApprentice/Students/blob/master/app/Model/Validators/StudentValidations.php


>Константы вроде const GENDER_MALE = "Man"; логичнее поместить в студента. Это ведь его свойства, а не свойства валидатора. В валидатор можно поместить константы вроде VALIDATE_MIN_LENGTH, относящиеся к валидации. Представь, что нам не нужна валидация и мы удалим этот класс. И вместе с ним удалятся константы, обозначающие пол, хотя они-то нам еще нужны.


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

>https://github.com/someApprentice/Students/blob/master/app/Model/Validators/RegisterStudentFormValidations.php


>А интересно, почему здесь StudentValidations передается как зависимость, а не наследуется? По идее ведь RegisterFormValiadtions мог бы расширять StudentValidations, или это неудобно?


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

>И тут получается похожий код:


>


>- https://github.com/someApprentice/Students/blob/master/app/Model/Validators/RegisterStudentFormValidations.php#L32


>- https://github.com/someApprentice/Students/blob/master/app/Model/Validators/StudentValidations.php#L58


>


>Может стоит сделать метод validateByRules($entity, $rules, $errorList) в базовом классе?


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

>Хотя, конечно, не очень понятно, как тогда там вставить код, меняющий правила проверки пароля:


Мне вообще кажется, что смена пароля должна осуществляться отдельно.

https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L11
Это ошибка отправлять пустую строку если нет запроса? А если бы это было отдельный случай к примеру получение запроса поиска?

https://github.com/someApprentice/Students/

>Ну и дальше стоит начинать изучать фреймворки, хотя бы микрофреймворки для начала, так как тут мы писали все с нуля, и на практике конечно эффективнее учиться использовать готовый код. Также потом стоит глянуть шаблонизатор twig и, может быть, библиотеку-data mapper для работы с БД под названием Doctrine.


Не терпиться уже начать!

>Doctrine


Даже после прочтения сложных определений в гугле не до конца понимают что это такое. Оно заменяет Mysql или любую другу БД?

....

Это нормально отвлекаться на постороние вещи во время изучения? Хоть я и настроен на продуктивную работу, всё равно, сложно сконцентрироваться на каком-то сложном вопросе. Я подумал, что мозг может работать в пассивном режиме, например, как ты когда что-то пытаешься вспомнить, и это потом сомо, через какое-то время, вспыхивает у тебя в голове. Ведь, в конце концов я самостоятельно решаю этот вопрос.
С этим всё нормально? Я хорошо справляюсь?
930216
75 Кб, 892x502
#188 #926233
>>919074 (OP)
К чему эти коты в шапке, весь все знают, кто является настоящим маскотом языка PHP.
926254
259 Кб, 448x457
#189 #926254
#190 #926256
Аноны, помогите правильно вкатится в PHP и стать junior.
21 с лишним хромолет. Есть высокий интерес к этому, но даже школьного курса информатики не помню, могу только шиндовс переустановить и по интернету полазить. С чего начать и через какой срок уже можно начать парится макакой. Мамка гонит, тем не менее время есть и желание тоже. Сильно не обоссывайте. В шапке хорошая инфа, но мне хочется, чтобы аноны поделились со своим опытом, с чего начинать
926260926267927305
18 Кб, 583x328
#191 #926260
>>926256

>хромолет

299 Кб, 927x1371
#192 #926267
#193 #926346
Сделал тут пару задачек на ООП. Посмотрите, плз, как оно ?
http://ideone.com/qRGcXB - Компания Вектор.

http://ideone.com/WeGENR - Вопросы с абстрактными классами.
931364
#194 #926381
Посмотрите, пожалуйста, как сделал задания. Заранее благодарю)

http://ideone.com/9wsu8g - Игра в кубики;
http://ideone.com/sRvu3e - мини "калькулятор";
http://ideone.com/8x1TeV - Игра в кубики с Пекой;
http://ideone.com/pJ4TO8 - Пхп без смс;
http://ideone.com/8GN4S3 - депозит;
http://ideone.com/O7tPEA - Айфон в кредит;
http://ideone.com/7SJzev - Задание со стихами;
http://ideone.com/MGrQkg - Регулярка на номера телефонов
926446926464
#195 #926446
>>926381
Ебать, спасибо тебе за эти задания с циклом, ибо я чёт никак не мог вдуплить как оно работает, а теперь дошло.
#196 #926464
>>926381
В депозитах поменяй переменную возраста с 1 на 16
926491
#197 #926491
>>926464
Я даун и не так понял задания, лол.
139 Кб, 1599x899
#198 #926597
пытаюсь начать программировать на похапе так, как это задумывалось, а не только решать задачки.
Научился выводить скрипт на страницу и отправлять запросы в бд(MySQL) + немного работы через PhpMyAdmin.
Стоит ли мне сразу вскочить на фреймворк и набегать на создание сайтов, обмазываясь гайдами, т.е поступать в стиле руби он рейлс или надо сначала осознать как это все делать на чистом пхп, итд?
посмотрел тут решение задачки про студентов, охуел от количества файлов. Без фреймворков можно с ума сойти же.
#199 #926603
>>926597
Когда перейдешь к фреймворкам после задач, то понимаешь, что все твои решения задач это корявые велосипеды и в реальной разработке не нужны. Но они учат понимать язык и его возможности.
926651
#200 #926604

>>92659>>926597


нужно знать как работает инструмент, чтобы им пользоваться.
сначала сделай сам, потом можешь юзать фреймворки
926613926651
someApprentice #201 #926609
>>926534
Весьма исчерпывающие ответы - спасибо!

>PHP 7


У меня уже давно phpfmt выдает ошибку на старую версию - из-за чего везде на гитхабе у меня съежает оформление кода, потому что раньше для отступов я использовал символ табуляции (т.к. это стояло по умолчанию в настройках sublimetext): https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php
#202 #926613
>>926604
Ради фана или развития может быть, а по факту обычному разработчику этого знать не надо.
Тебе совершенно не надо знать как работает мешалка массива, когда тебе его тупо надо перемешать.
Или тебе должно быть похер как отправляются данные в БД, твоя задача лишь знать куда и что отправляешь, а как уже оно там будет работать тебе должно быть чхать, если оно правильно работает.
926644
56 Кб, 400x400
#203 #926644
>>926613
Кек, представил, если бы врачи работали по таким принципам:

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

Хотел порофлить но так походу в 95% случаях и происходит, лол

(No offence)
926651
#204 #926651
>>926604

но ведь создавая с десяток MVC компонентов самостоятельно я убью неделю на то, что требует часа с фреймворком. Плюс, я могу просто посмотреть что создает именяет то или иное мое действие, и точно так же разобраться.
Ну и я не имею ввиду, что я просто научился писать if else и сразу ВБОЙ ЕБАНА. Я почитаю самые основы этой ебони, а дальше фреймворки.

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

>>926644

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

В общем, вы меня вдохновили на почитать основы, как минимум.
Подскажите еще, пожалуйста, какой фреймворк актуален в сфере зарабатывания денег при выполнении работы рабодниками на работе?
я так понимаю, что йии2 и симфони2 сейчас топовые, но который из них?
926760
#205 #926652
>>926597
а что сложного в том, чтобы сделать на чистом пхп? никто же не заставляет нуба сразу все это на МВЦ ООП хуярить (хотя было бы неплохо)
926669
#206 #926669
>>926652

то, что на MVC это логически проще, что ли. Ну или это потому что я уже почитал про мвц, а про то, как это сделать на чистом пхп я не могу сообразить, потому что в сети мало толковой информации про такое.
Ну и потому что это будет некрасивым, медленным велосипедом. Так то, я могу тебе и на реакте сейчас написать сайт со всем этим и уместить в одном index.js, но это будте жутко уродливо.
926684926730929243
#207 #926674
>>924460

>Разница есть


Тогда почему обычный метод можно вызвать статический через ::, а статический обычным -> ?
929243
#208 #926675
>>925772

Вопросы все еще по MVC саперу. А вот в какой-то момент я буду тестировать несколько domView, а там на html странице будут повторяющиеся id. От id в шаблонах наверное вообще отказаться тогда и заменить на классы?
929243
#209 #926684
>>926669

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


1) У тебя не должно быть глобальных переменных;
2) Только функции, принимающие данные на вход и бросающие в ответ изменённые данные;
3) Функции эти надо собрать в пространства имён, в виде дерева, а данные — в классы;
4) На вход им передавать другие функции, создавая таким образом композицiю их;
5) Логи и сообщения не должны оставаться всю ночь до утра;
6) Интерфейсы программ твоих приноси в дом господа, бога твоего;
7) Не еби TCP-сокет в контексте окружения его.
#210 #926725
>>919074 (OP)
Аноны, почему не пашет у меня
https://github.com/codedokode/pasta/blob/master/soft/web-server.md

>Чтобы веб-сервер использовал скрипт маршрутизации, его надо запускать такой командой:



>php -S localost:9001 router.php



Запускаю не из цмд, а с опенсервера. Создал отдельные файлы, всё как надо, в результате нихуя!
926747929243
#211 #926730
>>926669
хоспаде, туториал погугли (мвц на пхп), просто берешь и повторяешь. вообще умение хуярить мвц на чистом пхп - оно и не нужно по сути. Возьми фреймворк. А можешь даже попробовать взять цмску и поправить ее мвц код под свои нужды, у тебя сразу будет рабочий вариант с красивой админкой - такие задачи чаще всего и встречаются в рабоче пхпшника. Но перед этим лучше ООП поучить, про паттерны занстра, pdo почитать, а то с ходу в коде цмски не разберешься.
926751
#212 #926747
>>926725

создай index.php, в нем скинь

$router = new Router();
$router->run();

в файле router.php опиши класс Роутер и его функционал через публичную функцию run(), и не надо пердолить сервер командами
926748926755
#213 #926748
>>926747

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

define('ROOT', dirname(__FILE__));
require_once(ROOT.'/components/router.php');
926769
#214 #926751
>>926730
Что за хуйню ты ему втираешь?
Что значит "чистое пхп"? Как правило имеется ввиду отсутствие фремфорка.
ООП вообще часть языка блять.
А вот мвц это всего лишь патер, пусть пользует, хорошо и полезно.
926753
#215 #926753
>>926751

>Как правило имеется ввиду отсутствие фремфорка


Как правило имеется в виду, что PHP сам себе сервер - без всяких Апачей.
45 Кб, 508x602
#216 #926755
>>926747
Благодарю, анон, сейчас попробую
#217 #926760
>>926651
В фреймворках бывают недостатки и неудачные решения.
Например, в команде Yii есть какой то любитель пользовать указатели, что в пхп имхо не нужно вообще, и из за этого была большая ошибка в их RBAC модуле.

Возможности фремворка это расширение возможностей ПХП и не зная толком ПХП можно просто не понять или упустить многие возможности фреймворка.

>велосипед для нестандартного случая


Не для всех общих случае есть готовые хорошие решения, что говорить про нестандартные.
Вот хорошая статья на тему http://www.habrahabr.net/thread/1716

>мрт - тот же фреймворк


Плохой пример.
Мрт и врач это, как программист и монитор.

>Подскажите еще, пожалуйста, какой фреймворк актуален в сфере


Yii проще и популярнее в СНГ, Symfony сложнее, но вроде как более грамотно сделан.
Там еще кажется Symfony3 вышел, но я его не смотрел.
929243
#218 #926769
>>926748

>в файле router.php опиши класс Роутер и его функционал через публичную функцию run()


Окей, а как это сделать?
50 Кб, 866x473
#219 #926829
Аноны, как сделать так, чтобы после обновления страницы сбрасывались значения передаваемые через гет? А то вот так вот выходит всё.
И почему echo $_SERVER['HTTP_USER_AGENT'];
Показывает почему-то не мой браузер, а несколько штук?
926842929243
#220 #926842
>>926829

>страницы сбрасывались значения передаваемые через гет



На PHP никак, кажется

>несколько штук


У тебя хром
http://webaim.org/blog/user-agent-string-history/
926844926847
#221 #926844
>>926842

>На PHP никак, кажется


Да, ошибся.
Так можно: http://php.net/manual/ru/function.header.php
926851
#222 #926847
>>926842

> and the user agent string was a complete mess, and near useless, and everyone pretended to be everyone else, and confusion abounded.


Именно так и вижу этот список.
Мельком прочитал эту новеллу, но все-таки как быстро узнавать какой браузер?
929243
40 Кб, 604x604
#223 #926851
>>926844
Благодарю, анон-с
17 Кб, 774x550
#224 #926910
Подскажите криворукому, что не так ?
926912
#225 #926912
>>926910
$y вычисляется один раз, перед входом в цикл
926916
#226 #926913
Так как js тред умер напишу тут. Есть у меня в общем фронтэнд сторона, где есть форма и в ней генерятся разные поля, и это все потом отправляется php скрипту для обработки. Есть там поле с загрузкой нескольких изображений, надо что бы после загрузки юзер мог видеть то, что загрузил и менять порядок картинок, есть ли какая либа готовая под это дело? И в каком формате отправлять лучше на серв, если у меня там и картинки и текстовые поля в одной форме?
929243
#227 #926916
>>926912
понял, спасибо
#228 #926986
анончики, нужна помощь в php по интернет магазину на yii, если есть такие молодцы, то вброшу вводные
#229 #927086
Сап, пыхыпышники. Что нужно знать в JS для PHP разраба?
929243
#231 #927089
Поигрался я с ideone, установил phpstorm, в общем когда он открывает браузер там error502, как в таком случае поступают настоящие гуру пхп? Нужно установить веб сервер? А какой? Денвер?
927093
#232 #927093
>>927089
Да. Денвер прост для установки, полно гайдов:
http://www.denwer.ru
http://www.denwer.ru/base.html

А вообще заимей хост, так проще.
927098
#233 #927098
>>927093
Чому проще? Можно его заиметь бесплатно без регистрации и смс?
927102927205
#234 #927102
>>927098
Бесплатно - вряд-ли.
Обычно 100 р. за месяц.

А так - Денвер проще,
927107
#235 #927107
>>927102
Жаль что я еще и туповат. Был у меня давно хостинг+домен, хотел туда сайтик залить на джумле но так и неосилил.
#236 #927145
Кто-то смотрел курсы от php-start.com? , как они вам?
40 Кб, 630x291
27 Кб, 617x171
#237 #927169
Это нормально что он по 3 раза подряд одно и то же "случайно" выбирает? Или мой косяк?
927206927243
#238 #927190
<form action="main.php" method="GET">
Видел в какой-то книжке как делался запрос сам на себя здесь, стоит ли делать как там или и так пойдет?
927195
#239 #927195
>>927190
Как хочешь, так и делай.
927199
#240 #927199
>>927195
Ну как я написал очевидно меньше писать придется, там же писалось что-то типа $_SERVER[EBALA_TYDA_SUDA];
#241 #927204
>>927087

Как кота зовут? На бухгалтера учишься?
927263
#242 #927205
>>927098
опенсервер поставь. Там все включено(и пхп, и сикьюэль, и аллах) и он гипер-простой и бесплатный.
#243 #927206
>>927169

> Это нормально что он по 3 раза подряд одно и то же "случайно" выбирает? Или мой косяк?


разве array rand не возвращает случайное значение?
Попробуй выводить $рандом, а не массив[рандом]
55 Кб, 804x743
#244 #927219
https://github.com/codedokode/pasta/blob/master/soft/web-server.md
Как последнюю задачу с куки делать то блять?
Не было ничего нихрена о ней сказано
927304
17 Кб, 219x255
#245 #927223
public function __construct($first_name, $last_name) {
$this->first_name = $first_name;
$this->last_name = $last_name;
}
Аноны, почему они не пишут сразу $this->$first_name?
Зачем писать first_name? какого значение этой хуйни? Она ведь нигде не употребляется больше, это не переменная, ничто
#246 #927224
>>927223
И далее
public function say_name() {
echo "My name is " . $this->first_name . " " . $this->last_name . ".\n";
}
Почему нельзя написать вместо $this->first_name просто $first_name?
927233927253931357
26 Кб, 290x389
#247 #927233
>>927223
>>927224
Люди ведь подумать могут что ты наркоман.
927240
#248 #927240
>>927233
Я нихуя не понимаю зачем всё усложнено
927251931359
#250 #927251
>>927240
Усложнено настолько, что это просто охерено упрощает остальные 100500 ситуаций.
Давай представим, что у тебя класс 40 свойств. И наизусть ты их не помнишь. Предположим, что ты добавляешь в класс новый метод, в котором ты создаешь новые переменные и работаешь с ними. Создал метод, все вроде работает, нормально вызывается, но иногда почему этот класс начинает работать непонятно как и в нем совершенно другие значения свойств, а не те, которые ты ожидаешь. Лезешь в код и видишь, что переменная $item, которую ты создал в методе оказывается перезаписала свойство $item у этого же класса, а ты не знал, что в классе такое свойство есть. И таким образом, взглянув на код ты не можешь сразу визуально определить в каком случае работа происходит с локальной переменной метода, а когда затрагивается свойство класса.
1087 Кб, Webm
#251 #927253
>>927223
>>927224
ДА ТЫ ЖЕ УПОРОТЫЙ!
1268 Кб, 2929x1995
#252 #927263
>>927204
Кота зовут Лис.
Бухгалтер не я - моя тян.
А я - обычный вебмакак с котом, который не любит похапе и любит JS
927289927324
93 Кб, 558x800
#253 #927268
>>927087
Учи php!
Учи лучше!!!11
28 Кб, 320x318
#254 #927289
>>927263

>любит JS

#255 #927302
>>927223

Ты понимаешь, что обозначает $this->first_name? Это не то же самое, что переменная $first_name, это другая вещь. Это поле объекта. Соответственно, слева от стрелки указывается объект, а справа - название поля в нем.

Если что, в учебнике в ОП посте есть глава про ООП. Там это вроде объясняется.
927381
#256 #927304
>>927219

>Не было ничего нихрена о ней сказано


Там же написано: "необходимо изучить куки, переменную $_COOKIE и функцию setcookie()". При запуске скрипта проверяешь, прислал ли тебя пользователь куку с именем, скажем, "hui". Если прислал, то выводишь сообщение с текущим значением, увеличиваешь ее значение на единицу и ставишь пользователю, если не прислал - то ставишь ему эту куку со значением 1. Все, блядь, больше вообще ничего не надо.
#257 #927305
>>926256

> информатика


> интерес


> PHP


Ты СОВЕРШЕННО не понимаешь в чем суть PHP. PHP это не SICP "о, привет чуваки, зацените решение задачки на скиме, писал два месяца". PHP это не псевдоинтеллектуальные обсуждаения алгоритмов и структур данных. PHP это не сложные вычисления, нейроночки или динамические интерфейсы. PHP это язык, где люди могут побыть говнокодерами — ужасными, тупыми, безразличными ко всему рабами галер, которыми они на самом деле и являются. json_decode возвращает null, а мы смеемся. Кусок стэйта рендерится на сервере в глобальной области видимости, а мы смеемся и обмазываемся миддлварями на ноде. Три сеньор разработчика спрыгнули с крыши, пытаясь отрефакторить движок корпоративной CMS на 4-й пыхе, а мы смеемся и просим еще. Лапшекод, регулярочки, критические уязвимости — мы смеемся. Мы бездушно подпишемся на любой проект, где нам заплатят дошираком, наши предпочтения не основаны на логике программирования, бесцельное внедрение сторонник библиотек — наша стихия, мы — истинное лицо вебдевелопмента.
927562927572
#258 #927324
>>927263

Моар кота.
927334
78 Кб, 720x480
#259 #927334
>>927324
Не буду кидать, ибо оффтоп.
А вообще - ОП-няша.
Добра ему, всех благ и в нелегком деле обучения ньюфагов.
Именно благодаря ему сей тред не тонет.
Домо, PHP-ОП-сан!
#260 #927369
Курс по Laravel от webformyself годный? С учетом того, что он записан не на актуальной версии
927371
#261 #927371
>>927369
Зачем какие-то непонятные русские курсы , если есть laracast
927383
#262 #927381
>>927302
Не понимаю нихуя, вот и спросил
#263 #927382
начал делать 1 упражнение из основ ООП http://ideone.com/xHIidQ не могу понять в чем ошибка, нужно передавать во 2 foreach массив из ответов на вопросы, для которого писать отдельную функцию?
927386929236
#264 #927383
>>927371
Потому что я ленивый славскам не очень хорошо знающий английский
#265 #927384
Пацаны у меня трабл. Нужно сделать на старом сервисе одном подобие апи, что бы отдавать расписание.

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

Поэтому буду делать просто php файлом в корне проекта.

Суть проблемы в следующем:

Например есть много эвентов, и сторонний сервис, который будет моё "апи" опрашивать, требует под каждый эвент отдельный урл.

Под каждый эвент я не хочу хуярить отдельный файл вот так:
site.ru/event1_scheduale.php
site.ru/event2_scheduale.php
site.ru/event3_scheduale.php
site.ru/event3_scheduale.php

На фреймворке с нормальным роутингом я бы наебенил очень просто через 1 метод в 1 классе всё и урлы бы были вида:
site.ru/api/sceduale/event1
site.ru/api/sceduale/event2
site.ru/api/sceduale/event3

Но как так изебнуться что бы сделать в 1 пхп файле так? Что бы не копипастить всё это дело?

Ебаться с htaccess?

Я бы очень хотел сделать 1 файл, что бы пусть даже был некрасивый урл типа такого:

site.ru/scheduale.php/event1
site.ru/scheduale.php/event2
site.ru/scheduale.php/event3
#265 #927384
Пацаны у меня трабл. Нужно сделать на старом сервисе одном подобие апи, что бы отдавать расписание.

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

Поэтому буду делать просто php файлом в корне проекта.

Суть проблемы в следующем:

Например есть много эвентов, и сторонний сервис, который будет моё "апи" опрашивать, требует под каждый эвент отдельный урл.

Под каждый эвент я не хочу хуярить отдельный файл вот так:
site.ru/event1_scheduale.php
site.ru/event2_scheduale.php
site.ru/event3_scheduale.php
site.ru/event3_scheduale.php

На фреймворке с нормальным роутингом я бы наебенил очень просто через 1 метод в 1 классе всё и урлы бы были вида:
site.ru/api/sceduale/event1
site.ru/api/sceduale/event2
site.ru/api/sceduale/event3

Но как так изебнуться что бы сделать в 1 пхп файле так? Что бы не копипастить всё это дело?

Ебаться с htaccess?

Я бы очень хотел сделать 1 файл, что бы пусть даже был некрасивый урл типа такого:

site.ru/scheduale.php/event1
site.ru/scheduale.php/event2
site.ru/scheduale.php/event3
927391
#266 #927386
>>927382

>foreach ($question->answers as $letter => $answer) {



$question->answers должен быть ассивом или объектом, а у тебя
в описании класса там простая переменная

>public $answers; // варианты ответов

927394
#267 #927389
Хочу в классе объявить закрытое поле и сразу его инициализировать:

private $QueryFormPath = __DIR__ . '/' . 'queryform';

На что получаю сообщение об ошибке:

>Parse error: syntax error, unexpected '.', expecting ',' or ';'


Безобидное же действие, что не так?
927408929236
#268 #927391
>>927384
Чем тебя GET-запросы не удовлетворяют, поехавший?
927398
#269 #927394
>>927386
http://ideone.com/VwBMac
спасибо
почему то не получается сделать через новую функцию
#270 #927398
>>927391
Меня то они как бы устроят, но смотри я делаю вот что бы эти ребята могли опрашивать
http://mir-kvestov.ru/integration
вот их мануал:
https://docs.google.com/document/d/1b_MV2wfUgq0O9L-xjuPsbLlaVYJqNkSotaARvfBShS8/edit

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

Одновременно гет и пост вообще работать будут?
#271 #927401
Всё я кажется понял. Я сделаю урлы вида:

site.ru/scheduale.php/event1
site.ru/scheduale.php/event2
site.ru/scheduale.php/event3

и буду из
$_SERVER дергать:
event1
event2
event3
кусочек. Должно сработать.
927404
#272 #927404
>>927401
AcceptPathInfo только настроить не забудь.
927406
#273 #927406
>>927404

>AcceptPathInfo


Это ты про то, что бы никто не мог лазить по папкам и запускать скрипты которые не в корне лежат или другие файлы скачивать/смотреть вообще?
Спасибо за совет.
927407
#274 #927407
>>927406
Нет, если эту хуиту не включить, то запрос вида /shitcode.php/another_shit будет просто отклонен и у тебя ничего не получится.
927409
#275 #927408
>>927389
http://ideone.com/3vjYE3
Все же работает если выполнить. Хоть ideone и пишет ошибку.
#276 #927409
>>927407
Но у меня уже работает, видимо для modx наворачивали, для чпу.
45 Кб, 538x960
#277 #927449
Ребят, пытался пару раз вкатиться в пхп, пытался начать с заданий с сайта, но вообще не вдупляю как делать задание, хотя до этого прочитал фак, это я про http://archive-ipq-co.narod.ru/, может какую то литературу прочитать до того как начать знакомство с переменными и тд
927451929236
#278 #927451
>>927449

PHP исчерпывающее руководство

В свое время(годик назад) когда вообще ничего не понимал да и сейчас ничего не понимаю, дало неплохой старт, теперь могу спокойной пилить какие нибудь проектики для себя
927452927498
#279 #927452
>>927451
но там совсем для тупиц вроде меня, но если ничего прям не понимаешь, тебе зайдет
#280 #927488
927491
#281 #927491
>>927488
Зандстру хвалят
927502
#282 #927498
>>927451

>PHP исчерпывающее руководство


а можно автора? а то там много похожих
927501
#284 #927502
>>927491
А я не хвалю. Там первые несколько глав конечно хорошо подают основы ООП, а вот дальше начинается вода, так что я даже дропнул не дойдя до собственно паттернов, ну не смог я читать то, что тупо срет тебе в мозг без конкретики.
927503
#285 #927503
>>927502
я тоже дропнул, хз, вообще оч скучно как то заходят книжочки всегда, единственное шо почти фулл прочитал, исчерпывающее руководство
#286 #927521
Что лучше всего юзать для получения случайного значения из массива?
927524
#287 #927524
>>927521
дефолтные фукнции для работы с массивом?
http://php.net/manual/ru/function.array-rand.php
927528
#288 #927528
>>927524
Говорят что стандартная функция хуево рандомизирует.
927529927535927537
#289 #927529
>>927528
ну, в голову напрашивается самое дефолтное из дефолтнейших решений

узнать сколько всего значений, потом rand, потом взять случайный элемент из массива
927538
#290 #927535
>>927528

Конкретнее? Ты ведь не шифрование там пишешь наверно.

Если мне не изменяет память, функция rand() использует линейный генератор: https://ru.wikipedia.org/wiki/Линейный_конгруэнтный_метод

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

Также, есть улучшенный генератор (mt_rand) на основе Мерсенновского перемешивателя чисел: https://ru.wikipedia.org/wiki/Вихрь_Мерсенна

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

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

http://php.net/manual/ru/function.random-bytes.php (PHP7+)
http://php.net/manual/ru/function.openssl-random-pseudo-bytes.php

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

В серьезных системах могут использоваться аппаратные генераторы случайных чисел, которые генерируют совсем непредсказуемые последовательности, например, слушая тепловой шум (столкновения молекул): https://ru.wikipedia.org/wiki/Аппаратный_генератор_случайных_чисел

Аппаратный ГСЧ встроен в некоторые процессоры Intel: https://ru.wikipedia.org/wiki/RdRand
#291 #927537
>>927528

И если уж на то пошло, почему бы тебе не написать самому простой линейный ГСЧ и посмотреть на числа, которые он генерирует, чтобы проверить, насколько они получаются случайными? В статье википедии выше есть формулы и константы, если что. Знаний PHP особых не нужно, достаточно знать циклы.
#292 #927538
>>927529

array_rand это и делает, только она поддерживает массивы с любыми ключами, а не только с идущими подряд номерами.
#293 #927549
Аноны, такая хуйня. Есть у меня такое СПА, которое формы слать должно на сервер. Но роутинг осуществляется через якоря в урле. Все формы аяксом отправляются. Серв на пхп. Как он воспримет гет запрос с якорем внутри. Или все постом делать, что бы урл не трогать?
927583927586929236
38 Кб, 600x450
#294 #927560
Ок. Опять я со своим говнокодом.
>>924484
>>924780

Значит с формами и валидатором я разобрался. Хотел использовать entity класс для создания формы регистрации, но отказался и вот почему: 1 - я не храню пароль в базе, а в форме он должен быть 2 - для проверки полей на UniqueValue() нужно установить doctrine bridge и doctrine bundle и как-то это прикручивать к силексу и здесь смысл использования entity класса исчезает. Поэтому проще сделать отдельную форму и написать для нее свой unique constraint.

Все еще не ясно, что ты имеешь ввиду под использованием сервисов. В 83 треде ты писал, что:

> $app['validator'] = function() use($app){return new App\Helper\Validator($app);};


>Это по моему нарушение принципа DI, получается не DI, а Service Locator


Нужно регистрировать сервис провайдеры или что?
929712931351
#295 #927562
>>927305
А где иначе то?
Увы это болезнь не только PHP
#296 #927572
>>927305

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


Проиграл бы если бы сам с таким не сталкивался.
#297 #927583
>>927549
Аноны, ну че вы ну, знаете ведь небось. Гет запрос аяксом по-любому все обрабатывали.
#298 #927586
>>927549

>Но роутинг осуществляется через якоря в урле


Ето невозможно
http://stackoverflow.com/questions/2317508/get-fragment-value-after-hash-from-a-url-in-php
#299 #927790
В задачке про TestHub создание теста должно осуществляться на одной странице при помощи джаваскрипта или каждый вопрос на отдельной странице?
929236
#300 #927837
Поясните за ORM. Нахуй он нужен?
Я работал с Yii-шным ActiveRecord и Doctrine 2, а также с чистым PDO в других проектах.
Для простых крудов да, ООП, вся фигня, код с объектвми выглядит сладко. Но описывать более сложные SQL-запросы (с подзапросами, джойнами..) через квери-билдеры в ORM - Я ЕБАЛ!!1 Это ж ебаный бойлерплейт!
->select('kokoko')
->from('yoba')
->where('1=1')
Куча ебаных геттеров-сеттеров! Структура базы, связи между таблицами описывается внутри doc-комментов! Это я про доктрину. В Yii вообще пиздец без identity map, апдейты по всем полям, даже если ты изменил одно поле.
Ну что за пиздец?
927847929227
3896 Кб, Webm
#301 #927847
>>927837
Что тебе мешает использовать DQL той-же доктрины? Как по мне, доктрина очень годная ORM. Анотации, консоль, DQL, query builder, интеграция в симфони и дохуя чего еще. Но можно просто обмазываться PDO. Никто не запрещает.
927979
#302 #927852
Подскажите книжку где хорошо разбираются какие-то задачи с ООП, или просто что бы с решением было и комментариями.
927863929219
#303 #927863
>>927852
Dive into haskell
#304 #927979
>>927847
Бля, есть моар с душами что-нибудь?
928044
#305 #927983
анон, пробегись по моему коду, пожалуйста. Я почти доделал по одному гайду недосайт и ЖЕЛАЮВСЕМТЕЛОМ советов по улучшению читабельности/качества кода ну и, если есть, ошибки какие. С учетом того, что я js-джун и с бакэндом столкнулся три дня назад.4 дня до этого еще подучил синтаксис похапе

https://github.com/sylenien/php-news-site/

алсо дома лежит толстая здоровенная, сука, подробная книга по node.js, стоит ли начать читать ее вместо пыхи?
927985
#306 #927985
>>927983
Что за книга по ноду?
927990
975 Кб, 1536x2048
#307 #927990
>>927985

hands on node.js + пик. Люблю скупать книги такие, а по пыхе не было ничего.
927995
#308 #927995
>>927990
ЛЕЛ, скачал после своего вопроса точно такую же
#309 #928002
Анон, дико туплю ночью.
Подскажи неосилятору как сделать эти умножения?
<?php
for($x = 1; $x <= 10; $x++){
echo "$x*$x=\n";
}
1×1 =
2×2 =
928011
#310 #928006
>>927998
Схуяли там инъекция? Там intval, защищает от хуйни.

Схуяли sql в контроллере это не mvc? Обмажутся своими active record и ябут друг друга в жеппу! В идеале выделить работу с sql в прослойку - маппер, чтобы она не была в model. Но если нет, то где ей больше место - в model или controller?
928015929219
#311 #928011
928019
#312 #928015
>>928006

Почему ты даун?*
#313 #928019
>>928011
Спасибо, не туда переменную ставил.
#314 #928032
>>927998

поясни, почему инъекция, пожалуйста. Я думал, что если айди числовое, то посрать?
928036
#315 #928036
>>928032
>>927998

ну и да, что ты можешь про ноду сказать?
а то я боюсь потратить год на пхп, если лучше сразу то
#316 #928039
анончики, вопрос жизни и смерти, срочно нужен совет знатока по YII, можно за $
970 Кб, Webm
#317 #928044
>>927979
Не, недавно пак проебал.
#318 #928063
>>927998

>Зачем синглтон для соединения с БД?


Всмысле? А почему бы ему не быть синглтоном?

мимо-код-не-смотрел
929219
#319 #928072
Господа, как убрать пробелы из значений элементов двумерного массива?
Вроде как сделал через foreach и сомневаюсь, что так "правильно" - для одномерных массивов можно сделать array_map('trim', $array)
929219
#320 #928097
Я ознакомился со статьёй о безопасной авторизации на хабре:
https://habrahabr.ru/post/13726/ -Безопасный метод авторизации на PHP
И имею вопрос. Вот пользователь. Он ввёл свои данные, скрипт поискал юзера, нашёл, сравнил пароли, при совпадении создал ему новый хеш, записал куки и перенаправил работу скрипту проверки. Скрипт проверки сравнивает то, что записано в куках с тем, что записано в базе (как я понял) и в случае совпадения, возвращает "ок".

А теперь дурацкий вопрос. Как этим пользоваться? Сами скрипты я повторил у себя на хостинге, они работают. Допустим, у меня есть ещё пара php файликов, которые хочу доверить только авторизованным пользователям. Как это сделать?
928103928139929203
#321 #928103
>>928097
Немного исправлю ссылку: https://habrahabr.ru/post/13726/

И сразу ещё один вопрос.
Там используется конструкция
header("Location: check.php"); exit();
Я погуглил на тему header(), и везде пишут, что так отправляются заголовки html страницы. А в коде это используется для передачи управления другому скрипту. Как так-то?
928139
#322 #928125
Помните например такой проект как спрашивай.ру, который существует и сейчас. Проект с довольно большой аудиторией, на чём надо писать подобные сайты чтобы они нормально работали? Обыкновенного ПХП ООП и обычной базы данных хватит? Или нужно что-то сложнее?
929203
#323 #928135
Анон, проверь у тебя ideone работает? Ввожу код, жму ран и страница перезагружается
929203
#324 #928139
>>928097
Там смысл в том, что на страницах, которые ты хочешь отдавать только авторизованным пользователям, проверяются куки. Соответственно на любой такой странице тебе надо выполнять код скрипта проверки, если куки пользователя проходят проверку - отдавать содержимое, если нет - посылать нахуй или на страницу регистрации.
>>928103
Это не передача управления, а редирект на любую страницу, все правильно пишут. В статье просто демонстрируется проверка сразу после регистрации.
928166
#325 #928166
>>928139
То есть, весь код из check.php должен выполняться перед любым кодом со страницы, (допустим, index.php), а вместо print "Привет, ".$userdata['user_login'].". Всё работает!"; писать тело страницы со всеми хидерами и футерами?
928170929203
#326 #928170
>>928166
Да, именно так.
928171
#327 #928171
>>928170
Спасибо за разъяснение.
#329 #928320
А допустимо ли делать скачивание файла в задачке про файлообменник(и вообще) вот так вот:
<a href="/{{file.link}}" download>Скачать бесплатно и без смс</a>
Или надо как-то сложнее изворачиваться?
928323929203
#330 #928323
>>928320
Повалят скриптами.
Каптча нужна хотя бы простенькая.
928325
#331 #928325
>>928323
Для меня это еще сложно. Не покажешь как правильно делать то?
928331
#332 #928331
>>928325
Два массива со значениями от 1 до 10.
Если "введённое в поле" равно $arr1[$i] + $arr2[$o], то echo ссылка.
При обновлении страницы $i++, а $o+2 либо - array_rand.
Ну и вывод значений на странице соответствующий.
928336928343
#333 #928336
>>928331
Не, ну это ненадежно. Пусть как у Гугла делает. "Отметьте картинки на которых есть Абу".
928338928343
#334 #928338
>>928336
Можно прикрутить рекапчу эту самую.
928343
#335 #928339
http://ideone.com/3pc0qC
сделал метод getOvertimeHours(), но он выводит нули в массиве, и при выведении ошибка Notice: Array to string conversion
928349
#336 #928343
>>928331

>Два массива со значениями от 1 до 10.


>Если "введённое в поле" равно $arr1[$i] + $arr2[$o], то echo ссылка.


>При обновлении страницы $i++, а $o+2 либо - array_rand.


>Ну и вывод значений на странице соответствующий.


Сложна. Это что, делать отдельный шаблон и перенаправлять на него для этой хуиты?
>>928336
>>928338
Это сложно? Я вот погуглил, вроде гугл капчу нельзя прикрутить на локалхост, не?
928356
#337 #928349
>>928339
Так а вопрос в чем?
928363
#338 #928356
>>928343

> Это что, делать отдельный шаблон и перенаправлять на него для этой хуиты?


Вроде того.

>Это сложно? Я вот погуглил, вроде гугл капчу нельзя прикрутить на локалхост, не?


Это сложнее. Прикрутить можно, если сервер на твоем локалхосте имеет доступ в Интернет.
928358
#339 #928358
>>928356

>Вроде того.


Да не, это какой-то изъеб. Вот был же ex.ua, там можно было качать без капчи и регистраций, как они это делали не боясь что им завалят сервера?

>Это сложнее. Прикрутить можно, если сервер на твоем локалхосте имеет доступ в Интернет.


Ладно, только гугл подсказывает только сраные плагины на вордпресс.
928361928362928371
#340 #928361
>>928358
Ну я хз, вот тут как-то сделано на жабаскрипте: http://biotualet1.ru/otzyvy.html
То, что я имел в виду.
Но там после ввода ответа и нажатия срабатывает POST, а ты бы просто ссылку выдавал.
928367
#341 #928362
>>928358
Тебе не нужно геморроиться.
Только желающие повалить будут писать скрипты под тебя.
Ты можешь действия там менять рандомно (минус, плюс, деление, умножение) и т.п.
928367
#342 #928363
>>928349

>928339


https://ideone.com/YfDjGW
да уже ни в чем, я просто невнимательно смотрел, вместо числа массив передавал
#343 #928367
>>928361

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


В то то вот и дело, что я не знаю как это сделать.
>>928362
Ну как такое сделать я понимаю, но хотелось бы именно не "лишь бы работало", а правильно сделать.
928374
91 Кб, 915x506
#344 #928371
>>928358

>ex.ua


Там, где нет капчи, пользуются другими методами - типа блокировки известных прокси и ограничениями на количество запросов/одновременных подключений для остальных. Но это, вроде, уже к настройкам сервера ближе, а не PHP.
#345 #928374
>>928367

> POST


> не знаю


Прочитай первые главы учебника по пыхе "PHP 5 в подлиннике". Его принято поливать говном и считать за днище, однако это единственный учебник, где прежде, чем перейти к профессиональному программированию, освещается необходимый для этого дела минимум по запросам и формам.
928375
#346 #928375
>>928374
Ты меня не понял. Я не хочу постоянно перенаправлять пользователя туда-сюда. Я хочу как-то впилить туда капчу.
928377929191
#347 #928377
>>928375
Ну напиши простейший скрипт на JS, который AJAX запрос отправляет и получает ссылку на скачивание ответом.
928379
#348 #928379
>>928377

>Ну напиши простейший скрипт на JS, который AJAX запрос отправляет и получает ссылку на скачивание ответом.


Я так и думал. Проблема в том, что я толком то JS не знаю, не то что бы аякс. Ну да ладно, будет как раз повод его освоить.
#349 #928462
Посоны, есть куча PHP классов от вебсервиса, сгенерированных из XSD. Там собственно только поля, сеттеры и геттеры. Данные получаются на вебсервис и разгоняются по этим классам автоматом. Вопрос - как загнать эти классы в БД автоматом? При том, что там поля не соответствуют полям в БД? Есть какие-то готовые решения? Или все вручную катать?
928464929191
#350 #928464
>>928462
Вручную не нравится - классов полно, методов на вебсервисе тоже. Что хотелось бы - какую-то маппилку, которая просто берет готовые классы, маппит по какому-нибудь правилу или списку на классы из БД и все сама пишет в БД.
72 Кб, 1161x675
#351 #928496
В чем ошибка?то уже второй час долблюсь
928497929191
#352 #928497
>>928496
Измени условие на ошибочное и запусти. Это ведь Codeacademy? Днище, на самом деле, не всегда ясно, чего от тебя хотят, сам с этого охуевал. В данном случае, очевидно, хотят, чтобы ты сначала проверил верное утверждение ("3<7"), а потом изменил его на неверное ("3>7") и опять проверил.
928506
#353 #928506
>>928497
спасиба, добрый человек:ззз
Чего посоветуешь новичку для изучения PHP?
928509
#354 #928509
>>928506
Обзорно можно познакомиться например здесь: http://php720.com. Все довольно понятно, дизайн не выворачивает, читабельно.
929191
#355 #928514
Допустим пишу я сеттер для свойства класса и в нём делаю проверку. Например для $id я делаю проверку на то, что это число и оно больше либо равно нулю. Если всё хорошо, то присваиваю значение. Что лучше делать если условие не проходит? Выкинуть исключение и в нём написать в чём проблема или тупо вернуть false (или null) и ничего не делать?
928529928556929191
#356 #928529
>>928514
я ничего не делаю, так как у меня простые пути. Тупо если запросили несуществующее id с базы например, то и хуй с ним. Будет тупо редирект на уровне контроллера если модель ничего не вернула на 404 или вообще нахуй в личный кабинет, ибо нехуй лазить по чужим заявкам/страницам/платежам и пр.
928531929191
#357 #928531
>>928529
А записывать ты туда всякий мусор разрешаешь? Меня в данном случае сеттер волнует. Да конечно на сайте может быть валидация на стороне пользователя, но разве можно быть на 100% быть уверенным в том, что мы получили валидные данные от пользователя?
928542929191
#358 #928535
Прохожу от нехуй делать курсы битрикса (на самом деле, работодатель попросил).
В принципе, там много неоднозначных ответов (в одном тесте например правильный ответ - может работать на любом вебсервере умеющем в похапе, в другом - бэкэнд это строго апач с похапе).
Дурдом, короче. Зато теперь я трижды сертифицированный говноед.
Четвертый курс (Huiload) сдавать буду на следующей неделе у них в офисе.
928541
#359 #928541
>>928535
Ты сюда повыёбываться пришел или я не понял смысловой нагрузки твоего поста?
929191
#360 #928542
>>928531
Не разрешаю, тоже анально игнорирую если у меня попытались хуйню протолкнуть. А вообще я даже логирую пользовательские действия, и если кто-то попытался отключить фронт-энд проверки и споткнулся на бек-энд проверках, то так и заношу в базу, что вот дескать этот хуй пытался МАМ,ХАКЕРИТЬ)))
929191
#361 #928556
>>928514
Исключение конечно. Причем проверку не в сеттере лучше делать, а отдельный метод написать, который из сеттера вызывается. Вот метод этот уже true/false возвращает. А сам сеттер выглядит вроде этого:
if ($this->parameterIsValid($parameter)) {
$this->parameter = $parameter
}
throw new \UnexpectedValueException('Parameter is not valid');
928557
#362 #928557
>>928556
return в if блоке забыл
#363 #928561
Что бы изучит и уметь создавать вирусы, шпионские проги и т.д. А так же антивирусы к ним, это в какой язык нужно вкатываться ?
928563929178
#364 #928563
>>928561
ассемблер
#365 #928615
Как проверить, существует ли метод у статического класса?
929178
2 Кб, 160x50
#366 #928630
Я тут немного костылей нагородил, теперь вот не знаю, правильно или нет.

В общем, есть на странице селект, содержимое которого берётся при генерации страницы из бд с помощью функции:
<div id="div_change">
<?php
list_selector($table, $column, 'list_id', 'list_name');
?>
</div>

Содержимое селекта - список предметов. И этот список можно менять, добавляя или удаляя предметы.
Сделал это через аякс: нажимаем кнопку, срабатывает js-крипт, запускает через ajax php-код, а тот прописывает добавление/удаление предмета в БД.

И тут мне восхотелось сделать так, чтобы список на странице тоже обновлялся без перезагрузки страницы. И сделал это так: как только у аякса срабатывает success, тут же запускает через ещё один аякс ещё один пхп-файл, который принимает через _POST данные для генерации list_selector и запускает его с этими данными. Функция возвращает собранный html-код в тот файл, который вызван через второй аякс, оттуда код возвращается в js-скрипт и селектор обновляется.

Кривость какая-то, но проще способа не нашёл. Это так и должно быть, или я уже шизею?
928793929178
159 Кб, 700x990
#367 #928702
Привет котаны. Дело в том, что я уже достаточно долго пилю свой бложек на php, теоретически я хотел бы показать его своему потенциальному работодателю. Стоит ли мне это делать, либо у меня пиздец какое позорище получилось? Буду благодарен за любое мнение.
https://github.com/honeydev/s-blog
Пример для понажимать - http://honeytype_0ayl98.radius-host.net/
232 Кб, 1080x1920
#368 #928713
>>928702
Ну хуй знает. Это при попытке создать новый пост с загруженной картинкой. Тестами покрывал?
928746
#369 #928730
>>928702
Ну так на вскидку:
Нет публичной папки, весь код доступен пользователю.
Не используешь никаких паттернов управления данными. Все круды в контроллерах или что это там у тебя в перемешку с логикой.
4 класса в одном файле https://github.com/honeydev/s-blog/blob/master/app/src/authorization.php

Короче, может быть это и работает, но выглядит как свалка.
928739928746
#370 #928739
>>928702
>>928730
Дальше смотреть не стал.
Тут аноны кидают свои гитхабы. Полазь по ним, посмотри как они делают.
#371 #928746
>>928730
Нет, не покрывал не умею в функциональное тестирование.
>>928713
Просто у меня классы контроллеров не вынесены в отдельные файлы, но сами классы разделяются.
Короче буду все переделывать, спасибо. Все же нужно было изучать паттерны сначала, а не писать лижбы написать.
929167
#372 #928793
>>928630
Почему ты не хочешь сразу в первом аяксе обновлять список?
928830
#373 #928807
>>928702

github/sylenien -> php site
почитай роутер.пхп. Знакомый похапе миддл одобрил, правда, с придирками.
#374 #928830
>>928793
Вообще, да. Можно. Но тогда через аякс нужно будет передавать все данные и для апдейта таблицы и для апдейта селектора. Надо будет подумать на свежую голову завтра.
#375 #928887
Не работает PDO->lastInsertId(), всегда ноль возвращает. В чем может быть причина?
928939929167
8 Кб, 328x211
13 Кб, 451x498
9 Кб, 585x313
11 Кб, 621x268
#376 #928910
Нужна помощь, пытаюсь динамически вывести значения из БД
Пикрелейтед ошибка:

А вот скрины SiteController, модель CategoryPhp, и вывод во вьюху.

Пробывал проверить через is_array, тогда просто ничего не выводит.
928911928912929167
10 Кб, 543x310
#377 #928911
>>928910
Db.php
928912928917
#378 #928912
>>928910
>>928911
Все эти статические хуитки выглядят довольно опасно.
928914
#379 #928914
>>928912
Дело в том что я прохожу по видеокурсам, и там на этом моменте все работает, даже дамп базы импортнул - все равно не пойму в чем проблема.
928916929167
#380 #928916
>>928914

>Дело в том что я прохожу по видеокурсам


Какие-то хуевые видеокурсы. Чисто на первый взгляд

>include_once 'c:\openserver что-то там дальше


Во-первых, там и правда учат так пути прописывать? Во-вторых, инклюдить что-то в скрипте с объявлением класса это тихий ужас, это говнокодище за которое руки отрывать надо. Учи что такое неймспейсы и автозагрузка классов. В третьих, там какая-то дикая мешанина из статики и динамики. Короче исправь первые два пункта и потом попробуй написать тоже самое, только без статики.
928918929167
#381 #928917
>>928911
Алсо нихуя не понял зачем ты там еще и тру возвращаешь. Это же пхп, тебе не надо париться по поводу того что ты там возвращаешь в методе/функции.
928920
#382 #928918
>>928916
через PATH у меня почему-то не видит
#383 #928920
928922928942
#384 #928922
>>928920
Честно говоря, я не знаю как такая хуитень может работать без пространства имен.
929167
#385 #928939
>>928887
Ошибки в коде ищи. Такая же параша была. Смотри, что было выше.
7002 Кб, Webm
#386 #928942
>>928920
Ну теперь все встало на свои места. Хохол-быдлокодер хуже индуса.
Мой тебе совет:
Не надо проходить мутные курсы в стиле 'Магазин дилдаков за 24 наносекунды'.
В ОП посте есть учебник. Лучше порешай задачи из него и попробуй сделать студентов.
929077929167
#387 #928964
С какой стороны зайти к студентам?
#388 #928985
>>928964
ПАЦАНЫ, С БОКУ ЗАХОДИ! А НУ, ЧИКИ-БРИКИ И В ДАМКИ!
Хотелось бы услышать конкретный вопрос.
#389 #928999
>>928964
Сам не знаю с какой стороны подойти, но можно попробовать в тетради расписать свою архитектуру.
929028
#390 #929028
>>928964
>>928999
Для начала стоит написать индексный файл и заинклюдить туда шаблон главной страницы, прикрутив к нему бутстрап. Потом можно уже добавлять функционал. Можете посмотреть гитхабы анонов уже сделавших студентов.
929038
#391 #929038
>>929028
как найти гитхабы анонов которые уже это делали?
929167
#392 #929053
Поясните, почему хранить разметку в бд зашквар? Например, у сайта сложный дизайн, не хранить же каждый блок текста в отдельной таблице и не выводить его потом??
929059929159
#393 #929059
>>929053
раздели дизайн на меньшие шаблоны, выводи их инклудами.
929067
#394 #929067
>>929059
Но тогда получается, что одна страница будет лежать в нескольких колонках базы данных. А это множение колонок в таблице. ведь под каждый кусок шаблона должен выводиться определенный кусок из одной статьи.
929070
#395 #929070
>>929067
Бля. Не храни щаблоны в базе данных.
Покрайней мере в MySQL.
929076929167
#396 #929072
например я же не буду писать
<ul><?php
foreach($result as $item){
<li><?=$item?></li>
<?php } ?>
</ull>
<?php foreach($result2 as $text) {?>
<p class="hueta"><?=$text?></p>
<?php }?>
И подумайте сколько запросов к бд делать придется под такую жесть. И не рациональное использование таблиц получится (много таблиц с кусками одной страницы)
929076929152
#397 #929076
>>929070
я тебе про сложную верстку поясняю маня.>>929072
А не одностраничники на яндекс.народе
Или мне весь текст прямо в шаблоне хранить ежели верстка сложная?
929122
#398 #929077
>>928942

в оп посте нет ни одного гайда про веб-дев. Хохол-быдлокодер внятно объясняет азы, а в оп-посте просто блять задача в стиле "я научил тебя пользоваться палкой, иди строй ткацкий станок". Критикуешь этот курс - покажи хороший.
другой анон
929142929202
#399 #929078
Анон, помоги, пожалуйста!
Прохожу ООП по учебнику из ОП поста. Вроде не дурак, все разминочные задания сделал без особых проблем, а вот с последним (которое про компанию ВЕКТОР) впал в ступор.
Расписал абстрактные классы компания, департамент и сотрудник. Че дальше то делать ?
Нужно создавать класс для каждой профессии, или сделать профессию свойством сотрудника ?
Почему потребление кофе - не является свойством сотрудника ? Является ли свойством количество производимых страниц ? Если нет - почему ?
Где должны создаваться и добавляться в департамент сотрудники ? Это нужно делать в отдельном классе или прямо в классе департамент ?

Вопросов гораздо больше, но даже сформулировать их пока очень трудно. Помогите, прошу.
4 Кб, 1274x115
#400 #929102
Что это?

Объясните нубу последнею строку
929104929113929142
#401 #929104
>>929102
Посмотри в треде выше, ОП где-то постыл ссылку на свой урок про кодировки.
929152
#402 #929105
>>929078

>Почему потребление кофе - не является свойством сотрудника ?


Потому что я блять хуй знает. Я ебал этой задачи рот.
Вообще обосрался на этой задаче, хотя что-то до этого получалось.
Слава богу кто-то подсказал, что так заморачиваться не надо - это нигде на хуй не нужно будет.
929142
#403 #929113
>>929102
Синие узоры же на белом фоне. Дизайн наверное такой.
#404 #929117
>>929078

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

> Почему потребление кофе - не является свойством сотрудника ?


Потому что потребление кофе вычисляется методом на основании профессии и ранга. То же самое с зарплатой и листами.
#405 #929122
>>929076
Текст храни в базе, разметку страницы в шаблонах.
Научись правильно оформлять запросы к БД.
Сделал запрос данных из таблицы, перевел полученное в массив, вывел массив на странице.
Все.
#406 #929132
>>929078
Компания и департамент-то с чего абстрактные? Они обычные классы.

>Че дальше то делать ?


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

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


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

>Почему потребление кофе - не является свойством сотрудника ?


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

>Является ли свойством количество производимых страниц ? Если нет - почему ?


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

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


В контроллере. Для департамента пишешь сеттер сотрудников, контроллер добавляет их туда через сеттер. Можно без сеттера сразу при создании департамента через Dependency Injection, тогда тебе придется сначала создать сотрудников.

> Это нужно делать в отдельном классе или прямо в классе департамент ?


Это делается извне, в контроллере. В департаменте никакие сотрудники не создаются, они сами туда приходят (в нашем случае контроллер их туда добавляет).
929142929612929622
#407 #929134
>>929078

> Расписал абстрактные классы компания, департамент и сотрудник.


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

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


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

> Почему потребление кофе - не является свойством сотрудника ?


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

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

> Является ли свойством количество производимых страниц ? Если нет - почему ?


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

> Где должны создаваться и добавляться в департамент сотрудники ? Это нужно делать в отдельном классе или прямо в классе департамент ?


Тут есть 2 подхода:

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

Что еще непонятно?

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

Если ты из тех, кто критикует ООП, считает что он переусложнен и не нужен, то можешь попробовать решить задачу без ООП для сравнения. И посмотреть, насколько более простым будет решение.
#407 #929134
>>929078

> Расписал абстрактные классы компания, департамент и сотрудник.


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

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


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

> Почему потребление кофе - не является свойством сотрудника ?


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

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

> Является ли свойством количество производимых страниц ? Если нет - почему ?


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

> Где должны создаваться и добавляться в департамент сотрудники ? Это нужно делать в отдельном классе или прямо в классе департамент ?


Тут есть 2 подхода:

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

Что еще непонятно?

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

Если ты из тех, кто критикует ООП, считает что он переусложнен и не нужен, то можешь попробовать решить задачу без ООП для сравнения. И посмотреть, насколько более простым будет решение.
929148929612929622
#408 #929138
Есть много объектов, заполненных данными. Можно как-то их на поля таблицы разметить, чтобы сохранялись туда автоматом? Поля не соответствуют полям таблицы, имена классов тоже. Доступа к классам нет, так что в самих классах ничего не напишешь. К классу, от которого они все унаследованы, доступ есть.
929152
#409 #929142
>>929078

Если ты написал все классы, то дальше надо использовать их для решения задачи. А именно:

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

>>929132

Контроллеры - это понятие из архитектуры MVC, у нас тут не MVC ведь, а по сути просто программа для командной строки.

>>929105

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

>>929102

Ты данные выводишь, указав браузеру неправильную кодировку.

>>929077

С гайдами, да, не очень, но у нас есть задача про студентов и в ней очень много комментариев. Со ссылками на статьи про паттерны работы с БД, внедрение зависимостей, MVC и прочие умные вещи.

Я мельком глянул проект на гитхабе - https://github.com/victor-zinchenko/shop.php-start.com , пару классов - там много неправильного, на мой взгляд.

Ну например там есть папка components, а что такое "компоненты", ты можешь сформулировать?

Или например есть класс Cart, который судя по названию, представляет одну корзину, но почему у него все методы статические? Как создать например 2 корзины? На самом деле у него неправильное навание и правильно его называть SessionCartManager или как-то так.

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

Или вот класс DB. Можно подумать, это класс для работы с БД, но у него почему-то всего один метод getConnection. Может правильнее его было назвать ConnectionFactory? и опять же, везде статические методы.

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

Класс Product опять же назван неправильно, его объект не представляет собой один товар.

И так далее.

У нас в задаче про студентов изучаются примерно те же вещи, построение приложения. Только без злоупотребления статическими методами.
#409 #929142
>>929078

Если ты написал все классы, то дальше надо использовать их для решения задачи. А именно:

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

>>929132

Контроллеры - это понятие из архитектуры MVC, у нас тут не MVC ведь, а по сути просто программа для командной строки.

>>929105

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

>>929102

Ты данные выводишь, указав браузеру неправильную кодировку.

>>929077

С гайдами, да, не очень, но у нас есть задача про студентов и в ней очень много комментариев. Со ссылками на статьи про паттерны работы с БД, внедрение зависимостей, MVC и прочие умные вещи.

Я мельком глянул проект на гитхабе - https://github.com/victor-zinchenko/shop.php-start.com , пару классов - там много неправильного, на мой взгляд.

Ну например там есть папка components, а что такое "компоненты", ты можешь сформулировать?

Или например есть класс Cart, который судя по названию, представляет одну корзину, но почему у него все методы статические? Как создать например 2 корзины? На самом деле у него неправильное навание и правильно его называть SessionCartManager или как-то так.

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

Или вот класс DB. Можно подумать, это класс для работы с БД, но у него почему-то всего один метод getConnection. Может правильнее его было назвать ConnectionFactory? и опять же, везде статические методы.

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

Класс Product опять же назван неправильно, его объект не представляет собой один товар.

И так далее.

У нас в задаче про студентов изучаются примерно те же вещи, построение приложения. Только без злоупотребления статическими методами.
929202
#410 #929148
>>929134

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


>


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



Проиграл с задроченного ноулайфера, который не видит людей и строит абстрактные модели их предпочтений.
#411 #929152
>>929104

Статья на гитхабе про кодировки: https://github.com/codedokode/pasta/blob/master/cs/strings.md

>>929138

Можно сделать внешние классы-мапперы. Например, UserMapper умеет сохранять и загружать объекты User из таблицы users. В мапперах прописать название таблицы и соответствие между колонками таблицы и полями объектов, может даже правила преобразования (например поле DATETIME в PHP объект DateTime).

Паттерн так и называется Data Mapper, подробнее у Фаулера и у меня в уроке https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Также, вместо своего маппера можно взять библиотеку Doctrine. Она такое умеет.

>>929072

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

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

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

Но даже в случае кеширования, кеш хранится отдельно от исходных данных.
929171
#412 #929154
Поясните, пожалуйста за сессии. Есть некий php-класс. В одном методе я открываю сессию с помощью session_start(), пишу в $_SESSION, потом пишу header("Location: ".$desiredLocationURL) и в следующей строке записываю exit

Как можно в другом методе класса, который вызывается позже, получать доступ к $_SESSION? Почему-то к нему нету доступа, пишет

>Undefined variable: _SESSION


Нужно писать session_start()?
Сессия будет работать, если открыть браузер в анонимном режиме?
929253
#413 #929156
Будет ли работать сессия, если в браузере отключена поддержка cookies?
Сколько "держится" сессия?
929253
#414 #929159
>>929053

О какой разметке речь? Если ты хочешь сохранить набранный в HTML редакторе код статьи с форматированием - пожалуйста, сохраняй. Если ты хочешь сохранить верстку/дизайн сайта в БД, то это плохая идея. Ну хотя бы потому, что верстальщику неудобно будет с ней работать. Ведь все редакторы кода работают с файлами на диске, а не с данными в базе.

Файлы легко поместить в систему контроля версий вроде git, а данные в базе - нет.

Бывают CMS, где верстка хранится в БД, но это очень неудобно.

Шаблоны дизайна все же должны лежать в виде файлов на диске.

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


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

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


И пусть.

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


Ты что-то путаешь. Статья должна храниться в БД как одна сущность, целиком.
#415 #929167
>>929070

Что не так с MySQL?

>>929038

В комментариях к задаче про студентов в конце это написано. Прочитай их.

>>928964

Изучить комментарии которые даны к этой задаче. Там даны примеры, также есть ссылка на статью про MVC.

>>928942

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

>>928922

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

>>928916

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

>>928914

Не понимаешь - значит, надо разобраться. Поставь echo/var_dump, смотри что хранится в переменных, сравни с тем, что в них должно быть.

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

>>928910

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

Готовых ответов не будет.

Не прописывай абсолютные пути в include, пиши относительно __DIR__ лучше.

>>928887

Значит не было операции INSERT в ходе которой сгенерировался новый id.

>>928746

1 класс = 1 файл. Почитай мой урок по PSR-4 https://github.com/codedokode/pasta/blob/master/php/autoload.md

Паттерны тебе рановато изучать, чтобы их изучать надо ковырять исходный код Симфони и Доктрины.

>>928702

- Изучи PSR-4 и автозагрузку (ссылка выше)
- Изучи MVC, ты вообще не понимаешь, что такое контроллер: https://github.com/codedokode/pasta/blob/master/arch/mvc.md

У меня нет времени все разбирать сейчас, могу посоветовать почитать комментарии к задаче про студентов, там все подробно расписано: https://github.com/codedokode/pasta/blob/master/student-list.md
#415 #929167
>>929070

Что не так с MySQL?

>>929038

В комментариях к задаче про студентов в конце это написано. Прочитай их.

>>928964

Изучить комментарии которые даны к этой задаче. Там даны примеры, также есть ссылка на статью про MVC.

>>928942

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

>>928922

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

>>928916

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

>>928914

Не понимаешь - значит, надо разобраться. Поставь echo/var_dump, смотри что хранится в переменных, сравни с тем, что в них должно быть.

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

>>928910

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

Готовых ответов не будет.

Не прописывай абсолютные пути в include, пиши относительно __DIR__ лучше.

>>928887

Значит не было операции INSERT в ходе которой сгенерировался новый id.

>>928746

1 класс = 1 файл. Почитай мой урок по PSR-4 https://github.com/codedokode/pasta/blob/master/php/autoload.md

Паттерны тебе рановато изучать, чтобы их изучать надо ковырять исходный код Симфони и Доктрины.

>>928702

- Изучи PSR-4 и автозагрузку (ссылка выше)
- Изучи MVC, ты вообще не понимаешь, что такое контроллер: https://github.com/codedokode/pasta/blob/master/arch/mvc.md

У меня нет времени все разбирать сейчас, могу посоветовать почитать комментарии к задаче про студентов, там все подробно расписано: https://github.com/codedokode/pasta/blob/master/student-list.md
#416 #929171
>>929152

>Паттерн так и называется Data Mapper, подробнее у Фаулера и у меня в уроке



О, как раз что искал. Буду писать мапперы. Про доктрину почитал, но все пишут тормознутая, а мне надо что-то побыстрее. К тому же там как я понял надо в самих классах комментарии писать, чтобы доктрина их понимала. Свой маппер не должен сильно затормозить, это же всего +1 класс к каждому объекту, либо можно вообще общий для всех написать.
929253
#417 #929177
Есть ли какие-то стандарты, правила для кода PHP(сколько пробелов и прочее)?
929182929253
#418 #929178
>>928630

Вообще, у тебя все смешано в кучу. Вот посмотри:

list_selector($table, $column, 'list_id', 'list_name');

У тебя тут заложены ограничения:

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

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

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

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

То есть тебе надо подучить DOM, и DOM-объекты соответствующие тегам SELECT и OPTION.

>>928615

- method_exists
- function_exists
- рефлекшен

>>928561

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

Могу посоветовать интересный блог с свежей и актуальной информацией про ботнеты и прочий скам: https://krebsonsecurity.com/ Правда он на английском, но без английского в сфере кибербезопасности делать нечего.

Антивирусы (ядро) обычно пишут на Си++ ради производительности, но чтобы их писать, нужны очень широкие знания - начиная с машинных кодов и работы процессора, продолжая WinAPI, заканчивая форматами файлов и виртуальными машинами. То есть надо очень много изучать разных вещей, и низкоуровневых, и высооуровыневых, и этому на сомнительных форумах вряд ли научат. Там тебя только научат как скачать готовую программу, взломать кривой непатченный годами магазин на PHP и попасть в отдел К.
#418 #929178
>>928630

Вообще, у тебя все смешано в кучу. Вот посмотри:

list_selector($table, $column, 'list_id', 'list_name');

У тебя тут заложены ограничения:

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

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

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

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

То есть тебе надо подучить DOM, и DOM-объекты соответствующие тегам SELECT и OPTION.

>>928615

- method_exists
- function_exists
- рефлекшен

>>928561

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

Могу посоветовать интересный блог с свежей и актуальной информацией про ботнеты и прочий скам: https://krebsonsecurity.com/ Правда он на английском, но без английского в сфере кибербезопасности делать нечего.

Антивирусы (ядро) обычно пишут на Си++ ради производительности, но чтобы их писать, нужны очень широкие знания - начиная с машинных кодов и работы процессора, продолжая WinAPI, заканчивая форматами файлов и виртуальными машинами. То есть надо очень много изучать разных вещей, и низкоуровневых, и высооуровыневых, и этому на сомнительных форумах вряд ли научат. Там тебя только научат как скачать готовую программу, взломать кривой непатченный годами магазин на PHP и попасть в отдел К.
929360
#419 #929182
>>929177
PSR же
их несколько штук, почитай.
http://www.php-fig.org/psr/
#420 #929183
929185
#421 #929185
>>929183
>>929078
я тут обосрался изза того что в глаза долблюсь, потом просто наговнокодил и не стал переделывать, чтобы хоть как то соответствовать требованиям задачи, можешь посмотреть может поможет
#422 #929186
Как правильно прятать файл, который обрабатывает форму? Допустим мы используем аякс или просто js, что позволяет нам не писать допустим action="save.php", но на странице всёравно же будет виден код ajax или js, и по ним можно будет понять какой файл обрабатывает форму. Как правильно прятать?
#423 #929191
>>928542

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

>>928541

Он принес нам интересную инсайдерскую информацию про курсы битрикса. Может кому пригодится.

>>928514

Давай рассуждать логически.

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

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

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

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

>>928529

У него другая ситуация.

>>928531

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

>>928509

Я тут решил глянуть урок по ООП, и мне кажется, это не очень удачное начало: http://php720.com./lesson/50

Но это что касается ООП, другие темы я не смотрел там.

>>928496

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

>>928462

Либо написать свой Data Mapper, либо прикрутить Доктрину. Урок про маппер: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

>>928375

Логично капчу выводить до попытки скачивания. Логика может быть такая:

На странице просмотра файла:

- если пользователь не прошел капчу, показать ему капчу
- иначе не показать

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

В обработчике скачивания файла:

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

Хранить информацию о решении капчи можно в куках или сессии.

То есть тебе бы стоило начать с понимания, как работает HTTP, что такое GET/POST запросы.
#423 #929191
>>928542

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

>>928541

Он принес нам интересную инсайдерскую информацию про курсы битрикса. Может кому пригодится.

>>928514

Давай рассуждать логически.

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

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

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

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

>>928529

У него другая ситуация.

>>928531

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

>>928509

Я тут решил глянуть урок по ООП, и мне кажется, это не очень удачное начало: http://php720.com./lesson/50

Но это что касается ООП, другие темы я не смотрел там.

>>928496

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

>>928462

Либо написать свой Data Mapper, либо прикрутить Доктрину. Урок про маппер: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

>>928375

Логично капчу выводить до попытки скачивания. Логика может быть такая:

На странице просмотра файла:

- если пользователь не прошел капчу, показать ему капчу
- иначе не показать

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

В обработчике скачивания файла:

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

Хранить информацию о решении капчи можно в куках или сессии.

То есть тебе бы стоило начать с понимания, как работает HTTP, что такое GET/POST запросы.
#424 #929192
>>929186
Зачем прятать? Если save.php нормально написан, то ничего прятать не требуется, он любые параметры принимает, валидирует и выдает сообщения об ошибке в случае левых данных. Надо не прятать, а нормально инпуты проверять.
#425 #929197
>>929186
В коде аякса секретный ключ + текущее время. В htaccess редирект например /save/ на save.php. Потом из аякса делаем запрос на /save?secretkey, где secretkey md5 от секретного ключа + текущее время. Сервак сравнивает и показывает 404 not found со всеми заголовками, если не совпало.
929253
#426 #929199
>>929186
НИКАК
С помощью WEB-консоли браузера ЭКСПЕРИМЕНТАТОР может отследить параметры запроса и по какому адресу отправлены данные, а потом на питончике набросать скрипт, который отправляет тот же запрос, представляется браузером и сохраняет печеньки.

Можно настроить роутинг с помощью Alto Router или mod_rewrite, и тогда прописывать не action="save.php", а action="/backend/"; некоторые фреймворки позволяют повесить обработчики серверных событий, типа onRequestURL, например Wordpress мне кажется. Это не остановит заинтересованных лиц от попыток обхода механизмов. Так что для особо критических мест решает все более детальная проверка данных.
929253
#427 #929202
>>929142

Ну, не буду спорить, конечно, но названия классов и переменных - это уже нутакое, не влияющее на функционал. А так да, у хохла много лишнего, типа папки КОНФИХ и компоненцс. С другой стороны, такой подход удобен, чтоб скинуть клиенту готовый архив с сайтом и послать нахуй, а он сам сможет разобраться уже в коде на базовом уровне.
Я вот сейчас тот же тутор хохла прохожу, но многое переделываю под себя и свою логику. убрал дб_конфих и внес в database.php, где к базе подключается и ведется всякое нехорошее

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

вообще приятно, что в пхп-тредике ответят и пояснят, а не обоссут за любой вопрос, как в жс-треде, раковнике
кстати, можешь что нибудь сказать о ноде? У меня лежат две книги по ней и чешуться руки, но я только начал осваивать пхп, а еще в инетах пишут, что нода нинужна
хотел бы работать фуллстек жс макакой, в идеале еще и на удаленке
929263
#428 #929203
>>928320

Допустимо, но тут есть подвохи

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

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

Защиту от роботов делать не требуется, но если очень хочется, то можешь добавить.

>>928166

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

>>928135

У меня работает: http://ideone.com/Ppm71Y

Может у тебя какой-нибудь адблок стоит? Или может это были баги на ideone? Или браузер устарел?

>>928125

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

Википедия на PHP, фейсбук и вконтакте наичнались на PHP. Badoo на PHP.

>>928097

Разбей задачу на более мелкие:

- проверить введенный логин и пароль
- залогинить пользователя с данным id

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

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

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

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

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

Я тебе советую вместо чтения статьи просто понять, как работает авторизация и написать функции залогинивания/разлогинивания/проверки самому.
#428 #929203
>>928320

Допустимо, но тут есть подвохи

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

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

Защиту от роботов делать не требуется, но если очень хочется, то можешь добавить.

>>928166

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

>>928135

У меня работает: http://ideone.com/Ppm71Y

Может у тебя какой-нибудь адблок стоит? Или может это были баги на ideone? Или браузер устарел?

>>928125

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

Википедия на PHP, фейсбук и вконтакте наичнались на PHP. Badoo на PHP.

>>928097

Разбей задачу на более мелкие:

- проверить введенный логин и пароль
- залогинить пользователя с данным id

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

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

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

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

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

Я тебе советую вместо чтения статьи просто понять, как работает авторизация и написать функции залогинивания/разлогинивания/проверки самому.
#429 #929219
>>928072

Это тестовое задание? Можно через циклы, можно через array-walk_recursive или рекурсивные итераторы по массиву.

>>928063

Потому что лишнее усложнение и ограничение (с синглтоном не может быть больше 1 соединения).

Можно просто написать:

$pdo = new PDO(...);

зачем к этому добавлять синглтон? Чтобы было?

А вообще, чем плох в некотоых случаях синглтон, можно попробовать понять из урока по DI https://github.com/codedokode/pasta/blob/master/arch/di.md

>>928006

Инъекции там нет, но стиль плохой. Есть же плейсхолдеры, используй их, а не склеивай запрос из кусков.

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

SQL в контроллере это большой толстый контроллер, а не MVC. Код в контроллере не повторно используемый, его неудобно тестировать, и лучше его писать там поменьше.

> В идеале выделить работу с sql в прослойку - маппер, чтобы она не была в model. Но если нет, то где ей больше место - в model или controller?


Ты по моему не понимаешь, что такое модель и как работает MVC. У меня есть урок https://github.com/codedokode/pasta/blob/master/arch/mvc.md

>>927998

> SQL запросы прямо в контроллере, это не MVC:


Файл называется model/News, это разве контроллер?

По поводу синглтона - лучше дать ссылку на урок про DI. Это ведь к DI относится, как получить объект PDO.

>>927852

Это не книга, но в ОП посте есть учебник и в нем глава про ООП с парой задач. А так, не знаю.
#429 #929219
>>928072

Это тестовое задание? Можно через циклы, можно через array-walk_recursive или рекурсивные итераторы по массиву.

>>928063

Потому что лишнее усложнение и ограничение (с синглтоном не может быть больше 1 соединения).

Можно просто написать:

$pdo = new PDO(...);

зачем к этому добавлять синглтон? Чтобы было?

А вообще, чем плох в некотоых случаях синглтон, можно попробовать понять из урока по DI https://github.com/codedokode/pasta/blob/master/arch/di.md

>>928006

Инъекции там нет, но стиль плохой. Есть же плейсхолдеры, используй их, а не склеивай запрос из кусков.

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

SQL в контроллере это большой толстый контроллер, а не MVC. Код в контроллере не повторно используемый, его неудобно тестировать, и лучше его писать там поменьше.

> В идеале выделить работу с sql в прослойку - маппер, чтобы она не была в model. Но если нет, то где ей больше место - в model или controller?


Ты по моему не понимаешь, что такое модель и как работает MVC. У меня есть урок https://github.com/codedokode/pasta/blob/master/arch/mvc.md

>>927998

> SQL запросы прямо в контроллере, это не MVC:


Файл называется model/News, это разве контроллер?

По поводу синглтона - лучше дать ссылку на урок про DI. Это ведь к DI относится, как получить объект PDO.

>>927852

Это не книга, но в ОП посте есть учебник и в нем глава про ООП с парой задач. А так, не знаю.
929312
#430 #929227
>>927837

Попробуй погуглить, что значит ORM

ORM = Object to Relational (DB) Mapper

Маппер (сопоставитель) объектов с строками таблицы в БД.

Вот и ответ. ORM нужен, если ты хочешь загружать или сохранять данные из БД в виде объектов.

Урок https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

> Но описывать более сложные SQL-запросы (с подзапросами, джойнами..) через квери-билдеры в ORM


Query Builder перпендикулярен ORM. Можно делать ORM без Query Bulder, можно использовать Query Builder без ORM. Как следует из названия, он предназначен для сборки запросов по частям, например, когда вид запроса зависит от каких-то условий. В моем уроке это упомянуто.

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

> Структура базы, связи между таблицами описывается внутри doc-комментов!


А как ты бы хотел их описывать? В доктрине есть другие варианты + можно написать свой парсер.

В общем читай мой урок.
#431 #929230
Есть дата в формате 02/14/2017, как перевести её в количество секунд прошедших с 1970 года. Только без математических расчётов, есть функция которая преобразует дату в обычном формате в unix формат, я что-то не могу найти
929232
#432 #929232
>>929230
А, всё нашёл уже, извиняюсь
#433 #929236
>>927790

Удобнее наверно сделать хороший редактор, где все вопросы на одной странице. Сам подумай, в тесте может быть 10-50 вопросов. И может потребоваться их переставлять как-то.

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

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

>>927549

Якорь не отправляется на сервер.

> Или все постом делать, что бы урл не трогать?


Отправка POST запроса вроде меняет URL.

>>927449

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

>>927389

Нельзя использовать составные выражения при инициализации поля. Но их можно поставить в конструкторе.

>>927382

У тебя в объекте не заполнено поле answers. Потому там лежит по умолчанию null. И при попытке сделать по нему цикл foreach происходит ошибка.

Также, у тебя очень странный код, у тебя объекты Questions создаются в 2 местах кода, причем в одном из них они осле этого никак не используются.
#433 #929236
>>927790

Удобнее наверно сделать хороший редактор, где все вопросы на одной странице. Сам подумай, в тесте может быть 10-50 вопросов. И может потребоваться их переставлять как-то.

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

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

>>927549

Якорь не отправляется на сервер.

> Или все постом делать, что бы урл не трогать?


Отправка POST запроса вроде меняет URL.

>>927449

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

>>927389

Нельзя использовать составные выражения при инициализации поля. Но их можно поставить в конструкторе.

>>927382

У тебя в объекте не заполнено поле answers. Потому там лежит по умолчанию null. И при попытке сделать по нему цикл foreach происходит ошибка.

Также, у тебя очень странный код, у тебя объекты Questions создаются в 2 местах кода, причем в одном из них они осле этого никак не используются.
#434 #929243
>>927087

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

>>927086

Язык, DOM и тд. У нас в ОП посте есть задачки.

>>926913

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

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

>>926847

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

>>926829

Обновление страницы не меняет URL. надо делать редирект.

>>926760

В Yii вообще немало любителей делать "не как все". Они вроде табы до сих пор используют, и кучу вещей переизобрели.

>>926725

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

>>926675

Да, лучше отказаться.

>>926674

Это наследие прошлых версий. Делать так неправильно.

>>926669

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

>>926597

Сначала стоит освоить основы: ООП, MVC, формы, таблицы. У нас есть задача про студентов, помогающая это изучить.

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

В твоем коде есть проблема: ты обращаешься к элементу массива $_GET[amount'], но даже не проверил, есть ли такой элемент в нем вообще.

Число 5000 не надо копипастить, а надо вынести в переменную.
#434 #929243
>>927087

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

>>927086

Язык, DOM и тд. У нас в ОП посте есть задачки.

>>926913

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

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

>>926847

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

>>926829

Обновление страницы не меняет URL. надо делать редирект.

>>926760

В Yii вообще немало любителей делать "не как все". Они вроде табы до сих пор используют, и кучу вещей переизобрели.

>>926725

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

>>926675

Да, лучше отказаться.

>>926674

Это наследие прошлых версий. Делать так неправильно.

>>926669

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

>>926597

Сначала стоит освоить основы: ООП, MVC, формы, таблицы. У нас есть задача про студентов, помогающая это изучить.

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

В твоем коде есть проблема: ты обращаешься к элементу массива $_GET[amount'], но даже не проверил, есть ли такой элемент в нем вообще.

Число 5000 не надо копипастить, а надо вынести в переменную.
#435 #929253
>>929154
>>929156

Ответь сначала на такие вопросы (если знаешь ответ, если нет, так и пиши):

- что такое сессия?
- где хранятся помещенные в нее данные?
- если сессий на сервере много, как понять, какая из них соответствует какому пользователю? Ну то есть пришел HTTP-запрос от браузера, как понять. какая сессия соответствует этому пользователю?
- что делает sesion_start()?
- кто и когда заполняет массив $_SESSION? Что происходит с ним после завершения скрипта?
- как удаляются данные сессий, если они долго не используются?

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

>>929171

Все пишут, а ты померяй. Ну и настрой правильно.

>>929177

Единых официальных нет, но есть рекомендации PSR-1 и PSR-2 которые поддерживают крупные фреймворки и многие проекты. Смотри второй пост треда.

>>929186

Никак.

>>929197

не проще этот ключ явно передавать как GET- или POST-параметр?

Время на клиенте и на сервере может не совпадать. У меня сегодня телефон почему-то на 2 часа отстал.

>>929199

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

Проще наверно вводить какие-то лимиты и искать подозрительных пользователей которые методично загружают страницу за страницей.
#435 #929253
>>929154
>>929156

Ответь сначала на такие вопросы (если знаешь ответ, если нет, так и пиши):

- что такое сессия?
- где хранятся помещенные в нее данные?
- если сессий на сервере много, как понять, какая из них соответствует какому пользователю? Ну то есть пришел HTTP-запрос от браузера, как понять. какая сессия соответствует этому пользователю?
- что делает sesion_start()?
- кто и когда заполняет массив $_SESSION? Что происходит с ним после завершения скрипта?
- как удаляются данные сессий, если они долго не используются?

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

>>929171

Все пишут, а ты померяй. Ну и настрой правильно.

>>929177

Единых официальных нет, но есть рекомендации PSR-1 и PSR-2 которые поддерживают крупные фреймворки и многие проекты. Смотри второй пост треда.

>>929186

Никак.

>>929197

не проще этот ключ явно передавать как GET- или POST-параметр?

Время на клиенте и на сервере может не совпадать. У меня сегодня телефон почему-то на 2 часа отстал.

>>929199

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

Проще наверно вводить какие-то лимиты и искать подозрительных пользователей которые методично загружают страницу за страницей.
#436 #929263
>>929202

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

> да, кстати, а зачем корзине быть нестатической?


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

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

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

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

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

Я всегда стараюсь объяснить, почему кто-то не прав, чтобы из этого была польза и люди учились сами мыслить аналогично. А не заучивали догмы, не понимая, почему так, а не иначе.
#437 #929312
>>929219

>Это тестовое задание? Можно через циклы, можно через array-walk_recursive или рекурсивные итераторы по массиву.


Не тестовое, аутирую с вордпрессом. Мне требовалось убрать пробелы у значений перед отправкой в бд. Сделал через вложенный foreach, но думаю, что сделал какое-то говно и так никто не пишет.
#438 #929349
Антоши, а можете накидать литературы по PHP вроде той, что сейчас висит в шапке, но актуальной для 2016-17 годов?
929372
#439 #929360
>>929178

>list_selector($table, $column, 'list_id', 'list_name');


Там как раз и есть две функции. Одна работает с таблицей, а list_selector только формирует список, используя столбец $column в таблице $table и формируя div с параметрами id и name, list_id и list_name, в который его и помещает.

DOM пока для меня сложновата, но я посмотрю.
#440 #929372
>>929349
С тех пор ничего не изменилось же. Новые фичи в php7 и фреймворки появились, но основы от этого не меняются. Что в шапке, вполне актуально, а для новых фич качни любую книгу, где php7 разбирается.
#441 #929448
У меня вопрос по MySQL

Необходимо создать таблицу из 2 столбцов
Жанр - Количество

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

Всего у меня 4 таблицы:
Книги:
id - название - имя автора

Авторы:
id - Имя - Фамилия

Жанры:
id - название

Связка жанров и книг:
idКниги - idЖанра

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

Оформить запрос не получается. Прошу помощи.
http://pastebin.com/6C2W5zZ1 - структура бд
#441 #929448
У меня вопрос по MySQL

Необходимо создать таблицу из 2 столбцов
Жанр - Количество

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

Всего у меня 4 таблицы:
Книги:
id - название - имя автора

Авторы:
id - Имя - Фамилия

Жанры:
id - название

Связка жанров и книг:
idКниги - idЖанра

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

Оформить запрос не получается. Прошу помощи.
http://pastebin.com/6C2W5zZ1 - структура бд
929453929793
#442 #929453
>>929448
Я бы очень рад тебе помочь, но я не понял самого вопроса, в чем у тебя проблема то? Это тестовая/учебная задача, или у тебя траблы с реальным проектом?

Тебе нужно селект написать? В котором будет посчитано сколько книг в каждом жанре?
Наверное как-то так
SELECT genres, COUNT(*) FROM books GROUP BY genres;
929485
Yii2 Session #443 #929460
Привет анончики. Хочу запилить мультиязычность наYii.
Пробема в том что не знаю как организовать проверку кук и запись в сессии на всех страницах.
Сперва нужно по дефолту (при заходе на любую страницу сайта) повесить куку с дефолтным языком и записать дефолтную сессию, а при выборе другого языка - поменять.
Очевидно, мне не хочется проверять существование кук и сессий в каждом экшене, как это сделать в одном месте?
Может есть варик через конфигурацию компонентов?
929470929609
#444 #929470
>>929460

>при заходе на любую страницу сайта


то есть при вызове любого контроллера?

Тогда в конструкторе родительского контроллера или что там у вас используется.
929474
#445 #929474
>>929470
по сути мультиязычность нужна только на стороне клиента. так что на основном контроллере в папку frontend. Там сейчас 10 страниц, очень не хочется вешать на каждую проверку
Отвечая конкретно на вопрос, при вызове контроллера SiteController (я и не парился его переназывать ) проводить проверку сессий и кук
929487
#446 #929485
>>929453
Для себя делаю, учусь.

да, нужен селект. Списки жанров и книг в разных таблицах.
Они связаны между собой проходной таблицей.
То есть вместо того, чтобы в одну ячейку писать id жанров, я сделал табличку.
#447 #929487
>>929474
Прости бро, но я в глаза ниразу не видел yii, просто основываясь на опыте пытаюсь тебе дать совет.

> Там сейчас 10 страниц, очень не хочется вешать на каждую проверку


Что такое страницы? Страница собой представляет контроллер? Или ты методы одного контроллера имеешь ввиду?

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

http://ideone.com/fz6Jg3
929490
#448 #929490
>>929487
спасибо, я и не подумал
#449 #929503
Ребята а правда что правильно читать не пэхэпэ и даже не пиашпи а фипи?
929506929523929769
#450 #929506
>>929503
пыха
#451 #929523
>>929503
Правильно будет похапе
#452 #929550
https://jsfiddle.net/b073aLb5/
Что не так?
929551
#453 #929551
>>929550
Простите, забыл наследование сделать https://jsfiddle.net/b073aLb5/1/
199 Кб, 1920x1031
76 Кб, 1059x746
#454 #929560
Помогите пожалуйста.
929562929564929570
#455 #929562
>>929560

>he buys new car



Не благодари
929564929568
198 Кб, Webm
#456 #929564
>>929560
Из функций значения уже возвращать не нужно?
>>929562
кек
929566
#457 #929566
>>929564

>Из функций значения уже возвращать не нужно?



Как это? Т.е. выводить результат функций командой echo нельзя?
929569
#458 #929568
>>929562

a new car

Хотя я в артиклях довольно слаб, но предложения без артиклей сразу выдают иностранца.
#459 #929569
>>929566
Можно, но ты ниже используешь эхо на переменной, которая не существует в этой зоне видимости. И вообще это пиздарики. Куча каких-то эхо, наркоманские названия переменных, $bd++ вместо $db++.
929574
#460 #929570
>>929560
это тяжелый случай, у тебя функция ничего не ретернит, нигде не вызывается и ты к внутренним переменным функции обращаешься в глобальном коде.

Попробуй понять вот этот пример:
http://ideone.com/VnlelH
929574929576
#461 #929574
>>929569
>>929570
Я вас понял, поскольку функция это отдельный мир кода, так сказать, измерение, и все переменные внутри функции внешний мир не видит, для него они не существуют.
Следовательно, что-бы вызвать результат функции, нужно echo название_функции написать?
929577929579929644
#462 #929576
>>929570
https://www.codewars.com/kata/5839edaa6754d6fec10000a2/train/php
На примере моей задачи. Вот, я её так решил, в общем.

Кроме того, что я неправильно вызвал функцию, я решил её правильно?
13074 Кб, Webm
#463 #929577
>>929574
Почему ты так любишь лепить везде эхо? Сделай return в функции, потом вызови ее в переменную и когда все уже будет готова можешь принтить.
929583
#464 #929579
>>929574
Нет, ты можешь и внутри функции эхо написать, но ты ВЫЗОВИ СУКА ЕЁ ГДЕ-НИБУДЬ В КОДЕ
то что у тебя там написано
function hueta($huitka) {
....hueta code
}
- это только ОПИСАНИЕ ФУНКЦИИ, понимаешь? Ты тут лишь показываешь языку как она должна работать.

Потом ты в своём коде где тебе нужно пишешь
hueta($var);
и она выполняется

Блядь пиздец, пойду лучше в овервотч поиграю.
929583
#465 #929583
>>929579
>>929577
Короче пойду перечитывать инфу по функциям.
Спасибо.
929596
#466 #929586
Куда делся JS тред? Как найти?
#467 #929596
929607930386
6573 Кб, Webm
#468 #929607
>>929596
Ну и зачем ты все разжевал? А? А? А? А? А? А? А? А?
Давай удочку, а не рыбу, еба. Когда сам роешь инфу по проблеме, то в конце ты чувствуешь, что заебись ваще чотко все порешал. А если тебя тычут носом в решение, то это хуйня.
929608930386
#469 #929608
>>929607
Я и дал ему удочку, я же не за него его говнокод переписал. А так тоже самое блядь описал в 10 строках, что и в любом учебнике.
#470 #929609
>>929460
Тебе нужны транслейты слов для Yii:t или переводы из базы?
#471 #929612
>>929134
>>929132
Спасибо за ответы ! Началось хоть какое-то движение.
Сейчас имею вот такой недокод: http://ideone.com/fLnxX3

Я все равно не могу понять ситуацию с кофе и страницами.
В моем нынешнем решении я копирую несколько раз код функции getDrunkCofee, меняя только одно значение. Этого ведь можно избежать, сделав кофе и страницы свойствами сотрудника, разве не так ?
Может я не правильно понял условия, ведь потребление кофе и количество страниц зависит только от того, является ли сотрудник боссом ? Или при повышении ранка повышается потребление кофе и производство страниц ?
929622929653929658
#472 #929622
>>929612

>>>929134


>>>929132


И еще, кто-то может подсказать, в какую сторону читать: >>929612
В голове возникла мысль !
А может быть в общем классе "сотрудник" полностью описать функцию просчета, с использованием instanceOf, и выдавать результаты в зависимости от профессии(типа, класса) ?
929656
#473 #929644
>>929574

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

Конструкция такого вида

function somehing($x) {
.....
return $y;
}

создает новую функцию (но код в ней не выполняется, просто PHP теперь знает, что такая функция есть). В данном случае создается функция с названием something, которая принимает один аргумент, обозначенный переменной $x и возвращает что-то в конце своего выполнения с помощью return. return это специальная команда, которая выходит из функции, и возвращает указанное после нее значение.

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

something(10);

Вот эта строчка вызвает функцию и выолняет записанный в ней код. При этом в функции будет доступна переменная $x, равная 10. Если мы хотим сохранить результат, который вернет функция с помощью return, мы должны использовать переменную:

$result = something(10);

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

function getSquareSum($a, $b) {
return $a * $a + $b *$b;
}

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

Теперь посчитаем с ее помощью сумму квадратов чисел 3 и 4:

$sum = getSquareSum(3, 4);
echo $sum; // 25

Можно обойтись без промежуточной переменной:

echo getSquareSum(5, 6); // 61

Функция может быть без аргументов (ничего не принимать на вход) и может ничего не возвращать (то есть в ней нет команды return).

И да, функция не видит внешние переменные. Все, что ей нужно, ты должен явно передать через аргументы. Это делает код более логичным, сразу по заголовку видно, что нужно передать функции для ее работы.
#473 #929644
>>929574

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

Конструкция такого вида

function somehing($x) {
.....
return $y;
}

создает новую функцию (но код в ней не выполняется, просто PHP теперь знает, что такая функция есть). В данном случае создается функция с названием something, которая принимает один аргумент, обозначенный переменной $x и возвращает что-то в конце своего выполнения с помощью return. return это специальная команда, которая выходит из функции, и возвращает указанное после нее значение.

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

something(10);

Вот эта строчка вызвает функцию и выолняет записанный в ней код. При этом в функции будет доступна переменная $x, равная 10. Если мы хотим сохранить результат, который вернет функция с помощью return, мы должны использовать переменную:

$result = something(10);

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

function getSquareSum($a, $b) {
return $a * $a + $b *$b;
}

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

Теперь посчитаем с ее помощью сумму квадратов чисел 3 и 4:

$sum = getSquareSum(3, 4);
echo $sum; // 25

Можно обойтись без промежуточной переменной:

echo getSquareSum(5, 6); // 61

Функция может быть без аргументов (ничего не принимать на вход) и может ничего не возвращать (то есть в ней нет команды return).

И да, функция не видит внешние переменные. Все, что ей нужно, ты должен явно передать через аргументы. Это делает код более логичным, сразу по заголовку видно, что нужно передать функции для ее работы.
#474 #929653
>>929612

Копировать код функции 4 раза - плохая идея. Это затрудняет изменение программы и говорит о неправильном подходе.

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

Давай подумаем: в 4 классах-профессиях логика расчета потребления кофе - разная или одинаковая? Она одинаковая, единственное различие - это один коэффициент.

Следовательно, нам нужно не 4, а одна функция. Мы объявляем ее в базовом классе, и она потому будет доступна во всех потомках.

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

protected function getBasicCoffeeConsumption()
{
return 10;
}

Но тут встает другая проблема:

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

Обе этих проблемы решают абстрактные методы. В базовом классе мы делаем абстрактный метод:

abstract protected function getBasicCoffeeConsumption();

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

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

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

Есть ли в моем подходе недостаток: да, есть. Он предполагает, что во всех профессиях будет использоваться один и тот же метод, формула расчета кофе. Если это не так, то этот мой подход будет плохо работать (попробуй подумать, почему).
#474 #929653
>>929612

Копировать код функции 4 раза - плохая идея. Это затрудняет изменение программы и говорит о неправильном подходе.

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

Давай подумаем: в 4 классах-профессиях логика расчета потребления кофе - разная или одинаковая? Она одинаковая, единственное различие - это один коэффициент.

Следовательно, нам нужно не 4, а одна функция. Мы объявляем ее в базовом классе, и она потому будет доступна во всех потомках.

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

protected function getBasicCoffeeConsumption()
{
return 10;
}

Но тут встает другая проблема:

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

Обе этих проблемы решают абстрактные методы. В базовом классе мы делаем абстрактный метод:

abstract protected function getBasicCoffeeConsumption();

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

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

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

Есть ли в моем подходе недостаток: да, есть. Он предполагает, что во всех профессиях будет использоваться один и тот же метод, формула расчета кофе. Если это не так, то этот мой подход будет плохо работать (попробуй подумать, почему).
#475 #929656
>>929622

> А может быть в общем классе "сотрудник" полностью описать функцию просчета, с использованием instanceOf, и выдавать результаты в зависимости от профессии(типа, класса) ?


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

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

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

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

То есть код вида:

если класс == Менеджер то...
если класс == Инженер то...

противоречит идеям ООП о разделении кода на классы. Ты выносишь код, относящийся к классу, из класса наружу.
#476 #929658
>>929612

> public function getDrunkCofee()


>{


> return 'nothing'; //заглушка


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

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

> abstract class AbstractEmployee


> private $baseRate;


Перечитай в чем разница между protected и private.

> protected $baseRate = 500;


Нет гарантии, что все потомки укажут значения поля. Тут надо использовать абстрактный метод для получения этого числа.
77 Кб, 600x800
#477 #929708
Аноны, тупые вопросы за 300. У меня есть приложуха которая шлет гет запрос на получение списка, еще есть пост запрос на добавление данных и редактирование и есть еще удаление(как его слать кстати). Так вот на сервере эти запросы обрабатывает один файл, но разные функции? И получается для разных пост запросов надо разные пхп файлы?
31 Кб, 500x480
#478 #929712
Напомню Опу о себе.
>>924484
>>927560
#479 #929740
Может кто-нибудь скинуть решение задачи на проверку телефона из шапки? Я ее ниасилил
#480 #929741
Извиняюсь что немного не по теме.
- Есть один сайт на php, который возможно мне придется админить/переписывать и тд.
- в php ноль, но знаю питон, не слишком хорошо, но 99% проблем могу решить сам, не умоляя слезно на всех форумах сразу.
Вопрос в том как мне поступить, учить php и дербанить существующий сайт или писать на питоне с нуля? И сколько нужно просить за такую работу (сайт на питоне), учитывая что я живу мухсранске, нищеброд без гроша и фирма мелкая.
Извиняюсь за сумбурность
#481 #929745
Спасибо ОПу за задачки и обучение программирование на пыхе, а также анонам из версткотредов. Я переехал в ДС и нашел работу. Как я вас могу отблагодарить? Могу подарить тортик :3
929763
#482 #929747
Кстати, почему аякс в хроме только методом ГЕТ передает запросы на сервер?
929771
#483 #929753
Прятать стили в тэге стайл прямо в середину хтмл страницы - ведь совсем зашквар? Не первый раз такое встречаю, прямо у меня на работе есть такой говнокодер.
929775929808
#484 #929763
>>929745
Ты няшный?
929782
#485 #929769
>>929503
пи-а-пи
#486 #929771
>>929747
Так переключи на post.
929781
#487 #929775
>>929753
Можно просто в style у элементов же прописывать.
<div style="background-image: url(../images/vasya.gif);background-repeat:no-repeat; background-position:50% 50%;"> background-position:50% 50% </div>
929783929802
#488 #929781
>>929771
пост запросы не передаются аяксом на сервер в хроме, только геты. я и спрашиваю почему?
#489 #929782
>>929763
очень я даже тяночка ))
929789
#490 #929783
>>929775
Я знаю, но они именно ебашут <style> в середине html и это меня ужас как бесит. Оправдывается разраб тем, что ну стили же легче будет найти потом)) т.е. ему легче искать стили к странице, в которой он их прям в середине заебашил. ппц
#491 #929789
>>929782
Тогда не надо.
#492 #929793
>>929448
Лучше тебе делать отдельно таблицу для книги и отдельную для жанра.
929806
#493 #929802
>>929775
Нахуй так сложно, вот так надо:
<body bgcolor="green" background="fon.bmp">
<center>
<u>
<font color="red">Надпись, охуеть</font>
</u>
</center>
</body>

И никакие cssы в середине страницы не нужны.
#494 #929806
>>929793
Я так и сделал.
Даже пастбин с моей базой сделал.
Жанры и книги связаны между собой через промежуточную таблицу.
Нужно придумать, как оформить Селект, чтобы было
Жанр - количество книг в жанре.
929966
#495 #929808
>>929753
Дай пизды ему, епта
#496 #929965
Есть несколько кнопок radiobutton, как среагировать в jQuery на клик по любой из них. Класс и id не могу поставить каждой кнопке свой, так как они выводятся динамически.
929992
#497 #929966
>>929806
А что там оформлять? Селект иннер жойн и поехал.
930157
#498 #929992
>>929965
try this
$(кнопка).он("клик",функция() {
$(this) = self;
...
}
929993
#499 #929993
>>929992
self/this местами поменять*
туплю утром.
#500 #930105
Возможно тупой вопрос, но всё же. Представим ситуацию: у меня есть сделанный мной сайт, который активно работает с моей же базой данных. Сайт лежит в папочке, к которой прописаны пути в настройках апача. Так же есть база данных и конкретно phpmyadmin для неё, который допустим висит на локалхосте. Теперь я хочу чтобы всё это моё дело вышло в свет. Беру хостинг, заливаю туда папочку своего сайта и... Что делать с базой? Где она должна быть? Она отдельно хостится? Я ни разу не выкидывал в продакшн проекты.
930158
#501 #930134
PHPч, ПАМАГИ!
Помогите оценить время и стоимость следующей работы:
Нужен сайт - обменник криптовалюты
Предполагается:
1. Сверстать сайт под популярные браузеры из небольшого количества страниц без излишеств, никаких WebGL, Unity и прочих монстросити, но при этом не совсем голый html, допустим используется какой нибудь bootstrap
2. Настроить взаимодействие с некоторыми банками для транзакций (у некоторых, вполне возможно, есть API для php, у некоторых может и нет)
3. Настроить взаимодействие кошельков с криптовалютой для транзакций.
4. Настройка БД для логгирования различных действий (транзакции-шманзакции)
5. Смазать всё это дело защищенным соединением (HTTPS все дела)

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

Хочу услышать большое количество времени, сколько при таких условиях ушло бы времени на разработку именно у ТЕБЯ и сколько бы денег в качестве оплаты запросил именно ТЫ.
930163930486930920
#502 #930157
>>929966
Ну вот, у меня не получается это сделать.
#503 #930158
>>930105
Ну что у тебя за хостинг.
Например обычные веб-хостинги предоставляют панель управления. Такой же phpmyadmin.
Делаешь бекап своей базы, заливаешь его на хостинг.
Прописываешь пути подключения и все.
#504 #930163
>>930134
Смотря сколько секунд потратил на работу. Стандартный прайс для фрилансера 300к в секунду.
930164
#505 #930164
>>930163
А-а-атличная шутеечка, братан.
930166
#506 #930166
>>930164
А какого ты ответа ждешь? Чтобы я тебе сказал сколько ты должен брать за джобу? Ну пиздец, чо. Требуй с него 1 дошик, если долго будешь делать, а есть быстро, то два.
930167
#507 #930167
>>930166

>Чтобы я тебе сказал сколько ты должен брать за джобу?


Я попросил просто примерную стоимость описанной работы. Я же не прошу тут бухгалтерские расчёты вести и проводить серьёзную аналитику. Просто примерная цена или диапазон ну без фантазий конечно, типа 300 мильёновтыщ в секунду/доширак и свистнуть в хуй исходя из вышеописанных условий.
930172
#508 #930172
>>930167
Пиздос, ты знаешь всю ситуацию, представляешь себе заказчика и не выкладывая никакой инфы по своим скилам, платежеспособности заказчика и примерном времени выполнения тобой джобы, спрашиваешь у анона сколько тебе заломить с заказчика.
Если ты считаешь, что заказчик может соскочить, и он из страны, где о рублях не слыхали, то стартуй из расчета 15 баксов в час.
Но это совет в стиле: 'Секс переоценен, я на дваче читал'. Только ты владеешь инфой и ты можешь трезво оценить всю хуйню. Короче я заебался писать, проси у него 3 дошика.
930176
#509 #930176
>>930172
Отлично, так и запишем. "Три дошика".
#510 #930216
>>926220

>>Doctrine


>Даже после прочтения сложных определений в гугле не до конца понимают что это такое. Оно заменяет Mysql или любую другу БД?
На этот вопрос отвечать не нужно - ознакомился чуть подробней.
930920
#511 #930220
Товарисчи, до сих пор ебусь с задачкой про компанию Вектор.
Вроде бы основную логику сделал, сейчас с выводом информации на экран мучаюсь
http://ideone.com/3uQv9G - вот код
Вопросы:
1) Какого хера мне выдает ошибку "PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() in /home/z65BF4/prog.php:200" ??? Делал ведь предыдущую задачу про эту компанию, с этими же функциями и всё работало...

2) Как бы так красиво, в ООП стиле оформить вывод информации на экран и сам экшон (заполнение компании департаментами, тех сотрудниками и подсчет всего, что необходимо по условиям задачи) ?
930234930244930689
16709 Кб, Webm
#512 #930234
>>930220
1) mb_internal_encoding('utf-8');
Но ideone выебывается и всеравно выдает какую-то хуйню. Проверил на сервере - все работает.

2)Попробуй выводить рамку из черточек и слешей. Реализация примерно такая:

function padRight($text, $col)
{
return $text.str_repeat(' ',$col-mb_strlen($text));
}
function padLeft($text, $col)
{
return str_repeat(' ',$col-mb_strlen($text)).$text;
}

function printData($company, $headline)
{
$col1 = 20;
$col2 = 8;
$col3 = 12;
$col4 = 12;
$col5 = 12;
$col6 = 12;
$col7 = 50;
if($headline == 0){
echo padRight("Департамент", $col1) .
padLeft("сотр.", $col2) .
padLeft("тугр.", $col3) .
padLeft("кофе", $col4) .
padLeft("стр.", $col5) .
padLeft("тугр./стр.", $col6) . "\n" .
str_repeat("==", 40) . "\n";
}
И далее через foreach
padRight(имя департамента, $col1)
padLeft(количество чего-то, $col2-7)
16709 Кб, Webm
#512 #930234
>>930220
1) mb_internal_encoding('utf-8');
Но ideone выебывается и всеравно выдает какую-то хуйню. Проверил на сервере - все работает.

2)Попробуй выводить рамку из черточек и слешей. Реализация примерно такая:

function padRight($text, $col)
{
return $text.str_repeat(' ',$col-mb_strlen($text));
}
function padLeft($text, $col)
{
return str_repeat(' ',$col-mb_strlen($text)).$text;
}

function printData($company, $headline)
{
$col1 = 20;
$col2 = 8;
$col3 = 12;
$col4 = 12;
$col5 = 12;
$col6 = 12;
$col7 = 50;
if($headline == 0){
echo padRight("Департамент", $col1) .
padLeft("сотр.", $col2) .
padLeft("тугр.", $col3) .
padLeft("кофе", $col4) .
padLeft("стр.", $col5) .
padLeft("тугр./стр.", $col6) . "\n" .
str_repeat("==", 40) . "\n";
}
И далее через foreach
padRight(имя департамента, $col1)
padLeft(количество чего-то, $col2-7)
930244
8731 Кб, Webm
#513 #930244
>>930220
>>930234
Сорян, не сразу понял второй вопрос.
Можно создать отдельный класс для заполнения сотрудниками. А выводить на экран лучше, создав функцию по типу той, что я описал выше.
#514 #930322
>>919065

https://jsfiddle.net/akua0tr6/

Переделал 4ую js задачу с селекторами, ушел дальше ковырять MVC сапера. Вот твой предыдущий ответ из прошлого треда, если последний утонет: http://pastebin.ru/a1sx1IT2 , предыдущее решение: https://jsfiddle.net/82228qnq/
930323930686
#515 #930323
>>930322

Она по прежнему в легком варианте, если что.
5 Кб, 225x225
#516 #930337
http://ideone.com/oZw7mB - Айфон в кредит.
Доброго времени суток, я тут ебусь с задачей про айфон в кредит и не могу понять какого хуя оно что-то плюсует к долгу, вместо того, чтобы отнимать от него месячную стоимость.
Это происходит с разными данными. Например, с оригинальными данными 40к кредит, 5% процент и 1к комиссия, 5к месячная плата считает как надо, пробовал числа по-меньше - считает то нормально, то опять плюсует неизвестные числа. Сейчас в ней поставлены другие значения, а не оригинальные, дабы было понятно что за хуйня.
Может кто знает в чём ошибка и где я обосрался, помогите.
930340930686
#517 #930340
>>930337
Блять, там оригинальные данные.
Те что я тестирую, вот http://ideone.com/sgq4lu
930360
#518 #930360
>>930340

for (months=0;credit>0;months++)
{
credit = credit*percent+service-payment;
if (credit<payment) {
spent += credit;
months++;
break
} else { spent+= payment}
так же проще. если я не проебался нигде, еду с универа только
930686
49 Кб, 773x544
#519 #930386
>>929607
>>929596
Вот, спасибо, я понял.
930686
#520 #930486
>>930134
Я б сделал примерно за 2-3 месяца, может меньше. Но я не начинающий. Если хуефрилансера с сайта нанять, то может и на год растянуться и забаговано все будет. Самая сложная часть криптовалюты и как с ними взаимодействовать, остальное достаточно просто и стандартно. Запросил бы 10к баксов.
74 Кб, 1280x720
#521 #930538
Помогите установить Git, мне на курсах скинули инструкцию по установки, но я ничего не понял.
Умоляю, помогите
Кто-то работал с ним?
930547
#522 #930547
>>930538
sudo apt install git
Шелл для спермы можешь нагуглить, их много. Главное GUI не используй, хотя бы первое время. Учись работать с консолью.
930588930644
#523 #930554
Правильно ли понимаю, что по принципу Лисков, если наследник переопределяет не абстрактный метод, то он обязан вызвать родительский? Понял принцип так: "Вместо родителя всегда можно подставить наследника и код должен работать как и прежде".
Заодно напомню о скидках: https://ideone.com/IscxDU
930593930627930671
45 Кб, 640x480
#524 #930588
>>930547

>Windows: C:\Users\{LoginName} - Открываем контектное меню и выбираем пункт Git Bash


Что за LoginName?можешь дать почту или линк вк?то я тупой
930627
#525 #930593
>>930554
По принципу Лискова ты не можешь менять методы в классах-детях, которые были определены в родителе. Иначе ребенок уже не соответствует родителю, и ты не можешь заменить им родителя. Весь смысл наследования теряется. Конструктор к примеру если определен в родителе с параметрами, то он такой же и в детях, нельзя его переопределять под другие параметры.
930595930609930627
#526 #930595
>>930593
К тому же это фукнциональности касается, да. Если к примеру был метод turnPage($number), который менял страницу, то если в ребенке у тебя turnPage не меняет страницу, а делает что-то другое, то это нарушение по Лискову.
#527 #930609
>>930593

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


И правда.

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


Выходит, что parent::__construct() это плохо? Набросал простой пример, когда, вроде бы, принцип Лисков не нарушается, даже невзирая на то, что конструктор в наследнике переопределён: https://ideone.com/JBf2VC
930625930631930643
#528 #930625
>>930609
Нет, почему? Если у тебя __construct в ребенке принимает все те же параметры, что и parent::construct, то можно расширять. Это соответствует open-closed principle - ты не меняешь parent, а расширяешь его функциональность в ребенке. При этом функциональность parent остается нетронутой, ведь его __construct работает так же как и прежде.
930626930627
#529 #930626
>>930625
Сорь, непонятно написал - функциональность parent:__construct остается той же в ребенке, значит лисков и open-closed principle выполняются.
#530 #930627
>>930588

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

Если ты не используешь экран входа при загрузке, то скорее всего это что-то вроде c:\Users\Администратор

Если не знаешь точно, зайди в c:\Users и посмотри, что там есть.

>>930554

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

>>930593

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

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

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

- http://al-zatv.livejournal.com/52115.html
- http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html

>>930625

К конструктору требование совместимости не относится. Так как конструктор никто не вызывает на уже созданных объектах. Принцип Лисков говорит о совместимости созданных объектов, а не классов.
#530 #930627
>>930588

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

Если ты не используешь экран входа при загрузке, то скорее всего это что-то вроде c:\Users\Администратор

Если не знаешь точно, зайди в c:\Users и посмотри, что там есть.

>>930554

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

>>930593

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

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

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

- http://al-zatv.livejournal.com/52115.html
- http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html

>>930625

К конструктору требование совместимости не относится. Так как конструктор никто не вызывает на уже созданных объектах. Принцип Лисков говорит о совместимости созданных объектов, а не классов.
930634930646
#531 #930631
>>930609
В твоем примере лисков как раз нарушен - ты в ребенке принимаешь другое число параметров чем в родителе. Теперь ситуация - ты где-то юзаешь ребенка, а понадобилось заменить родителем. Ты этого сделать больше не сможешь - вызовет ошибку из-за несоответствия количества параметров.
930635
#532 #930633
Обратите внимание на формулировки например из статьи: http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html

> ..если для каждого объекта o1 типа S существует объект o2 типа T такой, что для всех программ P, определенных в терминах T, поведение P не изменяется при замене o2 на o1, то S является подтипом (subtype) для T.



> Говорят, что экземпляр наследника также ЯВЛЯЕТСЯ экземпляром базового класса, что выражается в возможности использования экземпляров наследника везде, где ожидается использование базового класса.



Видите, речь идет об объектах. Условно говоря, если у вас есть функция

function doSmth(A $a) { ... }

Что это значит? Значит, что эта функция должна обращаться только к полям и методам, которые есть в классе A.

Но вы в нее можете передать объект класса B, наследующегося от A, и все должно работать. То, что у него другой конструктор - это не проблема, так как вызываете вы его за пределами функции. Сама функция констурктор у $a не вызовет, так как это уже созданный объект.
930638
#533 #930634
>>930627

>К конструктору требование совместимости не относится. Так как конструктор никто не вызывает на уже созданных объектах. Принцип Лисков говорит о совместимости созданных объектов, а не классов.



Если создаешь объекты в цикле, и попал родитель и ребенок - будет ошибка. Тебе в каждом цикле придется смотреть, чтобы не создавался объект с 3 параметрами, а это уже кривой код. Код должен быть защищен от ошибок на уровне интерфейса.
930638930643
#534 #930635
>>930631

Принцип Лисков относится к уже созданным объектам, и не распространяется на конструктор.
#535 #930638
>>930634

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

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

- https://ru.wikipedia.org/wiki/Принцип_подстановки_Барбары_Лисков
- http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html
930639930658
#536 #930639
>>930638

>Саттер и Александреску в своём руководстве по использованию C++ для выражения этого принципа также используют фразу «подкласс не должен требовать от вызывающего кода больше, чем базовый класс, и не должен предоставлять вызывающему коду меньше, чем базовый класс».



В случае конструктора с расширеными параметрами подкласс как раз требует больше, чем базовый класс. Прямое нарушение.
930643
#537 #930643
>>930639

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

Если почитать исходное определение, то там речь идет о созданных объектах.

>>930634

Если ты имеешь в виду код вида $x = new $class, то это уже твоя проблема, что ты используешь такую конструкцию. Надо использовать if/else или switch ($class) ... и проблемы не будет. Или делать еще и конструкторы совместимыми.

>>930609

Принцип Лисков у тебя никак не нарушен. Объекты совместимы, а конструкторы не обязаны быть совместимыми.
930645
#538 #930644
>>930547

в чем прикол консоли? Гуи = тот же функционал, но быстрее и нагляднее же.
Чсв повышать? Симулировать линукс?
930679
#539 #930645
>>930643

>Принцип Лисков не распространяется на конструкторы.


В исходном определении речь идет о types и subtypes, которые по сути и есть классы и подклассы.

>We add to a type’s


specification a constraint clause that captures exactly those history properties
of a type that must be preserved by any of its subtypes, and we prove that each
of the type’s methods preserves the constraint.
930679930680
38 Кб, 927x240
151 Кб, 318x374
#540 #930646
>>930627
Cпасибо, что отвечаешь добрый анон), но тут ничего нет.
Может скинешь линк свой?
930679
#541 #930647
Есть курс по ПХП, можно выбрать дистанционные обучение и или в офисе с группой, что лучше выбрать?
Плюс с группой только то что английский есть
#542 #930658
>>930638

>http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html


На этой странице тоже пишут:

>Если посмотреть на исходное описание принципа подстановки в трудах Барбары Лисков, то можно с удивлением обнаружить, что оно полностью основано таких понятиях, как предусловия, постусловия и инварианты. Другими словами, описание этого принципа полностью основано на принципах проектирования по контракту:



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


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


>Производные классы не должны нарушать инварианты базового класса (инварианты базового класса и наследников суммируются)


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



Изменения конструктора нарушает эти правила, в частности первое.
#543 #930671
>>930554

> $matchedProducts = $discountResult->getMatchedProducts();


> $matchedPrice = $matchedProducts->reduce($pricesSum, 0);


> $totalPrice += $matchedPrice - $matchedPrice $discountResult->getPercent();


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

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

Метод getDiscountResult я бы переименовал в calculateDiscount/applyDiscount, так точнее получается.

> class CombinationDiscount implements DiscountInterface


> public function getDiscountResult(ProductCollection $notUsedProducts) {


...

> $notUsedProducts->removeProduct($matchedProduct);


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

Тем более название начинается с get...

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

А, и еще. А что, если в цикле тут название первого товара есть в списке, а второго нет?

> foreach ($this->names as $name) {


...

> if ($matchedProduct) {


> $notUsedProducts->removeProduct($matchedProduct);



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

> return new DiscountResult(new ProductCollection(), $this->percent);



Подозрительно, что ты не используешь тут переменную $productsUsedInThisDiscount, я решил выяснить, почему так, и нашел ошибку.

----

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

Предположим, что у тебя строка $productsUsedInThisDiscount->addProduct($matchedProduct); может выбросить исключение и выполнение методы getDiscountResult прервется. При этом переданный список будет уже изменен, и удаленные продукты при повторном вызове метода не будут участвовать в расчете скидок. То есть безопасность программы при возникновении исключения нарушена.

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

В этой статье https://habrahabr.ru/post/126374/ упоминается "строгая гарантия". Если бы метод не менял исходные данные, он бы реализовал "строгую" гарантию безопасности исключений.

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

----

> return new DiscountResult(new ProductCollection(), 0);


Если это часто встречается, стоило добавить конструктор DiscountResult::makeEmpty();

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

> $answer = (200 - 200 0.1) + (200 - 200 0.05) + (200 - 200 0.05) + (400 - 400 * 0.01) + 100;


> assert($answer == $c->calculateTotalPrice($discountCollection, $productCollection));


Вот тут есть момент, на который стоит обратить внимание. Дело в том, что в PHP дробные числа (float) хранятся приближенно (да еще и в двоичном виде, что требует преобразований в/из десятичной системы счисления), и операции с ними неточные. Ну например:

> var_dump(0.1 + 0.2); var_dump(0.1 + 0.2 === 0.3);


> double(0.3)


> bool(false)



o_0 как так?

Дело в том, что в двоичной форме число 0.3 - это бесконечная дробь. Там на самом деле 0.1 + 0.2 дают что-то вроде 0.29999999, просто при выводе оно округляется до красивого числа. А вот при сравнении видимо где-то в последнем разряде получается разница.

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

- https://habrahabr.ru/post/112953/
- http://floating-point-gui.de/errors/comparison/ (англ)
- тут еще интересный случай https://habrahabr.ru/post/247015/ (в PHP такое может возникнуть при сортировке по произвольному условию)

В общем, задача у тебя решена неплохо (кроме проблемы с измненением исходных данных), надеюсь, ты стал чуть лучше разбираться в ООП.
#543 #930671
>>930554

> $matchedProducts = $discountResult->getMatchedProducts();


> $matchedPrice = $matchedProducts->reduce($pricesSum, 0);


> $totalPrice += $matchedPrice - $matchedPrice $discountResult->getPercent();


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

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

Метод getDiscountResult я бы переименовал в calculateDiscount/applyDiscount, так точнее получается.

> class CombinationDiscount implements DiscountInterface


> public function getDiscountResult(ProductCollection $notUsedProducts) {


...

> $notUsedProducts->removeProduct($matchedProduct);


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

Тем более название начинается с get...

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

А, и еще. А что, если в цикле тут название первого товара есть в списке, а второго нет?

> foreach ($this->names as $name) {


...

> if ($matchedProduct) {


> $notUsedProducts->removeProduct($matchedProduct);



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

> return new DiscountResult(new ProductCollection(), $this->percent);



Подозрительно, что ты не используешь тут переменную $productsUsedInThisDiscount, я решил выяснить, почему так, и нашел ошибку.

----

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

Предположим, что у тебя строка $productsUsedInThisDiscount->addProduct($matchedProduct); может выбросить исключение и выполнение методы getDiscountResult прервется. При этом переданный список будет уже изменен, и удаленные продукты при повторном вызове метода не будут участвовать в расчете скидок. То есть безопасность программы при возникновении исключения нарушена.

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

В этой статье https://habrahabr.ru/post/126374/ упоминается "строгая гарантия". Если бы метод не менял исходные данные, он бы реализовал "строгую" гарантию безопасности исключений.

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

----

> return new DiscountResult(new ProductCollection(), 0);


Если это часто встречается, стоило добавить конструктор DiscountResult::makeEmpty();

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

> $answer = (200 - 200 0.1) + (200 - 200 0.05) + (200 - 200 0.05) + (400 - 400 * 0.01) + 100;


> assert($answer == $c->calculateTotalPrice($discountCollection, $productCollection));


Вот тут есть момент, на который стоит обратить внимание. Дело в том, что в PHP дробные числа (float) хранятся приближенно (да еще и в двоичном виде, что требует преобразований в/из десятичной системы счисления), и операции с ними неточные. Ну например:

> var_dump(0.1 + 0.2); var_dump(0.1 + 0.2 === 0.3);


> double(0.3)


> bool(false)



o_0 как так?

Дело в том, что в двоичной форме число 0.3 - это бесконечная дробь. Там на самом деле 0.1 + 0.2 дают что-то вроде 0.29999999, просто при выводе оно округляется до красивого числа. А вот при сравнении видимо где-то в последнем разряде получается разница.

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

- https://habrahabr.ru/post/112953/
- http://floating-point-gui.de/errors/comparison/ (англ)
- тут еще интересный случай https://habrahabr.ru/post/247015/ (в PHP такое может возникнуть при сортировке по произвольному условию)

В общем, задача у тебя решена неплохо (кроме проблемы с измненением исходных данных), надеюсь, ты стал чуть лучше разбираться в ООП.
936005
#544 #930679
>>930644

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

Вот простая книжка по git: https://git-scm.com/book/ru/v1

Не бойся командной строки, в ОП посте есть гайд по ней для начинающих.

>>930645

Можешь процитировать определение целиком? Я нахожу только такое:

https://en.wikipedia.org/wiki/Liskov_substitution_principle

> Subtype Requirement: Let \phi (x) be a property provable about objects x of type T. Then \phi (y) should be true for objects y of type S where S is a subtype of T.



Тут упомянуты объекты.

>>930646

Ну я вижу папку "Администратор". Думаю, надо зати в нее, щелкнуть правой кнопкой на пустом месте и выбрать "Git bash here " или как-то так.

Также git bash можно запустить через меню Пуск.

Если что, в ОП посте есть гайд по использованию консоли, советую изучить.

И в след. раз пиши больше подробностей:

- ссылку на гайд
- что ты сделал
- что не получилось

А то угадывать приходится.
#544 #930679
>>930644

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

Вот простая книжка по git: https://git-scm.com/book/ru/v1

Не бойся командной строки, в ОП посте есть гайд по ней для начинающих.

>>930645

Можешь процитировать определение целиком? Я нахожу только такое:

https://en.wikipedia.org/wiki/Liskov_substitution_principle

> Subtype Requirement: Let \phi (x) be a property provable about objects x of type T. Then \phi (y) should be true for objects y of type S where S is a subtype of T.



Тут упомянуты объекты.

>>930646

Ну я вижу папку "Администратор". Думаю, надо зати в нее, щелкнуть правой кнопкой на пустом месте и выбрать "Git bash here " или как-то так.

Также git bash можно запустить через меню Пуск.

Если что, в ОП посте есть гайд по использованию консоли, советую изучить.

И в след. раз пиши больше подробностей:

- ссылку на гайд
- что ты сделал
- что не получилось

А то угадывать приходится.
930694930725
#545 #930680
>>930645

И можно еще простой пример кода, где было бы видно нарушение принципа подстановки Лисков при различии в конструкторах?
930687
#546 #930686
>>930386

$db = chr($db - 1);

Это смотрится очень странно. Почему ты в одной переменной хранишь то число, то символ?

И названия $db, $bd неудачные, легко перепутать. Сам же перепутаешь и будешь спрашивать, что не так.

$findMissingLetter -> $letters

>>930360

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

>>930337

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

Алсо видел новость, что микрофинансовая организация сначала выдала кредит под 290% годовых, а потом, когда должник не смог выплатить, передоговорилась на 2300% годовых. https://rg.ru/2017/02/08/reg-pfo/mikrofinansovaia-organizaciia-potrebovala-2379-procentov-godovyh.html

2300 годовых - значит долг через год будет в 24 раза больше исходной суммы.

Так что в моей задаче все еще по-божески.

>>930322

> function collectionToArray(collection) {


> return Array.prototype.slice.call(collection);


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

var collectionToArray = Array.prototype.slice... (дальше подумай сам)

> function getElemByIdWithContext(selector, context) {


> return getElementsByProperty("id", selector, context);


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

var id = 'lalala';
findElementsRecursively(context, function (el) {
return el.id == id;
});

Или

findElementsRecursively(context, 'id', id, function (prop, value) {
return prop === value;
});

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

var findById = partialAny(findElementsRecursively, undefined, 'id', undefined, function (prop, value) ...);

findById(context, id)

Так, в общем, задачу можно считать решенной.
#546 #930686
>>930386

$db = chr($db - 1);

Это смотрится очень странно. Почему ты в одной переменной хранишь то число, то символ?

И названия $db, $bd неудачные, легко перепутать. Сам же перепутаешь и будешь спрашивать, что не так.

$findMissingLetter -> $letters

>>930360

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

>>930337

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

Алсо видел новость, что микрофинансовая организация сначала выдала кредит под 290% годовых, а потом, когда должник не смог выплатить, передоговорилась на 2300% годовых. https://rg.ru/2017/02/08/reg-pfo/mikrofinansovaia-organizaciia-potrebovala-2379-procentov-godovyh.html

2300 годовых - значит долг через год будет в 24 раза больше исходной суммы.

Так что в моей задаче все еще по-божески.

>>930322

> function collectionToArray(collection) {


> return Array.prototype.slice.call(collection);


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

var collectionToArray = Array.prototype.slice... (дальше подумай сам)

> function getElemByIdWithContext(selector, context) {


> return getElementsByProperty("id", selector, context);


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

var id = 'lalala';
findElementsRecursively(context, function (el) {
return el.id == id;
});

Или

findElementsRecursively(context, 'id', id, function (prop, value) {
return prop === value;
});

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

var findById = partialAny(findElementsRecursively, undefined, 'id', undefined, function (prop, value) ...);

findById(context, id)

Так, в общем, задачу можно считать решенной.
930724930749
#547 #930687
>>930680
http://ideone.com/U1QFQk

>Fatal error: Uncaught ArgumentCountError: Too few arguments to function ChildClass::__construct(), 0 passed in /home/lpoSIT/prog.php on line 28 and exactly 2 expected in /home/lpoSIT/prog.php:20

930927
#548 #930689
>>930220

Суть задачи тут все же в определении классов, как ты сделаешь вывод - не так принципиально. Можно просто функцию сделать, класс, или так написать.

Если тебе хочется ООП подход, то обычно это делается через классы для построения отчетов. Я бы сделал класс например StatReporter такого вида:

$reporter = new StatReporter;
$reporter->printReport($company);

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

> PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen()


На сайте не включено расширение mb_string. Видимо что-то сломали. Попробуй другой сайт.

Например http://sandbox.onlinephpfunctions.com/code/481086d900d41eac5344b4194eb32dcf63926e95

Я бы советовал вместо setDepartments сделать addDepartment, так удобнее будет.

> $production = $this->getBaseProduction();



> if($this->isBoss) {


> $production = 0;


> }


> return $production;



Можно чуть сократить (без фанатизма):

return $this->isBoss? 0 : $this->getBaseProduction();

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

[['Engineer', 1, 3], ...]

или

['3en1', '2ma3', ...]
#548 #930689
>>930220

Суть задачи тут все же в определении классов, как ты сделаешь вывод - не так принципиально. Можно просто функцию сделать, класс, или так написать.

Если тебе хочется ООП подход, то обычно это делается через классы для построения отчетов. Я бы сделал класс например StatReporter такого вида:

$reporter = new StatReporter;
$reporter->printReport($company);

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

> PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen()


На сайте не включено расширение mb_string. Видимо что-то сломали. Попробуй другой сайт.

Например http://sandbox.onlinephpfunctions.com/code/481086d900d41eac5344b4194eb32dcf63926e95

Я бы советовал вместо setDepartments сделать addDepartment, так удобнее будет.

> $production = $this->getBaseProduction();



> if($this->isBoss) {


> $production = 0;


> }


> return $production;



Можно чуть сократить (без фанатизма):

return $this->isBoss? 0 : $this->getBaseProduction();

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

[['Engineer', 1, 3], ...]

или

['3en1', '2ma3', ...]
56 Кб, 637x512
#549 #930694
>>930679
Я вел в терминале (bash), ключ, но он что-то не открывается
930924
#550 #930724
>>930686

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



чойта? Код прекращается до Завершения этого цикла.
#551 #930725
>>930679

ну, не знаю. Я пробовал и с консолью пол года, и на ГУИ. Гуи удобнее и нагляднее, а с консолью иногда казусы. Мне кажется, гуи дает полный необходимый для работы функционал, потому что большей частью фич гита никто не юзает, да и мало там прям таких извращенных штук.
#552 #930749
>>930686
Ага, я вчера тоже заметил такую хрень, когда просто менял саму сумму долга, а не долго+проценты и комиссия. Если меня только её - всё норм считает, так что можно считать что оно вроде бы правильно работает, хех. Но спасибо таки за ответ.
#553 #930814
>>925461
>>925484
>>925772

Напомню опу про серию вопросов по саперу.
931322
#554 #930920
>>930216

Почитай еще мой урок https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

>>930134

Не совсем то, но могу дать хорошую статью про ценообразование: http://russian.joelonsoftware.com/Articles/CamelsandRubberDuckies.html

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

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

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

В общем, учись считать.

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

Что именно входит в задачу - не важно, важно, сколько у тебя на нее уйдет времени.
#555 #930924
>>930694

Поясни, куда ты его ввел?

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

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

Не очень понятно, что ты делал дальше и что не получилось.

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

Ну и конечно плохо, что ты сам не понимаешь, что делаешь.
#556 #930927
>>930687

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

Твой код должен быть переписан так:

if ($class == 'ParentClass') {
$obj = new ParentClass(...);
} elseif (...) {
...
}

Или так:

$createParent = function () { return new ParentClass(...); };
$createChild = function () { ... };

$constructors = [$createParent, $createChild, ...];

Принцип Лисков тут вообще не при чем. Ошибка именно в твоем коде, так как когда ты пишешь

$object = new $class();

Ты должен гарантировать что данный класс не требует аргументов при создании. А не Барбара Лисков.
931015
#557 #931015
>>930927
http://ideone.com/hrLgHQ
Вот еще одно нарушение, уже без имени класса из переменной. Конструктор с другими параметрами ломает метод create() в классе-наследнике. Клиентский код ожидает, что метод будет работать, как и должен в родителе - по принципу Лискова. Но он не работает, тот же самый Fatal error.
931035931044
#558 #931035
>>931015

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

Причем, разумеется, сам PHP это не проверят и предупреждений не дает. И по заголовку класса это никак не очевидно. То есть использовать new static - это закладывать мину замедленного действия в код.

Добавлю еще, что new static - это изобретение разработчиков PHP (которые по моим ощущениям ООП вообще плохо понимают), мне оно не нравится, в других языках вроде Java такого бардака нет.
#559 #931044
>>931015

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

Ты сам похоже пока плохо LSP понял.

Метод create должен быть не-статический. Должно быть так:

class Parent
{
public fnction __construct() {}
public function test()
{
return new static;
}
}

class Child extens Parent
{
public function __construct($a, $b, $c) {}
}

function doSomething(Parent $p)
{
$p->test();
}

$o = new Parent();
doSomething($o); // ок
$o = new Child(1, 2, 3);
doSomething($o); // ошибка

Вот этот код иллюстрирует вредность использования new static.

В общем, вся проблем в нестандартных особенностях PHP, помогающих стрелять себе в ногу.
#559 #931044
>>931015

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

Ты сам похоже пока плохо LSP понял.

Метод create должен быть не-статический. Должно быть так:

class Parent
{
public fnction __construct() {}
public function test()
{
return new static;
}
}

class Child extens Parent
{
public function __construct($a, $b, $c) {}
}

function doSomething(Parent $p)
{
$p->test();
}

$o = new Parent();
doSomething($o); // ок
$o = new Child(1, 2, 3);
doSomething($o); // ошибка

Вот этот код иллюстрирует вредность использования new static.

В общем, вся проблем в нестандартных особенностях PHP, помогающих стрелять себе в ногу.
931080
#560 #931080
>>931044
Хм, да, должна быть функция, которая объект принимает, чтобы было где тип родителя указать. Тогда вот так:
http://ideone.com/zC5nTV
Статические методы в PHP к объекту тоже применяются, значит принимающая объект функция тут же ломается, Лисков нарушен.
931178
#561 #931178
>>931080

Ты опять полагаешься на странности PHP. Вот в этом коде: $object::method()

Это уже не ООП, а какое-то издевательство над ним. Статические методы и поля относятся к классу, а не к объекту, и вызываются на нем.

Ты должен писать ParentClass::method() для вызова статического метода.

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

Про моему это просто код, написанный в плохом стиле.

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

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

public void doSomething(Parent p)
{
p.staticMethod();
}

Всегда будет вызван Parent::staticMethod() независимо от того, какой мы объект передадим. И правильно, нечего использовать статические методы не по назначению.
#562 #931307
Спалю вам парочку годных сайтов
http://www.codingcage.com

http://www.itechempires.com
#563 #931322
>>930814

Пополняю серию. Правильно ли я установил события? http://ideone.com/GY8kav Ориентировался на твои слова:

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



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

931338
https://github.com/masssn/students.loc #564 #931331
>>903250
>>921309
>>904635

К сожалению, совсем забыл проверить этого анона, исправляюсь.

https://github.com/masssn/students.loc/blob/master/db config.ini
В конфиг имеет смысл помещать только то, что может менять пользователь. Опция driver тут явно лишняя, так как твой код скорее всего заточен под опредленную базу данных и с другой работать не будет, значит не надо давать ее выбирать.

https://github.com/masssn/students.loc/blob/master/students.sql#L31
Для имени TEXT - это слишком много. Также, на поля TEXT нельзя ставить индексы. Тут надо сделать VARCHAR и указать макс. длину.

> `gender` enum('Мужской','Женский')


Тут принято использовать латинские идентификаторы. Для них также стоит сделать константы в коде.

> `group_number` text NOT NULL,


Тут надо ограничить длину. Вообще, почитай про типы полей в MySQL.

> email` varchar(20)


20 символов это недостаточно для email

> `password` varchar(8) NOT NULL


8 символов для токена это маловато. Также, надо добавить с помощью слова COMMENT комментарий, что хранится в этом поле, чтобы другим людям было проще разобраться в твоей базе. Вот урок про комментарии: https://github.com/codedokode/pasta/blob/master/db/comments.md

Также, у тебя все файлы, включая конфиг БД, лежат в публичной папке. Если кто-то откроет URL http://example.com/db config.ini то он увидит пароли базы данных. Лучше сделать отдельную публичную папку, а все остальное разместить снаружи, почитай, это описано в комментариях к задаче.

https://github.com/masssn/students.loc/blob/master/app/autoload.php
Я не советую полагаться на getcwd(). Он же может быть разный. Лучше использовать константу __DIR__.

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

class_exists('Test');

У меня есть урок по автозагрузке: https://github.com/codedokode/pasta/blob/master/php/autoload.md

https://github.com/masssn/students.loc/blob/master/app/controllers/Controller.php#L29
тут не очень хорошо сделано. Если ты хочешь требовать регистрацию, то надо не выводить форму на любой странице, а делать редирект на страницу регистрации. Если ты хочешь потом вернуться назад, то надо еще передавать URL исходной страницы (а перед редиректом назад проверять, что он на твоем сайте, иначе это будет открытый редирект).

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

В методе action лучше было проверять весь URL, а не только первую часть. У тебя получается для одной страницы множество URL, что в общем-то плохо: /index/1, /index/2 и так далее. Лучше когда у страницы ровно один URL.

https://github.com/masssn/students.loc/blob/master/app/controllers/Controller.php#L152
Ошибка 404 сделана не совсем правильно. Ты должен отдавать HTTP код ответа 404, чтобы роботы и программы видели, что там ошибка.

- https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP

В PHP код ответа можно задать с помощью функции header().

Также, ты при выводе данных из $_SERVER не используешь htmlspecialchars. Из-за этого может быть XSS уязвимость.

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

Также, это вообще неправильно:

> $params = \app\DataHelper::makeSafeDatas($params);



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

Перечитай мои уроки по XSS и SQL и сделай правильную защиту:

- https://github.com/codedokode/pasta/blob/master/security/xss.md
- https://github.com/codedokode/pasta/blob/master/security/sql-injection.md

https://github.com/masssn/students.loc/blob/master/app/views/View.php
Тут не очень понятно, для чего предназначен массив $attributes. Ну например в контроллере ты часть данных передаешь через добавленные динамически свойства, а часть напрямую:

> $this->view->pages = $navDatas["pages"];


> $this->view->setAtributes($params);


Не очень понятно, почему так сделано.

Удобнее наверно просто передавать значения для подстановки в шаблон в виде массива в метод display(), а там извлекать их с помощью extract().

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

https://github.com/masssn/students.loc/blob/master/app/DataHelper.php#L11
В методе validate ты не проверяешь, что в массиве есть такие поля. Может быть ошибка если часть полей не будет передана в POST.

> if (!filter_var($datas['birth_year'], FILTER_VALIDATE_INT) && mb_strlen($datas['birth_year']) > 5 || mb_strlen($datas['birth_year']) < 4 || preg_match("^[A-z]^", $datas['birth_year'])) {


Слишком много условий. Проще либо написать одно рег. выражение либо проверить что число в диапазоне между X и Y.

Аналогично с суммой баллов, лучше проверить что это число и что оно в определенном диапазоне.

Не очень понятно, почему у тебя везде передаются массивы. Не лучше ли сделать объект-модель студента и везде передавать его? В функцию валидации, в форму, в функцию сохранения в БД. Массив плох тем, что непонятно, какие в нем есть поля, а каких нет.

Класс DataHelper надо переименовать, например в StudentValidator.

Имена неймспейсов принято писать с большой буквы. app можно было и не писать вообще.

https://github.com/masssn/students.loc/blob/master/app/Pager.php
Плохо что этот класс лезет в GET. Ты жестко его привязал к внешним данным, и не позволяешь просто передать номер страницы как переменную.

Неправильно писать datas, так как data это уже множественное число. Вообще, у тебя неудачно выбрано название функции: getNavDatas. Слово data не дает никакой полезной информации, так как любая функция работает с данными. Надо лучше выбирать названия для функций, чтобы они соответствовали предназначению функции.

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

Также, ты старательно избегаешь использования объектов и ООП вообще. Ты не сделал модель для студента, а передаешь везде массивы. В пагинаторе то же самое- ты возвращаешь массив, но лучше было сделать просто объект и у него методы getPagesCount(), getLink() и так далее. Попробуй переделать класс расчета пагинации на использование полей и методов вместо возврата массива.

Контроллер поиска и вывода списка студентов можно объединить в один. Аналогично можно объединить регистрацию и редактирование.

https://github.com/masssn/students.loc/blob/master/app/Singleton.php
Зачем это? Не надо использовать паттерны там, где это не нужно. Есди ты хочешь изучить паттерны, изучи код библиотек вроде Symfony Forms или Doctrine, почитай книгу Фаулера (шаблоны разработки корпоративных приложений) и посмотри как их надо использовать на реальных примерах, а не читай статьи от тех, кто дальше синглтона ничего не понял.
https://github.com/masssn/students.loc #564 #931331
>>903250
>>921309
>>904635

К сожалению, совсем забыл проверить этого анона, исправляюсь.

https://github.com/masssn/students.loc/blob/master/db config.ini
В конфиг имеет смысл помещать только то, что может менять пользователь. Опция driver тут явно лишняя, так как твой код скорее всего заточен под опредленную базу данных и с другой работать не будет, значит не надо давать ее выбирать.

https://github.com/masssn/students.loc/blob/master/students.sql#L31
Для имени TEXT - это слишком много. Также, на поля TEXT нельзя ставить индексы. Тут надо сделать VARCHAR и указать макс. длину.

> `gender` enum('Мужской','Женский')


Тут принято использовать латинские идентификаторы. Для них также стоит сделать константы в коде.

> `group_number` text NOT NULL,


Тут надо ограничить длину. Вообще, почитай про типы полей в MySQL.

> email` varchar(20)


20 символов это недостаточно для email

> `password` varchar(8) NOT NULL


8 символов для токена это маловато. Также, надо добавить с помощью слова COMMENT комментарий, что хранится в этом поле, чтобы другим людям было проще разобраться в твоей базе. Вот урок про комментарии: https://github.com/codedokode/pasta/blob/master/db/comments.md

Также, у тебя все файлы, включая конфиг БД, лежат в публичной папке. Если кто-то откроет URL http://example.com/db config.ini то он увидит пароли базы данных. Лучше сделать отдельную публичную папку, а все остальное разместить снаружи, почитай, это описано в комментариях к задаче.

https://github.com/masssn/students.loc/blob/master/app/autoload.php
Я не советую полагаться на getcwd(). Он же может быть разный. Лучше использовать константу __DIR__.

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

class_exists('Test');

У меня есть урок по автозагрузке: https://github.com/codedokode/pasta/blob/master/php/autoload.md

https://github.com/masssn/students.loc/blob/master/app/controllers/Controller.php#L29
тут не очень хорошо сделано. Если ты хочешь требовать регистрацию, то надо не выводить форму на любой странице, а делать редирект на страницу регистрации. Если ты хочешь потом вернуться назад, то надо еще передавать URL исходной страницы (а перед редиректом назад проверять, что он на твоем сайте, иначе это будет открытый редирект).

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

В методе action лучше было проверять весь URL, а не только первую часть. У тебя получается для одной страницы множество URL, что в общем-то плохо: /index/1, /index/2 и так далее. Лучше когда у страницы ровно один URL.

https://github.com/masssn/students.loc/blob/master/app/controllers/Controller.php#L152
Ошибка 404 сделана не совсем правильно. Ты должен отдавать HTTP код ответа 404, чтобы роботы и программы видели, что там ошибка.

- https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP

В PHP код ответа можно задать с помощью функции header().

Также, ты при выводе данных из $_SERVER не используешь htmlspecialchars. Из-за этого может быть XSS уязвимость.

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

Также, это вообще неправильно:

> $params = \app\DataHelper::makeSafeDatas($params);



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

Перечитай мои уроки по XSS и SQL и сделай правильную защиту:

- https://github.com/codedokode/pasta/blob/master/security/xss.md
- https://github.com/codedokode/pasta/blob/master/security/sql-injection.md

https://github.com/masssn/students.loc/blob/master/app/views/View.php
Тут не очень понятно, для чего предназначен массив $attributes. Ну например в контроллере ты часть данных передаешь через добавленные динамически свойства, а часть напрямую:

> $this->view->pages = $navDatas["pages"];


> $this->view->setAtributes($params);


Не очень понятно, почему так сделано.

Удобнее наверно просто передавать значения для подстановки в шаблон в виде массива в метод display(), а там извлекать их с помощью extract().

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

https://github.com/masssn/students.loc/blob/master/app/DataHelper.php#L11
В методе validate ты не проверяешь, что в массиве есть такие поля. Может быть ошибка если часть полей не будет передана в POST.

> if (!filter_var($datas['birth_year'], FILTER_VALIDATE_INT) && mb_strlen($datas['birth_year']) > 5 || mb_strlen($datas['birth_year']) < 4 || preg_match("^[A-z]^", $datas['birth_year'])) {


Слишком много условий. Проще либо написать одно рег. выражение либо проверить что число в диапазоне между X и Y.

Аналогично с суммой баллов, лучше проверить что это число и что оно в определенном диапазоне.

Не очень понятно, почему у тебя везде передаются массивы. Не лучше ли сделать объект-модель студента и везде передавать его? В функцию валидации, в форму, в функцию сохранения в БД. Массив плох тем, что непонятно, какие в нем есть поля, а каких нет.

Класс DataHelper надо переименовать, например в StudentValidator.

Имена неймспейсов принято писать с большой буквы. app можно было и не писать вообще.

https://github.com/masssn/students.loc/blob/master/app/Pager.php
Плохо что этот класс лезет в GET. Ты жестко его привязал к внешним данным, и не позволяешь просто передать номер страницы как переменную.

Неправильно писать datas, так как data это уже множественное число. Вообще, у тебя неудачно выбрано название функции: getNavDatas. Слово data не дает никакой полезной информации, так как любая функция работает с данными. Надо лучше выбирать названия для функций, чтобы они соответствовали предназначению функции.

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

Также, ты старательно избегаешь использования объектов и ООП вообще. Ты не сделал модель для студента, а передаешь везде массивы. В пагинаторе то же самое- ты возвращаешь массив, но лучше было сделать просто объект и у него методы getPagesCount(), getLink() и так далее. Попробуй переделать класс расчета пагинации на использование полей и методов вместо возврата массива.

Контроллер поиска и вывода списка студентов можно объединить в один. Аналогично можно объединить регистрацию и редактирование.

https://github.com/masssn/students.loc/blob/master/app/Singleton.php
Зачем это? Не надо использовать паттерны там, где это не нужно. Есди ты хочешь изучить паттерны, изучи код библиотек вроде Symfony Forms или Doctrine, почитай книгу Фаулера (шаблоны разработки корпоративных приложений) и посмотри как их надо использовать на реальных примерах, а не читай статьи от тех, кто дальше синглтона ничего не понял.
932458
https://github.com/masssn/students.loc #565 #931333
>>903250
>>921309
>>904635

https://github.com/masssn/students.loc/blob/master/app/DB.php
Зачем нужен этот класс? Почитай про DI: https://github.com/codedokode/pasta/blob/master/arch/di.md

Также почитай про использование исключений, ты бездумно скопировал try/catch из какой-то статьи, не понимая, как он работает: https://github.com/codedokode/pasta/blob/master/php/exceptions.md

https://github.com/masssn/students.loc/blob/master/app/models/StudentsGateaway.php#L40
public function addStudent($params)
Эта функция написана неправильно. Она подразумевает, что ей будет передан массив содержащий строго определенные поля в определенном порядке. Причем этот порядок нигде не документирован. Стоит в форме переставить 2 поля местами, как все сломается.

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

> setcookie('user_pass', $params["password"], time() + 3600000);


Есть принцип единой ответственности, каждый класс или функция должна выполнять свою задачу. Как установка куки связана с вставкой студента в БД? Никак, ее тут быть не должно вообще.

> public function getLastId()


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

https://github.com/masssn/students.loc/blob/master/app/models/StudentsGateaway.php#L78

> public function getAll($sort, $start, $limit)


тут нет проверки, что в параметре sort разрешенные значения, а не какой-то вредоносный код. Перечитай урок про SQL инъекции.

> " LIMIT " . $start . "," . $limit;


Это надо было делать через плейсхолдеры.

> public function search($search, $sort, $start, $limit)


> :x IN(name, second_name, group_number, summary)


Для поиска надо использовать LIKE или что-то такое, так как твой вариант не позволяет искать по части фамилии.

> public function getCountBySearch($search)


> WHERE


> " . $search . "


Надо использовать плейсхолдеры.

https://github.com/masssn/students.loc/tree/master/app/views
Для шаблонов и классов надо сделать разные папки.

https://github.com/masssn/students.loc/blob/master/app/views/students_list_template.php#L10

> <td> <a href="/index/?sort=name&page=<?php echo $this->link; ?>">Имя</a></td>


Знак & нельзя просто так писать в HTML коде, это спецсимвол. Почитай про мнемоники (entities) в HTML.

> <a href="/index/?sort=<?php echo $this->sort; ?>&page=<?php echo $i;?>">[<?php echo $i?>]</a>


Не надо собирать ссылку по кускам. Лучше сделать функцию, которая ее генерирует.
https://github.com/masssn/students.loc #565 #931333
>>903250
>>921309
>>904635

https://github.com/masssn/students.loc/blob/master/app/DB.php
Зачем нужен этот класс? Почитай про DI: https://github.com/codedokode/pasta/blob/master/arch/di.md

Также почитай про использование исключений, ты бездумно скопировал try/catch из какой-то статьи, не понимая, как он работает: https://github.com/codedokode/pasta/blob/master/php/exceptions.md

https://github.com/masssn/students.loc/blob/master/app/models/StudentsGateaway.php#L40
public function addStudent($params)
Эта функция написана неправильно. Она подразумевает, что ей будет передан массив содержащий строго определенные поля в определенном порядке. Причем этот порядок нигде не документирован. Стоит в форме переставить 2 поля местами, как все сломается.

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

> setcookie('user_pass', $params["password"], time() + 3600000);


Есть принцип единой ответственности, каждый класс или функция должна выполнять свою задачу. Как установка куки связана с вставкой студента в БД? Никак, ее тут быть не должно вообще.

> public function getLastId()


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

https://github.com/masssn/students.loc/blob/master/app/models/StudentsGateaway.php#L78

> public function getAll($sort, $start, $limit)


тут нет проверки, что в параметре sort разрешенные значения, а не какой-то вредоносный код. Перечитай урок про SQL инъекции.

> " LIMIT " . $start . "," . $limit;


Это надо было делать через плейсхолдеры.

> public function search($search, $sort, $start, $limit)


> :x IN(name, second_name, group_number, summary)


Для поиска надо использовать LIKE или что-то такое, так как твой вариант не позволяет искать по части фамилии.

> public function getCountBySearch($search)


> WHERE


> " . $search . "


Надо использовать плейсхолдеры.

https://github.com/masssn/students.loc/tree/master/app/views
Для шаблонов и классов надо сделать разные папки.

https://github.com/masssn/students.loc/blob/master/app/views/students_list_template.php#L10

> <td> <a href="/index/?sort=name&page=<?php echo $this->link; ?>">Имя</a></td>


Знак & нельзя просто так писать в HTML коде, это спецсимвол. Почитай про мнемоники (entities) в HTML.

> <a href="/index/?sort=<?php echo $this->sort; ?>&page=<?php echo $i;?>">[<?php echo $i?>]</a>


Не надо собирать ссылку по кускам. Лучше сделать функцию, которая ее генерирует.
932458
Сапер #566 #931338
>>925461

По поводу сапера и словарей:

> MinesweeperGame.prototype._addCellToDict = function(x, y, dict) {


> MinesweeperGame.prototype._isCellInDict = function(x, y, dict) {



Тебе не кажется, что тут есть смысл сделать отдельный объект "двухмерный словарь" и писать dict.addCell(x, y) или dict.hasCell(x, y)?

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

>>925484

> И еще, стоит ли писать вот такую обертку вокруг метода реализации чтобы не кидать каждый раз свойства объекта ему в аргументы


Если сделать отдельный объект, будет красивее и исчезнет обертка:

MinesweeperGame.prototype.countFlags = function() {
return this._flags.count();
};

>>925772

> ...ты имел ввиду действительно двумерный массив ([ [true, false], [false, false], [false, true], [true, false]) или словарь ( {1: {1: true, 2:false}, 2: {1: false, 2: false}, 3: {1:false, 2: true})?


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

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


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

>>931322

> Правильно ли я установил события?


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

> this._domView.setLeftMouseDownEventToCell(function(event) {


В общем да, нормально, только может функцию стоит как-то еще переименовать. Вроде addCellLeftClickListener, как-нибудь так.

> that._domView.setFaceType("danger-face");


Вот мне кажется, это должно называться по другому. Что обозначает значок? Что идет обработка события? Тогда логично назвать функцию как setIsBusy(true) или как-то так. И может быть, даже стоит сделать смену значка внутри view.

То есть мне кажется, лучше бы если вью просто выдавал событие клика по клеточке, а не отдельно mousedown/up. И чтобы контроллер не проверял e.which. И чтобы вью передавал в контроллер не event.target (который относится к DOM), а координаты. То есть я предлагаю всю работу с DOM и нативными событиями засунуть в вью, а из контроллера убрать. Разделить зоны ответственности.
Сапер #566 #931338
>>925461

По поводу сапера и словарей:

> MinesweeperGame.prototype._addCellToDict = function(x, y, dict) {


> MinesweeperGame.prototype._isCellInDict = function(x, y, dict) {



Тебе не кажется, что тут есть смысл сделать отдельный объект "двухмерный словарь" и писать dict.addCell(x, y) или dict.hasCell(x, y)?

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

>>925484

> И еще, стоит ли писать вот такую обертку вокруг метода реализации чтобы не кидать каждый раз свойства объекта ему в аргументы


Если сделать отдельный объект, будет красивее и исчезнет обертка:

MinesweeperGame.prototype.countFlags = function() {
return this._flags.count();
};

>>925772

> ...ты имел ввиду действительно двумерный массив ([ [true, false], [false, false], [false, true], [true, false]) или словарь ( {1: {1: true, 2:false}, 2: {1: false, 2: false}, 3: {1:false, 2: true})?


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

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


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

>>931322

> Правильно ли я установил события?


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

> this._domView.setLeftMouseDownEventToCell(function(event) {


В общем да, нормально, только может функцию стоит как-то еще переименовать. Вроде addCellLeftClickListener, как-нибудь так.

> that._domView.setFaceType("danger-face");


Вот мне кажется, это должно называться по другому. Что обозначает значок? Что идет обработка события? Тогда логично назвать функцию как setIsBusy(true) или как-то так. И может быть, даже стоит сделать смену значка внутри view.

То есть мне кажется, лучше бы если вью просто выдавал событие клика по клеточке, а не отдельно mousedown/up. И чтобы контроллер не проверял e.which. И чтобы вью передавал в контроллер не event.target (который относится к DOM), а координаты. То есть я предлагаю всю работу с DOM и нативными событиями засунуть в вью, а из контроллера убрать. Разделить зоны ответственности.
932755
#567 #931351
>>927560

> Все еще не ясно, что ты имеешь ввиду под использованием сервисов. В 83 треде ты писал, что:


>> $app['validator'] = function() use($app){return new App\Helper\Validator($app);};


>>Это по моему нарушение принципа DI, получается не DI, а Service Locator


> Нужно регистрировать сервис провайдеры или что?



Там проблема в том, что ты в сервис Validator передаешь весь $app целиком вместо указания конкретных зависимостей. Это паттерн ServiceLocator, и это описано в моем уроке по DI. В данном случае это плохо, никакого смысла так делать нет.

Надо так: new Validator($app->something, $app->em, $app->helper)

> 1 - я не храню пароль в базе, а в форме он должен быть


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

$form = ...
$form->submit();
$password = $form->password->getValue();
$auth->setUserPassword($user, $password);
...

То есть часть полей идут напрямую в entity, часть остаются в форме.

> 2 - для проверки полей на UniqueValue() нужно установить doctrine bridge и doctrine bundle


Doctrine Bundle в силекс, я думаю, не поставить, так как это кусок фреймворка Симфони.

>>924780

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


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

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


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

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


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

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


> Но это же не форма. Это валидатор, в который я передаю форму с констрантой.


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

> Этот класс создан специально для того, чтобы проверить есть ли такая связка логин+пароль в базе, и если этот класс не может этого сделать, то зачем он тогда нужен?


Он нужен, но должен вызываться в другом месте. Не ставиться как валидатор для формы.

> Что значит использовать сервисы? У тебя есть уроки использования или примеры таких сервисов?


Сервис - это класс, который не представляет какую-то сущность, но содержит методы. Это довольно широкое определение получается, вот тут есть еще что-то по теме, но не очень понятно: http://design-pattern.ru/patterns/service-layer.html

Ну например мы можем сделать сервис для работы с БД:

class UserGateway {
public function insertUser(User $user);
...
}

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

Давай посмотрим сюда: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Controller/CommentController.php и параллельно вспомним чем должен заниматься контроллер в MVC.

У тебя он занимается:

- выводом данных (printComments, очень странная функция) - а должен заниматься view
- сборкой дерева комментариев (makeCommentTree) - а должна model (кстати используется неэффективный алгоритм, почитай потом урок https://github.com/codedokode/pasta/blob/master/db/trees.md )
- определением id текущего пользователя ($hash = $_COOKIE['fileshare'];) - а лучше сделать отдельную функцию для этого в отдельном сервисе авторизации
- генерацией ссылок (return $app->redirect("/download/$fileId");) - а лучше сделать для этого функцию

Или посмотрим на https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Controller/RegisterController.php . Он занимается:

- генерацией паролей и хешей, что относится к модели ( $user->setSalt(uniqid());, $user->setHash(md5($user->getEmail().$user->getSalt().$data->password));). Очевидно, в модели должна быть функция вроде setUserPassword, ты вместо этого просто пишешь код стеной
- установкой авторизационных кук вместо сервиса авторизации

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

Это и называется толстый контроллер (fat ugly controller).

Это затрудняет понимание и правку кода, мешает повторному использованию. ну например, нам нужно в другом месте получить дерево комментариев. Как это сделать, если код для этого жестко вклеен в контроллер и его нельзя вызвать из другого места? То же касается операций смены пароля, авторизации, генерации ссылок.
#567 #931351
>>927560

> Все еще не ясно, что ты имеешь ввиду под использованием сервисов. В 83 треде ты писал, что:


>> $app['validator'] = function() use($app){return new App\Helper\Validator($app);};


>>Это по моему нарушение принципа DI, получается не DI, а Service Locator


> Нужно регистрировать сервис провайдеры или что?



Там проблема в том, что ты в сервис Validator передаешь весь $app целиком вместо указания конкретных зависимостей. Это паттерн ServiceLocator, и это описано в моем уроке по DI. В данном случае это плохо, никакого смысла так делать нет.

Надо так: new Validator($app->something, $app->em, $app->helper)

> 1 - я не храню пароль в базе, а в форме он должен быть


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

$form = ...
$form->submit();
$password = $form->password->getValue();
$auth->setUserPassword($user, $password);
...

То есть часть полей идут напрямую в entity, часть остаются в форме.

> 2 - для проверки полей на UniqueValue() нужно установить doctrine bridge и doctrine bundle


Doctrine Bundle в силекс, я думаю, не поставить, так как это кусок фреймворка Симфони.

>>924780

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


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

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


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

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


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

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


> Но это же не форма. Это валидатор, в который я передаю форму с констрантой.


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

> Этот класс создан специально для того, чтобы проверить есть ли такая связка логин+пароль в базе, и если этот класс не может этого сделать, то зачем он тогда нужен?


Он нужен, но должен вызываться в другом месте. Не ставиться как валидатор для формы.

> Что значит использовать сервисы? У тебя есть уроки использования или примеры таких сервисов?


Сервис - это класс, который не представляет какую-то сущность, но содержит методы. Это довольно широкое определение получается, вот тут есть еще что-то по теме, но не очень понятно: http://design-pattern.ru/patterns/service-layer.html

Ну например мы можем сделать сервис для работы с БД:

class UserGateway {
public function insertUser(User $user);
...
}

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

Давай посмотрим сюда: https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Controller/CommentController.php и параллельно вспомним чем должен заниматься контроллер в MVC.

У тебя он занимается:

- выводом данных (printComments, очень странная функция) - а должен заниматься view
- сборкой дерева комментариев (makeCommentTree) - а должна model (кстати используется неэффективный алгоритм, почитай потом урок https://github.com/codedokode/pasta/blob/master/db/trees.md )
- определением id текущего пользователя ($hash = $_COOKIE['fileshare'];) - а лучше сделать отдельную функцию для этого в отдельном сервисе авторизации
- генерацией ссылок (return $app->redirect("/download/$fileId");) - а лучше сделать для этого функцию

Или посмотрим на https://github.com/anotherCodeMunkey/fileshare/blob/master/App/Controller/RegisterController.php . Он занимается:

- генерацией паролей и хешей, что относится к модели ( $user->setSalt(uniqid());, $user->setHash(md5($user->getEmail().$user->getSalt().$data->password));). Очевидно, в модели должна быть функция вроде setUserPassword, ты вместо этого просто пишешь код стеной
- установкой авторизационных кук вместо сервиса авторизации

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

Это и называется толстый контроллер (fat ugly controller).

Это затрудняет понимание и правку кода, мешает повторному использованию. ну например, нам нужно в другом месте получить дерево комментариев. Как это сделать, если код для этого жестко вклеен в контроллер и его нельзя вызвать из другого места? То же касается операций смены пароля, авторизации, генерации ссылок.
#568 #931352
>>924780

И еще. Если ты встроил проверку логина/пароля в форму, то как их проверить без формы? Тот же вопрос по поводу валидации комментариев, пользователей. Можем ли мы достать комментарий из формы или еще откуда-нибудь и проверить на правильность?
#569 #931355
>>924780

То есть, у нас должны быть какие-то классы (сервисы), часть модели, которые содержат операции вроде "сменить пароль", "залогиниться под пользователем X", "проверить правильнсоть комментария", "добавить комментарий" и тд.
#570 #931357
>>927223

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

$this->first_name это поле объекта
$first_name это переменная, аргумент конструктора

>>927224

> Почему нельзя написать вместо $this->first_name просто $first_name?


Потому что в методе say_name нет такой переменной, и если ты не пропустил изучение функций, то должен знать что внутри функции видны только созданные в ней или переданные ей перменные, и $first_name там нет.
#571 #931359
>>927240

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

Ну ты говоришь объекты, это сложно. А реши задачу про Вектор или кошки-мышки из моего учебника без объектов. Будет еще сложнее. ООП как раз придумано чтобы позволить в больших программах разбивать код на отдельные изолированные классы чтобы с ним было проще работать.

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

> http://ideone.com/WeGENR - Вопросы с абстрактными классами.


В функции checkAnswer лучше было сделать только проверку, без вывода на экран. То есть пусть функция просто проверяет ответ, возврашает 0 или 1 (ну или true/false), или число баллов, а код, который ее вызвал, уже решает, что с этим делать.

Из-за этого у тебя еще и копипаста получилась.

Поле $tip логичнее было поместить в AbstractQustion так как подсказка может быть у вопроса любого типа.

В остальном верно.

> http://ideone.com/qRGcXB - Компания Вектор.


Тут все верно.
#573 #931369
Есть где-нибудь пример полного процесса создания сайта, от вёрстки макета и до натягивания его на КМС?
931388932781
39 Кб, 604x457
#574 #931388
>>931369

>Есть где-нибудь пример полного процесса создания сайта, от вёрстки макета и до натягивания его на КМС?


>КМС

#575 #931777
Есть вот такая строка:
$user->password = password_hash($data['password'], PASSWORD_DEFAULT);
Пароль должен хешироваться в базе, но ниху не получается. Прописывается в таблице обычными символами, т.е. то что ввел юзер при регистрации.
Чому так? Где я мог обосраться?

ОпенСервер, PHP 5.5, Апач 2.4, MySQL 5.6, регистрацию через подключенную RedBean
931794932781
#576 #931794
>>931777
Что значит не хешируется?
Ты пароль шифруешь? С помощью чего?
931811
#577 #931811
>>931794

>Ты пароль шифруешь?


Да, шифрую пароль, введенный юзером при регистрации на сайте.

>С помощью чего?


С помощью функции password_hash(). Алгоритм хеширования BCrypt.
931872
#578 #931843
Можете сказать CSS который был в 2012 году, сильно отличается от того который сейчас?
931875932781
#579 #931872
>>931811
с помощью var_dump посмотри значение поля
$user->password
Либо передай в другую форму и посмотри значения
#580 #931875
>>931843
Да. Появилось множество методологий.
Пре-процессоры. Если тебя технологии интересуют.
В разве что появилось множество интереснейших вещей.
#581 #931876
Есть кто может помочь дубу?
932781
#582 #931910
>>921312

>>>Задача 2: сделать функцию addProperty(object, name, initialValue) для создания приватных свойств с геттерами и сеттерами на объекте или прототипе объекта.


>> https://jsfiddle.net/sh21j4p1/


>Тут опечатка в коде...


Исправил, теперь всё работает: https://jsfiddle.net/sh21j4p1/1/

Я пытался задать метод через прототип и обратиться к нему в "конструкторе" функции, но мне выдалась ошибка о том что этот метод не является функцией: https://jsfiddle.net/3sjvm5gp/
Почему так получилось? Ведь если функция не находиться в объекте она ищется по цепочке в его прототипе.

>>908071

>Задача 3: сделать функцию для добавления в объект или прототип нового метода addMethod(object, name, fn).


Что-то у меня не получилось понять подвоха этой задачи: https://jsfiddle.net/zmLjh7ur/
Более того, я не смог понять как работает функция super(): https://jsfiddle.net/b073aLb5/1/
В чем моя ошибка? Здесь же должна быть такая же ситуация, super должен искать метод в прототипе.

>>921312

>Задача про фастфуд


>> Почему-то не получается https://jsfiddle.net/y28h2o2b/3/


>this.menu не определено


Определил https://jsfiddle.net/y28h2o2b/3/
Привычка что переменные сами определяются в php

>Электросеть



https://jsfiddle.net/6591a2sL/5/

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


>> Лучше исключить её из перебора потому, что ЛЭП тоже может вернуть какое-то количество мощности.


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


Но мы можем и даже должны иметь возможность узнать её мощность.

>>>> ElectricalNetwork.prototype.countPrice = function() {


>>>> price += this.elements.countPrice(balance);


>>>> balance = this.elements.countPower(balance);


>>>Вот здесь нехорошо, что код расчета закупок/продаж размазан по 2 классам - ElectricalNetwork и PowerLine. Логичнее его оставить только в ElectricalNetwork. Ну подумай сам: кто принимает решение о закупке: электросеть или начальник на конкретной ЛЭП (или руководство удаленной сети, к которой подключена ЛЭП)? Логично, что решение принимают в центре, а на ЛЭП только сообщают, сколько нужно принять или передать, запрашивают цены и тд. Так как сама ЛЭП не знает про баланс энергии в сети.


>>С другой стороны электросеть не знает о ценах и о внутреннем устройстве ЛЭП. Моя идея в том, баланс можно просто передать в условный счетчик. Ведь это для ЛЭП свойственно иметь и считать цену.


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


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

>> function PowerLine(power, price) {


>> this.power = power;


>> this.price = price;


>> }


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


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

>> PowerLine.prototype.countPower = function(power) {


>> var thispower = this.power;



>> for (var i = 0; i < thispower; thispower--) {


>> if (power == 0) {


>> break;


>> }



>> power += power / -Math.abs(power);


>что-то я не могу толком понять, что тут происходит. Зачем мы power делим саму на себя? Получится ведь либо 1, либо -1. Тут явно ошибка.


Наверно я сбил столку неправильно назвав функцию - эта функция считает сколько энергии останется после передачи\получения её через конкретную ЛЭП.

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

>> if (this.elements instanceof PowerLine) {


>> price += this.elements.countPrice(balance);


>> balance = this.elements.countPower(balance);


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


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

>Определение типа переменной


>>>Недостаточно, надо бы проверить что там есть свойства от 0 до length - 1.


>>>от 0 до length - 1


>> А как это выразить в условии


>Написать цикл, проверяющий наличие свойств с помощью оператора in.


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

>15. Напиши функцию неглубокого копирования объектов и массивов


https://jsfiddle.net/uyey3at1/3/

>>>> for (property in object) {


>>>тут есть подвох, for in перебирает не только свойства объекта, но и его прототипов. Если кто-то расширит стандартный Object.prototype, это свойство или метод попадет в цикл.


>> Опять же, не могу понять что с этим не так: Если это клон объекта, то этот клон должен иметь тот же прототип что и "донор"(?).


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


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

>Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы.


А других встроенных объектов это замечание касается?

>Глубокое копирование


>> https://jsfiddle.net/j8pydqsg/2/


>> var clone = new object.constructor;


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


>


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


>- если источник - массив, создать новый массив и скопировать элементы


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


>- иначе, если источник - не объект (а число, строка, null и тд), можно просто вернуть его


Переписал всё: https://jsfiddle.net/b0a7tk75/
#582 #931910
>>921312

>>>Задача 2: сделать функцию addProperty(object, name, initialValue) для создания приватных свойств с геттерами и сеттерами на объекте или прототипе объекта.


>> https://jsfiddle.net/sh21j4p1/


>Тут опечатка в коде...


Исправил, теперь всё работает: https://jsfiddle.net/sh21j4p1/1/

Я пытался задать метод через прототип и обратиться к нему в "конструкторе" функции, но мне выдалась ошибка о том что этот метод не является функцией: https://jsfiddle.net/3sjvm5gp/
Почему так получилось? Ведь если функция не находиться в объекте она ищется по цепочке в его прототипе.

>>908071

>Задача 3: сделать функцию для добавления в объект или прототип нового метода addMethod(object, name, fn).


Что-то у меня не получилось понять подвоха этой задачи: https://jsfiddle.net/zmLjh7ur/
Более того, я не смог понять как работает функция super(): https://jsfiddle.net/b073aLb5/1/
В чем моя ошибка? Здесь же должна быть такая же ситуация, super должен искать метод в прототипе.

>>921312

>Задача про фастфуд


>> Почему-то не получается https://jsfiddle.net/y28h2o2b/3/


>this.menu не определено


Определил https://jsfiddle.net/y28h2o2b/3/
Привычка что переменные сами определяются в php

>Электросеть



https://jsfiddle.net/6591a2sL/5/

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


>> Лучше исключить её из перебора потому, что ЛЭП тоже может вернуть какое-то количество мощности.


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


Но мы можем и даже должны иметь возможность узнать её мощность.

>>>> ElectricalNetwork.prototype.countPrice = function() {


>>>> price += this.elements.countPrice(balance);


>>>> balance = this.elements.countPower(balance);


>>>Вот здесь нехорошо, что код расчета закупок/продаж размазан по 2 классам - ElectricalNetwork и PowerLine. Логичнее его оставить только в ElectricalNetwork. Ну подумай сам: кто принимает решение о закупке: электросеть или начальник на конкретной ЛЭП (или руководство удаленной сети, к которой подключена ЛЭП)? Логично, что решение принимают в центре, а на ЛЭП только сообщают, сколько нужно принять или передать, запрашивают цены и тд. Так как сама ЛЭП не знает про баланс энергии в сети.


>>С другой стороны электросеть не знает о ценах и о внутреннем устройстве ЛЭП. Моя идея в том, баланс можно просто передать в условный счетчик. Ведь это для ЛЭП свойственно иметь и считать цену.


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


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

>> function PowerLine(power, price) {


>> this.power = power;


>> this.price = price;


>> }


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


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

>> PowerLine.prototype.countPower = function(power) {


>> var thispower = this.power;



>> for (var i = 0; i < thispower; thispower--) {


>> if (power == 0) {


>> break;


>> }



>> power += power / -Math.abs(power);


>что-то я не могу толком понять, что тут происходит. Зачем мы power делим саму на себя? Получится ведь либо 1, либо -1. Тут явно ошибка.


Наверно я сбил столку неправильно назвав функцию - эта функция считает сколько энергии останется после передачи\получения её через конкретную ЛЭП.

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

>> if (this.elements instanceof PowerLine) {


>> price += this.elements.countPrice(balance);


>> balance = this.elements.countPower(balance);


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


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

>Определение типа переменной


>>>Недостаточно, надо бы проверить что там есть свойства от 0 до length - 1.


>>>от 0 до length - 1


>> А как это выразить в условии


>Написать цикл, проверяющий наличие свойств с помощью оператора in.


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

>15. Напиши функцию неглубокого копирования объектов и массивов


https://jsfiddle.net/uyey3at1/3/

>>>> for (property in object) {


>>>тут есть подвох, for in перебирает не только свойства объекта, но и его прототипов. Если кто-то расширит стандартный Object.prototype, это свойство или метод попадет в цикл.


>> Опять же, не могу понять что с этим не так: Если это клон объекта, то этот клон должен иметь тот же прототип что и "донор"(?).


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


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

>Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы.


А других встроенных объектов это замечание касается?

>Глубокое копирование


>> https://jsfiddle.net/j8pydqsg/2/


>> var clone = new object.constructor;


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


>


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


>- если источник - массив, создать новый массив и скопировать элементы


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


>- иначе, если источник - не объект (а число, строка, null и тд), можно просто вернуть его


Переписал всё: https://jsfiddle.net/b0a7tk75/
#583 #931914
>>921312

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


Простите, я просто обычно делаю всё разом.
#584 #931925
Как установить пхп-сервер у себя на компе и писать в нём код?
931926931927
#585 #931926
>>931925
А ОП-пост прочитать слабо?

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

https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
931930
8 Кб, 192x263
#586 #931927
#587 #931930
>>931926
Ты ОП? Подскажи пожалуйста, я вообще хотел язык программирования - кое-какие операции на компе сделать самым простым способом. Я года 3 назад в этом треде прошёл курс молодого бойца, так что помню что в ПХП есть всякие операции с папками и язык лёгкий.
Или есть что получше?
932057932781
#588 #931986
Поясните насчет даты. Её лучше образовывать в бд или php скриптом? В БД с помощью типа DATE можно вывести дату запроса, есть ли смысл писать метку на php?
932009932781
#590 #932057
>>931930
Powershell для Windows.
Bash для *nix.
#591 #932086
Подскажите пожалуйста зачем нужны анонимне функции? Уже с год пишу код и знаю о них, но на практике я так и не понял куда их впихивают, почему на собеседованиях про них спрашивают, и вообще почему в своё время столько шуму было про их введение. ведь на практике они как-бы и профитов не дают. Или я неправ?
932219
#592 #932219
>>932086

(я уже раньше писал, просто скопирую сюда)

Давай я тебе дам задачу. Есть какая-то сущность и коллекция этих сущностей (Работник и список работников, Ученик и классный журнал, Товар и Корзина, Товар и Склад). Можешь представить их как объекты или массивы, если не знаешь ООП.

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

Напиши функцию, отбирающую массив сущностей, соответствующих определенному критерию.

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

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

Как ты представишь в своем коде "критерий" или "формула"? Как передать в функцию этот критерий?
12 Кб, 332x692
#593 #932252
Решил поковыряться в массиве в боевом коде напрямую как в объекте через ссылку. Хуй знает как так получилось, но словил какой-то баг или особенность языка которую я не знал, что тупил целый час в итоге выискивал в чем там дело. Попытался этот "баг" сейчас на ideone воспроизвести что бы вам показать и в итоге нихуя.

Суть примерно в том, что в результирующем массиве должен был затираться элемент "6ab" и вместо него повторяться "5ab" еще раз.

Мб версия пыхи старая, мб еще что - не знаю, в общем кто поможет мб понять в чем обсер?
http://ideone.com/LMl108
932259
#594 #932259
>>932252

Для начала изучи внимательно предупреждение про ссылки и foreach тут http://php.net/manual/ru/control-structures.foreach.php

Не стоит использовать ссылки если ты не понимаешь до конца как они работают и не прочел целиком раздел мануала про них.
#595 #932297
задача про студентов выглядит примерно как гайд "как нарисовать сову", подскажите как мне за нее взяться или что почитать если только прошел предыдущие уроки ОПа
932334932781936773
2666 Кб, Webm
#596 #932334
>>932297
для начала установи апач\нгинкс, пхп и базу данных. Настрой все это, чтобы работало. Потом можешь начать с создания страницы с прикрученным к ней бутстрапом. Дальше расширяй и наполняй контентом. Аноны кидают тут свои гитхабы, можешь посмотреть как они делают.
#597 #932343
Не нашёл JS тред, куда-то он уплыл с концами.
У меня какая-то попобава. Если вставляю в html скрипт, например
<input type="text" id="input">
<script>
input.onblur = function() {
console.log("ок");
};
</script>

то он работает. А если вынести его в отдельный файл, подключив его в шапке
<script type="text/javascript" src="core.js"></script>
то не работает. В консоль браузера сразу при загрузки страницы падает
ReferenceError: input is not defined

В другом месте вот такая функция не работает с той же ошибкой:
$(function(){
$('td, .table-cell').click(function(e){//ловим элемент, по которому кликнули
//....
});
});
Перечитал, как нужно js-скрипты в отдельный файл выносить - никаких особых камней там нет. Подключай сверху, да выноси на здоровье. Не понимаю.
932344932461932749
#598 #932344
>>932343
Да, добавлю, что на соседнем сайте точно такие же скрипты работают нормально.
932401932408
#599 #932401
>>932344
Там есть таки подводный камень, в общем у тебя js подключен в шапке, то там должны быть проверки на то что js ждет построения DOM дерева, иначе он будет пытаться выполниться до того как у тебя собственно html отрисовался и ссылаться на несуществующие id или class'ы на html странице.

А вообще ты возможно с путями проебался, попробуй в корень сайта кинуть а не в ту же папку в которой html лежит, ладно я хуевый советчик, простите :(
933021
#600 #932408
>>932344
скрипты в самом низу подключай
933021
#601 #932458
>>931331
>>931333
Спасибо, на днях попробую переделать.
#602 #932461
>>932343
Каково оно учить JavaScript в 2016?

https://habrahabr.ru/post/312022/
933021
2767 Кб, 1440x1080
#603 #932473
Прошу глянуть код гостевоху и надавать мне каких-нибудь советов, чтобы избежать ошибок, да хоть по оформлению кода, пока не стал пилить дальше
https://github.com/grigoryMovchan/zuihitsu
#604 #932556
Чому тред такой мертвый? Еле доскроллил до него. Подскажите гайдов по парсингу html-страниц. Хочу сделать страницу с ценами конкурентов.
932561932676932781
#605 #932561
>>932556

> Подскажите гайдов по парсингу html-страниц. >Хочу сделать страницу с ценами конкурентов.


А смысл? Все будет ломаться при малейших изменениях в верстке.
932566
#606 #932566
>>932561
Ну так починить не долго, тем более там сайты работают годами на одних и тех же cms и с одной и той же версткой. Просто реально заебывает руками перебирать всех и смотреть кто начал демпинговать.
932781
#607 #932676
>>932556
Если знаком с DOM и CSS-селекторами, то просто ставишь Goutte: https://github.com/FriendsOfPHP/Goutte или аналог, и парсишь без задней мысли что нужно.
#608 #932704
Здравствуйте, не нашел тред по JS, установил Subline, поставил туда Package Control, установил Emmet, но чет когда нажимаю восклицательный знак и таб - никуя не происходит. Что делать?
932728932781
#609 #932728
>>932704
Разобрался, какой плагин поставить на саблайн, чтоб пхп юзать.
#610 #932749
>>932343

Файлы (HTML, JS) не могут загрузиться мгновенно. Они загружаются с какой-то скоростью.

Браузер парсит (разбирает) HTML и картинки поточно, по мере поступления (а вот JS и CSS файлы он сначала загружает целиком, а только потом применяет их).

Соответственно, когда у тебя скрипт в шапке получается такая ситуация:

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

Почитай статьи про то как работает браузер, например эти

- https://learn.javascript.ru/onload-ondomcontentloaded
- http://javascript.ru/tutorial/events/timing#zagruzka-stranicy
- https://learn.javascript.ru/external-script
- http://webknowledge.ru/kak-rabotaet-brauzer-chto-proishodit-za-kulisami-sovremennyh-brauzerov/

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

- обработчик ставится на инпут не сразу, а только когда загрузится весь HTML файл. Какое-то время страница не будет реагировать на клики, и тд (я очень часто такое вижу). Еще хуже, кстати, когда JS скрипт при инициализации изменяет верстку и она прыгает в момент его срабатывания. Это указывает на уровень профессионализма фронтенд-специалиста.
- если в коде ты ссылаешься на функции из файла, ну например <button onclick="something()"> то до загрузки скрипта клик по кнопке будет вызывать ошибку

Некоторые подключают скрипт в начале, но делают инициализацию по событию document.ready (оно срабатывает когда браузер разобрал HTML файл до конца и создал все дерево ДОМ). Этот подход имеет такой же недостаток.

Мне в голову пришел такой способ:

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

Также, можно использовать классические обработчики в HTML атрибутах: <button onclick="doSomething()">. Этот метод не всегда подходит (плохо стыкуется с ООП кодом).

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

И что интересно, мало где описывается то, что я написал. Такая вот индустрия, такие вот люди в ней работают. Прыгающая верстка и не сразу работающие кнопки это норма для них. Вот киви кошелек например, на нем кнопки начинают работать только после загрузки страницы целиком. Зато у них используется ангулар и все на аяксе. А твиттер это вообще один большой сборник антипаттернов по построению интерфейсов. Кнопка "назад" в нем работает как генератор случайных чисел и никогда не знаешь, куда она тебя приведет. Алсо, меня периодически перебрасывает на мобильную версию по непонятной причине.
#610 #932749
>>932343

Файлы (HTML, JS) не могут загрузиться мгновенно. Они загружаются с какой-то скоростью.

Браузер парсит (разбирает) HTML и картинки поточно, по мере поступления (а вот JS и CSS файлы он сначала загружает целиком, а только потом применяет их).

Соответственно, когда у тебя скрипт в шапке получается такая ситуация:

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

Почитай статьи про то как работает браузер, например эти

- https://learn.javascript.ru/onload-ondomcontentloaded
- http://javascript.ru/tutorial/events/timing#zagruzka-stranicy
- https://learn.javascript.ru/external-script
- http://webknowledge.ru/kak-rabotaet-brauzer-chto-proishodit-za-kulisami-sovremennyh-brauzerov/

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

- обработчик ставится на инпут не сразу, а только когда загрузится весь HTML файл. Какое-то время страница не будет реагировать на клики, и тд (я очень часто такое вижу). Еще хуже, кстати, когда JS скрипт при инициализации изменяет верстку и она прыгает в момент его срабатывания. Это указывает на уровень профессионализма фронтенд-специалиста.
- если в коде ты ссылаешься на функции из файла, ну например <button onclick="something()"> то до загрузки скрипта клик по кнопке будет вызывать ошибку

Некоторые подключают скрипт в начале, но делают инициализацию по событию document.ready (оно срабатывает когда браузер разобрал HTML файл до конца и создал все дерево ДОМ). Этот подход имеет такой же недостаток.

Мне в голову пришел такой способ:

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

Также, можно использовать классические обработчики в HTML атрибутах: <button onclick="doSomething()">. Этот метод не всегда подходит (плохо стыкуется с ООП кодом).

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

И что интересно, мало где описывается то, что я написал. Такая вот индустрия, такие вот люди в ней работают. Прыгающая верстка и не сразу работающие кнопки это норма для них. Вот киви кошелек например, на нем кнопки начинают работать только после загрузки страницы целиком. Зато у них используется ангулар и все на аяксе. А твиттер это вообще один большой сборник антипаттернов по построению интерфейсов. Кнопка "назад" в нем работает как генератор случайных чисел и никогда не знаешь, куда она тебя приведет. Алсо, меня периодически перебрасывает на мобильную версию по непонятной причине.
933021
0 Кб, 54x36
#611 #932754
аноны, плиз, помогите

имею кусок кода:

$text = preg_replace_callback('/(?<=^|>)[^><]+?(?=<|$)/', [????], $text);

function replace($text, $pattern, $tag) {
return preg_replace('/'. $pattern .'/', $tag, $text);
}

как мне написать параметр [????], чтобы передать в callback функцию необходимые параметры?
0 Кб, 26x26
0 Кб, 26x26
#612 #932755
>>931338

http://ideone.com/oDVbum можно ли делать вот такой return false как у меня в 14 и 16 строке? Не выбрасывать же исключение, если пользователь мисскликнул флагом по открытой клетке. На счет значка не совсем тебя понял что с ним делать. Это пикрелейтед 2 когда идет mousedown, и пик1 когда mouseup.

http://ideone.com/B91hZ0 перенес dom-заботы во View. Это нормально, что я всегда кидаю координаты из event.dataset к вызову любой функции func? Не знаю еще каким образом их можно передать из контроллера в представление.
#613 #932756
>>932755

14 и 26 строке
#614 #932761
Изучаю адаптивную вёрстку и заметил, что не получается уменьшить окно браузера меньше чем дом 480 пикселей примерно. Почему так? На видео вижу как люди уменьшают его до практически до 1 пикселя. Пробовал на всех браузерах.
932781
#615 #932765
>>932755

> можно ли делать вот такой return false



Смутно догадываюсь что такая проверка и дальнейшее ничего-не-делание должна быть в контроллере..
#616 #932766
>>932755

Про значок вопрос относится ко второй ссылке на ideone. Извиняюсь за флуд, вначале пишу в тред, потом думаю.
#617 #932777
>>932755

> можно ли делать вот такой return false как у меня в 14 и 16 строке?


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

> this._flags.addCell(x, y);


> this._flagsCounter--;


А мы не можем вычислять число оставшихся флагов через разницу между числом мин и числом в this._flags? Можно было бы избавиться от лишнего поля и и риска его рассинхронизации с другими полями.

> На счет значка не совсем тебя понял что с ним делать. Это пикрелейтед 2 когда идет mousedown, и пик1 когда mouseup.


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

> this._domView.preventContextMenuOnField();


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

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

Вот, если что, про инкапсуляцию статья: http://learn.javascript.ru/internal-external-interface (я не призываю копировать стиль кода и скрытие переменных в замыкании, а просто почитать про суть инкапсуляции)

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

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

> Это нормально, что я всегда кидаю координаты из event.dataset к вызову любой функции func?


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


Из представления в котроллер, ты имел в виду? Да, можно через аргументы, можно сделать объект события, если хочется усложнить.
#617 #932777
>>932755

> можно ли делать вот такой return false как у меня в 14 и 16 строке?


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

> this._flags.addCell(x, y);


> this._flagsCounter--;


А мы не можем вычислять число оставшихся флагов через разницу между числом мин и числом в this._flags? Можно было бы избавиться от лишнего поля и и риска его рассинхронизации с другими полями.

> На счет значка не совсем тебя понял что с ним делать. Это пикрелейтед 2 когда идет mousedown, и пик1 когда mouseup.


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

> this._domView.preventContextMenuOnField();


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

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

Вот, если что, про инкапсуляцию статья: http://learn.javascript.ru/internal-external-interface (я не призываю копировать стиль кода и скрытие переменных в замыкании, а просто почитать про суть инкапсуляции)

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

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

> Это нормально, что я всегда кидаю координаты из event.dataset к вызову любой функции func?


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


Из представления в котроллер, ты имел в виду? Да, можно через аргументы, можно сделать объект события, если хочется усложнить.
937393
#618 #932778
>>932755

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

Тестировать естественно в первую очередь модель, это и проще, и полезнее.
#619 #932781
>>932761

Я проверил на Хромиуме, по ширине пустое окно ограничено 337 пикс, по высоте можно хоть 0 пикселей сделать. Фаерфокс - то же самое.

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

Ты можешь 1) увеличить масштаю, что уменьшит ширину 2) использовать режим тестирования адаптивной верстки, в Хроме это Ctrl + SHift + I -> иконка смартфона, в Фаерфоксе то ли пункт в меню, то ли кнопка в отладчике.

Еще ты можешь сделать iframe любого размера и в нем открыть свою страницу.

Под 1 пиксель проверять верстку не требуется. Проверяй на реалистичных разрешениях, http://mydevice.io/devices/

>>932704

Возможно тип файла не тот. Попробуй на html-файле. Или что-то в настройках не включено.

>>932566

Я сталкивался с таким, чинить придется постоянно, если много сайтов.

А яндекс-маркет не годится для этого? Я всегда там цены сравниваю.

И я помню, был какой-то сервис который давал API для извлечения цен.

>>932556

Изучи DOM, может быть Xpath, и возьми какую-нибудь библиотеку вроде phpQuery или как нижу упомянули, Goutte.

>>932297

Это прошел? https://github.com/codedokode/pasta/blob/master/soft/web-server.md

Комментарии и пояснения к студентам все прочел?

Туториал из php мануала прошел? http://php.net/manual/ru/tutorial.php

>>931986

В БД надо хранить как DATE, DATETIME, TIMESTAMP.

>>931930

PHP может не самый идеальный, но если ты его уже знаешь то его взять будет легче.

А так, да, bat/bash/powershell/python - что-то из этого.

>>931876

не зная в чем проблема - вряд ли.

>>931843

CSS3 это дополнения к CSS2.1. То есть тени или скругления это новое, а расчет ширины/высоты элемента идет по тем же принципам.

>>931777

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

Если ты думаешь, что проблема в password_hash то просто протестируй ее, дай ей что-нибудь и проверь что будет на выходе.

>>931369

Есть, я видел такие курсы, в том числе бесплатные. Ссылок не помню, погугли.
#619 #932781
>>932761

Я проверил на Хромиуме, по ширине пустое окно ограничено 337 пикс, по высоте можно хоть 0 пикселей сделать. Фаерфокс - то же самое.

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

Ты можешь 1) увеличить масштаю, что уменьшит ширину 2) использовать режим тестирования адаптивной верстки, в Хроме это Ctrl + SHift + I -> иконка смартфона, в Фаерфоксе то ли пункт в меню, то ли кнопка в отладчике.

Еще ты можешь сделать iframe любого размера и в нем открыть свою страницу.

Под 1 пиксель проверять верстку не требуется. Проверяй на реалистичных разрешениях, http://mydevice.io/devices/

>>932704

Возможно тип файла не тот. Попробуй на html-файле. Или что-то в настройках не включено.

>>932566

Я сталкивался с таким, чинить придется постоянно, если много сайтов.

А яндекс-маркет не годится для этого? Я всегда там цены сравниваю.

И я помню, был какой-то сервис который давал API для извлечения цен.

>>932556

Изучи DOM, может быть Xpath, и возьми какую-нибудь библиотеку вроде phpQuery или как нижу упомянули, Goutte.

>>932297

Это прошел? https://github.com/codedokode/pasta/blob/master/soft/web-server.md

Комментарии и пояснения к студентам все прочел?

Туториал из php мануала прошел? http://php.net/manual/ru/tutorial.php

>>931986

В БД надо хранить как DATE, DATETIME, TIMESTAMP.

>>931930

PHP может не самый идеальный, но если ты его уже знаешь то его взять будет легче.

А так, да, bat/bash/powershell/python - что-то из этого.

>>931876

не зная в чем проблема - вряд ли.

>>931843

CSS3 это дополнения к CSS2.1. То есть тени или скругления это новое, а расчет ширины/высоты элемента идет по тем же принципам.

>>931777

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

Если ты думаешь, что проблема в password_hash то просто протестируй ее, дай ей что-нибудь и проверь что будет на выходе.

>>931369

Есть, я видел такие курсы, в том числе бесплатные. Ссылок не помню, погугли.
936773
#620 #932828
PHPч, существуют ли какие нибудь API в открытом доступе для совершения переводов средств между клиентами банковских систем типа сбербанк, альфа-банк, запсибкомбанк? А то пока что я увидел только то, что банки просто так не выдают API. С кем то (сбербанк) нужно связываться и говорить, зачем нужен API, у альфа-банка вроде чуть попроще, но всё равно нужно получать токен приложения и всё такое.
934376
#621 #932831
Как в JavaScript принято писать моки для объектов определённого класса? В Sinon.js своё особое видение моков: https://stackoverflow.com/questions/26037940/mocking-class-in-sinon-js-and-instanceof

Как я понял, у них мок это объект, ожидающий, что на другом объекте (который передался в конструктор мока при создании) будут вызваны определённые методы:
var dep = {foo: function() {}};
var depMock = sinon.mock(dep);
dpeMock.expects("foo").once();

// передаём объект dep как зависимость тестируемого класса
...

// убеждаемся в том, что на объекте dep был вызван метод foo один раз:
depMock.verify()

А что делать если тестируемый объект проверяет переданные аргументы через instanceof? По ссылке на stackoverflow предлагают вместо этого преверять наличие только нужных методов, но это же неудобно, что если их много?
Делаю сейчас так:
var dep = {foo: function () {}, __proto__: FooClass.prototype}
// дальше то же, что и вверху
933012
#622 #933012
>>932831

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

Стандарт, который довольно трудно понять, говорит примерно то же:

https://www.ecma-international.org/ecma-262/5.1/#sec-11.8.6
https://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.3

> var dep = {foo: function () {}, __proto__: FooClass.prototype}


Это неправильно. __ proto __ не определена стандартами и не обязана работать везде и всегда.
#623 #933021
>>932401

>иначе он будет пытаться выполниться до того как у тебя собственно html отрисовался и ссылаться на несуществующие id или class'ы на html странице


Билять. Вот оно что.
А пути правильные, проверял уже (они и так в корне).
>>932408
Попробую.
>>932461
Хех, читал эту статью. Всё это хрень. Может на собеседованиях и спрашивают, а реально нет смысла гнаться за трендом. Делай так, как работает, и хрен с ним. Заказчику глубоко наплевать. Да и как по мне, самый простой код - самый лучший. Если можно обойтись без усложнения, то лучше это сделать.
>>932749

>- сделать JS файл, содержащий только функции, но не ставящий никаких обработчиков никуда


>- подключить его в шапке


>- сразу после инпута поставить вызов функции инициализации внутри тега script


Пожалуй, этот способ самый оптимальный, так и сделаю.

И ведь читал про выполнение кода со страницы, а про вызовы с конкретными id не дошло. Решил, что раз функция срабатывает после некоего события, то до события этот кусок кода просто не используется. А когда используется, все id уже поименованы. Окей, мне стало понятнее.
933161
#624 #933026
Сап, пхпач, помогай. Не знаю как реализовать класс с текучим интерфейсом (fluent interface). да, это моё тестовое задание. остальные сделал, а это в душе не ебу как.

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


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

$o = new JsonFluent('{"first":"apple","second":"banana","third":{"sub1":1,"sub2":2,"sub3":3}}');
$o->get('first'); // Вернёт 'apple'
$o->get('third')->get('sub2'); // Вернёт 2
933161933165
#625 #933058
Вопрос к ОПу. Вот он пишет, что тех кто говорит про то что одинарные кавчки быстрее двойных, надо пинком скидывать с крыш многоэтажки. Но ведь они и правда быстрее: в двойных кавычках пхп проверяет наличие переменных, а в одинарных не ожидает их встретить. В чем я не прав?
933161933178
#626 #933161
>>933021

Не, JS это не декларативный язык вроде CSS и конструкция

$('#abc').click(...);

это именно команда: найти все элементы с id = abc, которые есть в данный момент, и повесить на них обработчик. Она не повесит обработчики на добавленные в DOM позже элементы.

>>933026

Текучий интерфейс это когда все методы возвращают this. Мне это не нравится, бессмысленное увеличение кода.

>>933058

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

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

echo 'a=' . $a . ', b = $b'. ...

И это ухудшение не стоит нескольких нано- или микросекунд.

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

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


А это важно только на этапе компиляции. При использовании кеширования опкодов (opcache) компиляция длеается только один раз, а дальше скомпилированный скрипт берется из кеша и разницы не будет (как мне кажется).

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

> php -dvld.active=1 -r 'echo "Hello world";'


line # E I O op fetch ext return operands
-------------------------------------------------------------------------------------
1 0 E > ECHO 'Hello+world'
1 > RETURN null

Как видим, наш код скомпилировался в 2 инструкции, echo и return.

Теперь поменяем вид кавычек:

line #
E I O op fetch ext return operands
-------------------------------------------------------------------------------------
1 0 E > ECHO 'Hello+world'
1 > RETURN null

Как видим, коды после компиляции получились точно такие же.

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

> php -dvld.active=1 -r 'echo "Hello $x world";'



line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
1 0 E > ADD_STRING ~0 'Hello+'
1 ADD_VAR ~0 ~0, !0
2 ADD_STRING ~0 ~0, '+world'
3 ECHO ~0
4 > RETURN null

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

Поскольку форматирование могла сбиться, скопирую пост на pastebin: http://pastebin.ru/NhNjneDP
#626 #933161
>>933021

Не, JS это не декларативный язык вроде CSS и конструкция

$('#abc').click(...);

это именно команда: найти все элементы с id = abc, которые есть в данный момент, и повесить на них обработчик. Она не повесит обработчики на добавленные в DOM позже элементы.

>>933026

Текучий интерфейс это когда все методы возвращают this. Мне это не нравится, бессмысленное увеличение кода.

>>933058

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

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

echo 'a=' . $a . ', b = $b'. ...

И это ухудшение не стоит нескольких нано- или микросекунд.

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

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


А это важно только на этапе компиляции. При использовании кеширования опкодов (opcache) компиляция длеается только один раз, а дальше скомпилированный скрипт берется из кеша и разницы не будет (как мне кажется).

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

> php -dvld.active=1 -r 'echo "Hello world";'


line # E I O op fetch ext return operands
-------------------------------------------------------------------------------------
1 0 E > ECHO 'Hello+world'
1 > RETURN null

Как видим, наш код скомпилировался в 2 инструкции, echo и return.

Теперь поменяем вид кавычек:

line #
E I O op fetch ext return operands
-------------------------------------------------------------------------------------
1 0 E > ECHO 'Hello+world'
1 > RETURN null

Как видим, коды после компиляции получились точно такие же.

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

> php -dvld.active=1 -r 'echo "Hello $x world";'



line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
1 0 E > ADD_STRING ~0 'Hello+'
1 ADD_VAR ~0 ~0, !0
2 ADD_STRING ~0 ~0, '+world'
3 ECHO ~0
4 > RETURN null

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

Поскольку форматирование могла сбиться, скопирую пост на pastebin: http://pastebin.ru/NhNjneDP
#627 #933165
>>933026

А, хотя в твоем случае надо писать не return $this. Подумай сам, что надо возвращать. Или поищи готовые аналогичные библиоетки, например, phpQuery какой-нибудь.
933179
#628 #933178
Я не >>933058, но сделал маленький тест.
Сгенерил миллион строк в php 7.1:
3 подстановки vs 6 конкатенаций (оно вообще употребляется во множественном числе?).
Подстановки отрабатывают на 15-20% быстрее.
#629 #933179
>>933165
Да, мне уже подсказали. Возвращать нужно new JsonFluent($data).
#630 #933198
Пытаюсь разобраться с шифрованием. Не могу понять на чём путаюсь.

Допустим я хочу написать сервис по обмену сообщениями, и при этом хочу чтобы эти сообщения ни кто не мог прочитать кроме собеседников. Никогда! Вообще!

Я ознакомился что для шифрование применяется при помощи ключа. Но где хранить этот ключ? Если сохранить его в БД, то доступ будет не только у собеседников, но и у тех у кого есть доступ к БД.
Нужно сделать так чтобы ключ оставался только у собеседников. Может для этого выступить сам пароль от сервиса? Сомневаюсь что это будет надежно, потому что пользователи вряд ли будут делать пароли длиннее, к примеру, 12 символов.
933203
#631 #933203
>>933198

Попробуй почитать для начала про такие вещи:

- симметричное и асимметричное шифрование
- открытый и закрытый ключ
- протокол Диффи-Хеллмана

Почитай про то, как устроен протокол SSL.
933317
#632 #933249
Можно ли PHP скрипт превратить в исполняемый файл (.exe)?
933308
#633 #933308
>>933249
Боюсь себе даже представить зачем такое кому-то может понадобится.
#634 #933317
933493
#635 #933493
>>933317

1) ^ это операция XOR, а не возведение в степень. Не перепутал?
2) при возведении в степени вроде 10 000 получаются гигантские числа. PHP такие числа хранит в float формате, который сохраняет 8-16 знаков из числа, а нужно точное представление. Потому надо брать расширения для работы с большими целыми числами:

http://php.net/manual/ru/book.gmp.php
http://php.net/manual/ru/book.bc.php

Также, ты используешь для генерации случайных чисел rand(). Она использует линейный генератор ( https://ru.wikipedia.org/wiki/Линейный_конгруэнтный_метод ) который довольно предсказуем. Нам нужно что-нибудь получше, а именно:

http://php.net/manual/ru/function.openssl-random-pseudo-bytes.php
http://php.net/manual/ru/function.random-bytes.php

Также, потом советую глянуть расширение openssl, содержащее готовые функции шифрования (но сначала попробуй написать свою): http://php.net/manual/ru/book.openssl.php

Насчет кода - должны получиться именно одинаковые числа. Потому что (x ^ y) ^ z = (x ^ z) ^ y. Остаток от деления нужен для того, чтобы неприятель не мог догадаться, какие были исходные числа, проведя обратную операцию.
934039
#636 #933496
Анончик, если я отправляю ajax-запрос к php-файлу, в котором есть редирект header('Location'), то редирект произойдёт?
937461
#637 #933564
Нужда заставит, ещё и не такое говно придётся выучить.
933610
sage #638 #933610
>>933564
Просто ради просвещения: что, по Вашему мнению, можно хотя бы с натяжкой отделить от говна в таком случае?
#639 #933639
Кто что думает по поводу отмирания MVC во фронтенде?

https://habrahabr.ru/company/tuturu/blog/321820/
937461
#640 #933643
Нет, всё равно попобава. С JS-функциями.
В index.php стоят две одинаковые кнопки:
<div><a href="javascript:void(0)" onclick="show_flights_table()" id="a_save_object" class="a_demo_three b_green" title="Показать таблицу">Показать таблицу</a></div>
и
<div><a href="javascript:void(0)" onclick="add_line_in_flights_table()" id="a_save_object" class="a_demo_three b_green" title="Добавить строку">Добавить строку</a></div>
Там же в хидере подключён скрипт
<script type="text/javascript" src="core.js">
В core.js стоят функции
function show_flights_table()
{
...
}

и такая же
function add_line_in_flights_table()
{
...
}

Нажимаем первую кнопку - всё ок, никаких варнингов, браузер показывает таблицу. Нажимаем вторую - хром ничего не делает, выдаёт
Uncaught ReferenceError: add_line_in_flights_table is not defined at HTMLAnchorElement.onclick (index.php:54)
А если запустить через файерфокс, то вторая кнопка срабатывает. Правда, там дальше начинает ругаться на $(div).html(data); (ReferenceError: $ is not defined[Подробнее] core.js:262:5), но это уже другой вопрос.
Я даже пробовал стирать из второй функции вообще всё между { }. Всё равно not defined. Да как так-то?
933654
#641 #933654
>>933643
Я думаю, из-за 2 одинаковых id подряд.

> onclick="show_flights_table()" id="a_save_object"


>onclick="add_line_in_flights_table()" id="a_save_object"



Скорее всего ты намешал там где то джиквери.
когда ты вызываешь "onclick='function()'", она должна быть в глобальной области видимости (принадлежать объекту window), возможно твои функции обернуты во что то, хз, покажи код хоть.

Ну и еще:

>a href="javascript:void(0)"


Если нет ссылки, почему бы просто не опустить параметр href?
933684
#642 #933673
Ребят, подскажите, пожалуйста, как установить на локальный сервер Mail_Mime?
937461
#643 #933684
>>933654

>Если нет ссылки, почему бы просто не опустить параметр href?


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

>Я думаю, из-за 2 одинаковых id подряд.


Да, есть такое. Исправил. Но ошибка та же.

>Скорее всего ты намешал там где то джиквери.


Чего нет, того нет. По нажатии на кнопку запускается js-скрипт, оттуда аяксом запускается php-скртипт и выполняет что-то там с базой. Раньше так делал, всё работало нормально.

Код примерно такой (я убрал лишние блоки и функции для удобочитаемости): https://jsfiddle.net/jou5Ljyj/
933735937461
#644 #933707
Сап аноны, нужна помощь. написал сайт на yii2. для мультиязычности юзаю куки и сессии ,но какого-то черта yii перезаписывает мою куку для языков чем-то вроде этого
ef2e3b878bea166e1a349599475821d6b94b13cb609c8db980144ff065535613a:2:{i:0;s:5:"_csrf";i:1;s:32:"Q7hju019PJ61cOMbR1Y4Bm9V4stpWCpU";}
я не ебу что это такое ( ну только догадываюсь)
что-то связанное с безопасностью.
кто знает как с этим бороться, что делать?
937461
#645 #933735
>>933684
Вообще, я тоже для всяких интерактивных элементов использую тег "<a>" без href (НО ТАК НЕ НАДО ДЕЛАТЬ, лол). Например для кнопок есть "<button>" и т.п.

У тебя там жесть какая то в примере. Вот сравни я упростил: https://jsfiddle.net/Lwv50ps3/ - так работает. Вопрос, почему у тебя функции не попадают в глобальную видимость. Если ты там прямо из проекта скопипастил кусок кода, то у меня для тебя плохие новости: ты ничего не понимаешь в хтмл, no offence
933777
#646 #933777
>>933735
Это пока не проект, а просто разрозненные куски кода.

Не понял, зачем после функций вставлять такие строки?
window.add_line = add_line;

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


Скорее, почему одна попадает, а вторая (точно такая же) нет.
933780
#647 #933780
>>933777
Ну как бы я эту функцию прикрепил к глобальной видимости (window). А иначе она бы не запустилась на jsfiddle, с той же ошибкой что у тебя.

>Скорее, почему одна попадает, а вторая (точно такая же) нет.


Да, вот это. Может кто поумнее объяснит нам позже.
933782
#648 #933782
>>933780
Ящитаю, это какой-то глюх Хрома. Может быть даже конкретно моего. ФФ даже не морщится.

>прикрепил к глобальной видимости (window)


И ничего страшного, что прикрепление происходит после самой функции? При чтении, браузер читает сначала всё, что вне функций, а только потом их, так вроде?
933826
#649 #933802
Анон, помоги, пжлст.
Почему программа некорректно считает среднее значение тугриков/страниц ? 296 строка

http://sandbox.onlinephpfunctions.com/code/e7ac3081e037c3c3e6b0064d3feb1589d3da0721
937461
#650 #933826
>>933782

>И ничего страшного, что прикрепление происходит после самой функции? При чтении, браузер читает сначала всё, что вне функций, а только потом их, так вроде?


Первый раз слышу, если честно. Никогда никаких проблем не было с таким подходом.
#651 #933931
Есть ли еще мануалы по битриксу кроме официальной документации? Как-то тяжеловато читается. Можно и в видео-формате.
#652 #933994
Обработка GET и POST запросов должна происходить в разных методах с точки зрения MVC? Допустим есть страница с формой. Если приходят по гет, то просто рисуем вид, а если пост, то нужно обработать. Посылать ли в этом случае с формы на другой action чтобы обрабатывать его другим методом? По идее так и надо делать, т.к. метод должен выполнять одну ф-цию
934007
#653 #934007
>>933994

> в разных методах с точки зрения MVC?


В разных методах класса-обработчика.

>Если приходят по гет.


То обрабатываем обработчиком и контроллеру отдаем решать что с ним делать.

>а если пост


то обрабатываем обработчиком и отдаем контроллеру решать что с ним делать.
934081937461
#654 #934039
>>933493

>gmp_powm


Эта функция была специально придумана для этого алгоритма?

Теперь всё получилось: https://ideone.com/I0LCYo
Завтра постараюсь задать вопросы, после того как осознаю алгоритм.

Спасибо!!!
934824937461
#655 #934081
>>934007

>класса-обработчика.


Что под этим подразумевается? Обычно роутинг настроен так, что запрос от пользователя попадает в метод контроллера (экшн). Меня интересует в разных ли экшенах обрабатывать гет и пост запрос для одной страницы, учитывая, то если запрос гет, то там нужно только вид отрендерить.
934091934104
#656 #934091
>>934081

В форме удобнее обрабатывать и ГЕТ и ПОСТ одной функцией. Почитай например https://github.com/codedokode/pasta/blob/master/forms.md
#657 #934104
>>934081
Нет принципиальной разницы: можно в одном экшне, можно в разных. Если у тебя там мало кода, то, как по мне, проще читать один экшн, да и разделение на 2 экшна вынудит копипастить код.
#658 #934122
Анон, помоги решить проблему. Есть ajax-запрос, который отправляет данные к php-файлу. В этом php-файле идёт валидация данных, после чего эти данные записываются в переменную $_SESSION в виде json-массива. Как только это происходит, в теле функции .done() в ajax-запросе происходит переход на поддомен, на котором пыха знать не знает о сессии. То есть, сессия просто NULL. В чём могут быть подводные камни кросдоменных сессий? И какого хуя моя сессия не передаётся на поддомен?
934139
77 Кб, 1708x801
#659 #934134
В чем ошибка?
934137
#660 #934137
>>934134
После case должна быть не точка с запятой, а двоеточие. И нахуя ты используешь альтернативный синтаксис, если у тебя сплошной код без разрывов?
#661 #934139
>>934122

Как по-твоему работают сессии? Откуда берутся и куда сохраняются данные из массива $_SESSION в начале и после завершения скрипта?
934143
#662 #934143
>>934139
Это суперглобальная переменная, которая хранится вне зависимости от домена. Главное, чтобы на одном сервере. Кстати, проблему решил буквально только что одной строчкой кода:

$some_name = session_name("some_name");

Сука, 5 часов проводил раскопки на StackOverflow
934146
#663 #934146
>>934143

Нет, тебе сначала надо изучить механизм работы сессий (прежде чем его вообще использовать) так как ты его явно не понимаешь. Сессия это не переменая. $_SESSION это лишь механизм для доступа к одной сессии из хранилища.
86 Кб, 900x900
#664 #934181
Хочу прокачать свой английский в техническому плане, кто как осваивал его?
На каком уровне нужно знать пхп, чтоб устроиться на стажировку?что обычно спрашивают на собеседовании, что нужно делать стажировке.
934504937461
#665 #934376
>>932828
Я слышал только про Робокассу, не знаю, есть ли там нужный тебе функционал.
#666 #934429
ОП, проясни пожалуйста механизм работы реалтайм-индексов в sphinx. Как я понял, эти индексы непосредственно к таблице никакого отношения не имеют и создаются только внутри сфинкса, так? То есть, применительно к задаче на файлообменник, для того чтобы эти индексы заполнялись при добавлении файла, дополнительно к запросу на заполнение полей таблицы нужен еще и запрос для заполнения реалтайм-индекса? Далее, при использовании реалтайм-индекса невозможно сразу получить все поля строки, т.е. если у нас проиндексировано только имя файла, то сфинкс отдаст в виде результата поиска только айдишник(и), по которым придется еще раз делать запрос, но уже непосредственно в БД, для извлечения строк с найденными сфинксом айди? Или нужно все поля в индекс загонять?
937459
#667 #934504
>>934181
читать со словарем, плюс смотреть ютуб и т.д. практика короч. если есть желание фундаментально прокачаться, еще нужно добавить какой-нить видеокурс по произношеию типа american english и учебник по грамматике, допустим English Grammar by Raymond Murphy. я английский знаю норм (не считая литературного), но моей главной проблемой является лень читать на английском, если есть страница на русском, потому что для обработки английского текста требуется больше усилий, даже если все слова известны. но перебарываю себя, надеюсь, однажды эта разница сгладится и мне будет похуй, на каком языке читать.

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

>> На каком уровне нужно знать пхп, чтоб устроиться на стажировку?


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

плюс учебные проекты, которые у тебя есть, нужно максимально причесать, чтобы не говорить "вот тут такой-то функционал не работает, потому что это учебный проект"
934653
29 Кб, 329x449
#668 #934653
>>934504
Если просят, чтоб был опыт в коммерческой деятельности, можно ли обойти это на собеседовании ?
С каким редактором лучше работать?(пхпшторм не вариант)
934654934701936017
#669 #934654
>>934653
Почему пхпшторм не вариант? Единственная нормальная IDE. У меня как-то коллега в саблайме писал, так я подходил к нему и просто охуевал с того, как он каждый класс в глобальном поиске ищет.
934659934662936017
#670 #934659
>>934654
Сабжей для покупки нет, ибо школьник.
936977
#671 #934662
>>934654

Sublime 3 умеет переходить к классу и функции по имени. А к файлам по имени умеет переходить Sublime 2. Не понимаю, зачем там поиск. Наверно чтобы найти все случаи использования класса.
#672 #934697
Поясните за Битрикс, насколько он норм/(не норм), за какое время примерно можно выучить?
934703
#673 #934701
>>934653
если просят чтоб был опыт, то нужно либо соврать, что он был (что вполне реально, допустим найти левый сайт вебстудии и сказать, что клепал там визитки и интернет магазины), но могут заебать вопросами и спалить, либо сказать, что опыта нет, но я вот умею то и это, вот мои готовые проекты. я бы выбрал второй вариант.

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

кстати на собеседовании также могут спросить, каким ide пользуешься, явно ожидая, что ты скажешь "штормом". у меня так и было.
#675 #934750
Чому при записи кириллических символов в сессию они потом отображаются в виде Юникода? Например, вот это \u041c\u043e\u0441\u043a\u0432\u0430 = Москва.
937458
#676 #934824
>>934039
Я только что понял что значит этот алгоритм. Я думал что среди аргументов есть само сообщение которое нужно зашифровать, и алгоритм конкретно предназначен именно для этого, но оказалось что он только генерирует ключ по которому сообщение будет шифроваться.

Хорошо, на вопрос как одним из способов шифруются сообщения мы ответили, но что если помимо обмена сообщений, я хочу, чтобы сообщения навсегда сохранялись в БД. Если сессия(?) прекратит свое существование, то все параметры который нужны для алгоритма будут утрачены.
Я вижу только один вариант с хранением этих параметров или самого ключа в БД. Но я, опять же, тут наступаю на свой хвост: Если ключ храниться в БД, то возможность расшифровать сообщения есть не только у собеседников, но и у тех у кого есть доступ к этой самой БД.
Есть ли какие-нибудь решения этой проблемы или я хочу невозможного?
934864934871934872
#677 #934864
>>934824

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

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

В общем, подумай, что тебе нужно: нужно ли хранить историю, кто должен иметь доступ к сообщениям и тд.
#678 #934871
>>934824

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

- telegram (англ) https://core.telegram.org/api/end-to-end
- https://core.telegram.org/mtproto
- протокол приложения signal (англ) https://en.wikipedia.org/wiki/Signal_Protocol

Также, прочитай про SSL (это слой шифрования, который например используется в HTTPS).
#679 #934872
>>934824

Если ты хочешь хранить сообщения на сервере (для истории и синхронизации), то надо хранить их зашифрованными. А ключ хранить где-то в другом месте. Но может быть лучше вооще их не хранить? Или хотя бы спрашивать пользователя, хочет ли он вести запись истории или нет. Программа, которая уважает приватность пользователя, не должна ничего записывать без его согласия.
142 Кб, 1366x768
77 Кб, 1366x768
#680 #934915
Посоны, решаю задачу из самоучителя, ответ ровно 61270 должен выйти, или нет?
934917937458
#681 #934917
>>934915
Алсоу, задача про школьный кредит на айфон.
934921
#682 #934921
>>934917
61270 с копейками
934922
#683 #934922
>>934921
ебанный в рот...
934924
#684 #934924
>>934922
думаешь проценты не надо считать раз последний месяц?
934925934927
54 Кб, 471x582
#685 #934925
>>934924
Хм, сейчас чекну.
113 Кб, 400x234
#686 #934927
>>934924
О!! Бля, как я заебался. С десяти вечера сижу. Добра, анон.
195 Кб, 960x720
#687 #935100
>>919074 (OP)
Реквестирую гуру книжного php. обмазался за много лет пиком, но так и не начинал читать. сейчас думаю с чего начать, может быть анон мне в этом поможет? хотел бы услышал порядок прочтения этих многобукав
#688 #935104
>>935100
Из всего этого списка говном не отдает только орейли
978 Кб, Webm
#689 #935254
>>935100

>> PHP5 TOP SECRET


ШОК! АЛЛА ПУГАЧЕВА ВЫУЧИЛА ПХП ВО СНЕ БЛАГОДАРЯ.....
#690 #935357
>>935100
я когда спрашивал про книги у своего препода по этому делу (его квалификация у меня сомнений не вызывает, работает тимлидом), он говорит все переведенные книги по php - неактуальное говно, которым надо топить печь. думаю он имел в виду примерно такую литературу, как на картинке.

а рекомендовал он например такие книги:
роберт мартин "чистый код"
роберт мартин "идеальный программист"
чет фаулер "программист-фанатик"
935364
#691 #935364
>>935357
Смысла начинать с этих книг нет.
935512
#692 #935512
>>935364
а с каких есть?
935518936033
#693 #935518
>>935512
Орайли с фотки выше, да и в шапке инфы полно. Начать учить язык очень легко, хоть на codecademy курсы проходи, тяжело будет дальше.
#694 #935535
Аноны, установил apache2, php, mysql-server, mysql-client, phpmyadmin на убунту 16.04. При переходе на localhost/phpmyadmin/ отображается php файл как есть, т. е. не интерперетируется. Что я сделал не так?
935559937458
#695 #935559
>>935535
Какай то гайд использовал? ПХП до апача ставил? Зачем тебе pma?
#696 #935916
как можно работая в шторме настроить браузер (или сам шторм), чтобы при изменении php кода в файле браузер рефрешился? live edit, насколько я понял, работает только при редактировании html, css и js.

подскажите кто знает, а то уже заебался. не верю, что тут нет этого, в netbeans же был netbeans connector, который именно эту полезную функцию выполнял.
935919936120
#697 #935919
>>935916

Я не знаю, есть ли такая функция, но советую отвыкать от такого режима. Лучше сесть, все сделать, и потом проверять, чем обновлять страницу каждые 10 секунд. Если тебе надо отследить, как происходит выполнение кода по шагам, попробуй использовать отладчик.
#698 #935943
Что скажете насчет БЭМ?
935957935964
#699 #935957
>>935943
В пхп треде?
#700 #935964
>>935943

Система именования классов мне там нравится. Компоненты БЭМ у меня использовать повода и необходимости не было.
4 Кб, 472x56
Скидки #701 #936005
>>930671

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



Тогда предлагаю ввести дополнительную абстракцию. Например, нужно добавить такую скидку: если среди товаров есть A и B, то снизить их суммарную стоимость на 20 единиц (не процентов). То есть раньше у нас было "снижение стоимости" основанное на процентах, теперь добавляется "снижение стоимости" в виде фиксированного значения. Код в классе Calculator поменялся с

$totalPrice += $matchedPrice - $matchedPrice ✱ $discountResult->getPercent();

на

$totalPrice += $matchedPrice - $discountResult->getDepreciation();

Не мог подобрать нормального названия для "снижения стоимомсти". Ну и подход с новой абстракцией получился многословным.
https://bitbucket.org/learning_acc/discounts/src

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


А мне нужно это реализовывать?

https://2ch.hk/pr/res/898502.html#919067 (М)

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



Так по условию требуется их комбинировать, там ещё написано "Скидки применяются последовательно в порядке описанном выше."
http://www.cyberforum.ru/php-oop/thread1459985.html
937439
#702 #936017
>>934653
>>934654
Phpstorm никто вам на работах ставить не будет, дорого. Учите netbeans или eclipse, он везде. Как вариант notepad++, но это неудобно.
936119
#703 #936030
>>935100
Я бы на твоем месте не читал все это говно, а читал напрямую документацию на http://php.net/manual/ru/
Обязательный раздел справочник языка. Дальше читай книги в шапке (Шлосснгейл, Зандстра). Еще http://www.phptherightway.com/ хорош. PSR стандарты почитай на http://www.php-fig.org/psr/, научат код нормально оформлять и велосипеды не изобретать. Ну и пасты опа конечно все перечитать. Остальные твои книги на потом оставь, будешь читать в последнюю очередь, там все равно обычно ничему хорошему не научат. Зато если их в конце читать будешь, то сразу уже видно будет, когда тебе какое-нибудь говно навязывают, вместо общепринятых практик.
#704 #936033
>>935512
ООП освоить надо сначала на примере PHP. Зандстру читай из шапки, очень доступно объясняет. После него уже любая книга по паттернам нормально идет, он там в конце еще и упомянает, какие дальше прочесть можно.
#705 #936046
Все еще читаете книжки по php и решаете задачки? А люди вон раскрученные проекты запускают на php без всяких знаний:
https://habrahabr.ru/company/everydaytools/blog/322068/
https://github.com/AndreyAzimov/whentosurf/
936049936822
#707 #936084
Вкатываюсь в PHP. Поставил PhpStorm и Apache под линуксом. Смущает одна проблема: каждый раз перед запуском приходится деплоит каждый файл отдельно. Думаю, можно это делать как-то более удобно, но нагуглить не получается. Лучше всего чтобы можно было по одному нажатию сразу деплоить и запускать.
936090936822
#708 #936090
>>936084
http://www.phptherightway.com/#building_and_deploying_your_application

Ознакомься, в нормальных книгах все давно расписано.
936822
#709 #936119
>>936017
У тебя работа какая-то не очень правильная, мне с первого дня дали мак (на выбор еще убунта была), два здоровских монитора и лиценщионный шторм. Как можно вообще работать в эклипсе и небинс? Шторм на голову выше всех этих поделок
#710 #936120
>>935916
можешь сделать обновление страницы самостоятельное.
Можно через плагин для браузера.
Можно в редакторе Atom.
#711 #936123
Сап, аноны. Есть диплом, который написан на symfony. Препод сказал, что это слишком сложно для нашей шараги и нужно писать без фрейма. Что можно сделать, диплом достался нахаляву и писать заного вообще нет желания. В вебе я чуть умнее сапога.
936542
sage #712 #936205
Обычно не пользуюсь pecl'ем, но тут open source проект и автосборка с тестами. Такой вопрос: pecl.php.net всегда работает как говно или сегодня у него просто не тот день?
936255936822937438
#713 #936255
>>936205
Я как-то пытался в пекла поставить джёрмана на седьмую версию пхп, трахался где-то пару часов
937438
10 Кб, 507x269
#714 #936275
Всё утро пытался настроить phpunit в своём phpstorm, чтобы он распознавал классы юнит-тестирования. Пробовал и через встроенный композер, и вручную пфар указывал, перезапускал несколько раз, ничего не помогало: жаловася на Undefined class PHPUnit_Framework_TestCase. Потом залез в исходники пфара и посмотрел тамошние неймспейсы, вручную изменил нижние подчёркивания на бекслеши — и заработало. ~_~
Очевидно, проблема в каком-то автолоадере, который не обучен заменять подчёркивания на слеши. Интересно, в каком. И почему это не работает из-коробки? Или, возможно, использовать PHPUnit_Framework_TestCase это устаревший подход?
936509
#715 #936282
И вообще, расскажите занимательную историю, почему вы не перекатываете тред после 500 поста? Вам не важно, что он уходит на дно раздела и никому не виден? Вам не нужны здесь новые люди?
936752936822936847
#716 #936310
http://windows.php.net/ эта блять помойка лежит уже пол дня, и это единственное место где можно скачать PHP под апач. Чтобы авторы и админы это херни сдохли от рака блять.
#717 #936509
>>936275

Это просто разные версии phpunit, старая использовала подчеркивания, новая неймспейсы.
1374 Кб, Webm
#718 #936542
>>936123
Послать нахуй препода. Можешь попросить у анонов ну или спиздить тех же студентов и выдать их за свой диплом.
#719 #936752
>>936282
Периодически все равно тред пересоздается же, новые люди приходят. А кто изучать взялся, все равно тут по многу тредов сидит уже. Вот реклама в /b не помешала бы, там часто народ создает треды о программировании и не знает с чего начать, надо бы им сюда ссылку кидать.
936977937458
#720 #936773
>>932297
>>932781
Я все это читал и делал, пришлось всякие уроки искать для понимания что мне делать и как, сделал вот так пока что
https://github.com/siqel/abiturientlist
936977937429
#721 #936822
>>936282

Со старыми еще не разобрались

>>936205

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

>>936084

А ты разобрался с возможностями PhpStorm? Он немного умеет деплоить, а именно: копировать файлы в другую папку, копировать их по FTP итд. Все нажатием одной кнопки. Как именно у тебя организован деплой? Как настроен сервер, какие папки итд?

>>936090

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

>>936046

> работаю удаленно в Railsware.


Интересно, конечно, чем он там занимается с таким уровнем знаний

> Учитесь писать код двумя методами: практика и поиск в Google


Не советую брать с него пример.
936987
#722 #936847
>>936282
Из /b сюда приходят в основном чтобы вставить копипасту с лурочки про PHP, которая уже лет 11 как неактуальна.
#723 #936977
>>934659
Если куда-то после школы поступишь, то можешь воспользоваться студенческой лицензией для PHPStorm, сам на такой сижу: https://www.jetbrains.com/student/

>>936752

> надо бы им сюда ссылку кидать.


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

>>936773
Не понимаю зачем в студентах роутер, там ведь 2-3 страницы - для формы и для студентов. Кстати этот роутер в треде был уже десятки раз, с одними и теми же ошибками (никак не обрабатываются отсутствующие контроллеры/экшны, не используется preg_quote). DataGateway не должен брать данные из $_POST, работать с HTTP - задача контроллера.
Пагинатор обычно считает limit и offset, а не лезет в базу и суперглобальные переменные: https://github.com/siqel/abiturientlist/blob/master/src/PageLinker.php
Тут ведь есть пример с объяснениями: https://github.com/codedokode/pasta/blob/master/student-list.md#Постраничная-навигация/
Повсюду статические вызовы, классы используются, но код по-прежнему процедурный: https://github.com/codedokode/pasta/blob/master/arch/di.md
Почитай про форматирование кода: >>919075
937123
#724 #936987
>>936822

> Со старыми еще не разобрались


Ответ защитан :3
#725 #937123
>>936977
спасибо, я постараюсь переделать, хотел спросить еще почему при выводе студентов первая запись не отображается, а начинает выводить только со второй, а первую запись выводит уже на 4 странице
937438
#726 #937156
Установил ПХП 7.1.2 и Апач 2.4.25 на комп (в данный момент на винду), не работает расширение mbstring.
В php.ini прописал(раскоментил):
extension_dir = "ext"
extension=php_mbstring.dll
Апач перезагружал, все равно выдает ошибку 500, если загружать в браузере, в логах
PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen

Подскажите, в чем проблема ?
937438937645
28 Кб, 700x452
#727 #937266
Туповатый вопрос от туповатого вкатывалищика-ньюфага: как вывести элемент из массива, который уже в массиве?
К примеру:
$massive = array (
'massive' => array (
'massive1' => 'govno',
'massive2' => 'ne rabochee'
)
);
Вот как мне вывести отдельно "говно" и "не рабочее"? Пишу echo "тут должно быть {$massive['massive']}" - пишет просто "Array", а если что-то уровня echo "тут должно быть {$massive['massive'['massive1']]} и {{$massive['massive'['massive2']]}" - вообще ничего, просто пустота, но не крашится.
Может я как-то не так это делаю? Гуглить пытался, но чёт внятного объяснения не нашёл.
937267937269
#728 #937267
>>937266

В 2 шага:

// Получаем внутренний массив
$inner = $massive['massive'];
// Получаем элемент из внутреннего массива
echo $inner['massive1'];

Или, если убрать промежуточную переменную:

echo $massive['massive']['massive1'];
937271
#729 #937269
>>937266

> вообще ничего, просто пустота, но не крашится.


У тебя просто скрыт вывод ошибок. Я запустил у себя- выводит:

PHP Parse error: syntax error, unexpected '[', expecting ']' in D:\2.php on line 1

Проверь значение параметра display_errors в php.ini
#730 #937271
>>937267
Спасибо большое!
#731 #937275
Как правильно в этом случае сделать отступ между Сайдбаром и Контентом? https://jsfiddle.net/bzmcbokf/
937425
82 Кб, 720x720
#732 #937292
Доброго вечерочка, дорогие пыхеры.
Я аутист-ньюфаг в пхп и пишу текстовую "игру" да, я ебанутый и пишу игру на пхп, которая будет в основном зависить от рандома и геймплея как такого нет, кроме как читанины отчёта происходящего на момент запуска кода игры. Почти все события и ивенты будут происходить с помощь циклов, рандомизации и условий, ну и других танцев с бубном. Пока что я сделал основные статы и основной эквип для обычного тестовой пробы работоспособности. Вот этот пиздец: http://ideone.com/UhZSsG
Так что вот какой вопрос: есть ли способ сделать более-менее приемлемый и не вырвиглазный простой интерфейс для текста с помощью хтмл и чтобы это было реально для ньюфага по сложности? Ну и желательно с возможностью смены данных статов героя и имени, ну или хотя бы пустое окошко для ввода имени, лол.
937306937424
#733 #937306
>>937292
Хоть бы на классах это попробовал сделать, лол.
#734 #937328
Делаю студентов. Такой вопрос : нужно 3 страницы выходит а не две? Сам список, форма добавления, и временный профиль студента для редактирования данных. Или сделать форму регистрации и редактирования шаблонами и использовать роутинг у условием?
937409937411937422
#735 #937378
Статья «Hello, (real) world!» на php в 2017 году: https://m.habrahabr.ru/post/322170/

Ошибки в рассуждениях автора каждый может поискать самостоятельно.
#736 #937379
Насчет фреймворков и то, как они якобы усложняют жизнь. Вот все аноны, кто решал задачу про студентов, писали сами код работы с БД, код вывода таблицы с сортировками, кто-то еще роутинг. А в фреймворке все это уже написано. Нужен роутинг? 10 строчек. Нужно загрузить сущность из БД? 3 строчки. Нужно вывести таблицу с пагинацией и сортировкой? 10 строчек (включая HTML).

Конечно, фреймворк еще надо установить. Несколько команд в консоли надо выполнить.

Вот так вот, по мнению автора статьи, фреймворки "усложняют" жизнь разработчика. Или он какие-то фреймворки неправильные использовал?
#737 #937392
Я уже неделю не могу осилить функции.
Последний момент, где я клянусь богом - нигде не нашел.
http://php720.com/lesson/42

function square($num)
$num - что это. На примере урока, это квадрат числа, который задается в $num.

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

Каким образом при вызове этой функции, и написания в скобках число, переменная понимает, что это число её?
square($num)
square(7);

Как это происходит? Вот мы вызвали функцию, написали в скобках число. Функция просчитала все и выдала ответ. Но как она поняла, что число именно приписывается к $num? Точнее так. Смотрите. До создании функции, мне надо создать переменную $num?

Помогите пожалуйста, у меня сейчас голова взорвется.

Я вижу часы, вижу время, но не понимаю как они работают.
937400937405938055
#738 #937393
>>932777

MVC сапер.

https://github.com/codedokode/pasta/blob/master/js/minesweeper-mvc.md

> Если игрок попал на мину и игра проиграна, представление должно отобразить соответствующее сообщение с кнопкой перезапуска игры (нажатие на которую тоже обработает контроллер).



А как контроллер обработает попап, если я создам его (попап) только к концу игры? Т.е. для кликов по полю (которое создано до игры) он биндит функции до начала игры, а тут вот такой случай. Создавать попап заранее и держать его где-то чтоли.
937419
#739 #937400
>>937392
$num - аргумент этой функции. Это лишь условная переменная которой функция будет оперировать.
Когда будешь эту функцию вызывать то можешь класть любое число в качестве аргумента
937404
#740 #937404
>>937400
А что такое аргумент с точки зрения функции?
Если там, в этих скобках - нужно будет подставить не число, а пример, или слово? Как это работает?

Я бы хотел узнать об этих вот. Словах. АРгумент. Вот. Что это значит?
Я все эти учебники смотрю. Там мне дают рыбу, а не удочку. Везде нужно следовать инструкции. И не дают внутрь глянуть прибора.

Я понимаю, все и не сразу. Но хоть жаргонные слова знать, что-бы вот сейчас ты написал мне аргумент, а я даже не знаю что это. А если загуглю - охуею
937406937408
#741 #937405
>>937392

Функция - это подпрограмма (отдельная маленькая программа), которую мы используем так:

1) объявляем (определяем, создаем) функцию с помощью слова function, например function square($n) { return $n * $n ; }. Мы указали название функции square, список аргументов в круглых скобках, тело функции в фигурных скобках.
2) далее мы вызываем функцию с помощью указания имени и круглых скобок, например echo square(10);

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

function square($n) { ... - один аргумент $n
function add4($a, $b, $c, $d) { return $a + $b + $c + $d; } - 4 аргумента

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

square(100) - вызываем функцию и передаем ей 100 как значение $n
add4(10, $x, 100, 500 + 1) - вызваем функцию и передаем ей 4 значения как $a = 10, $b = $x, $c = 100 и $d = 501

При вызове начинает выполняться тело функции, а переменные-аргументы получают указанные в скобках значения. То есть если ты вызвал функцию как square(100), то внутри нее переменная $n будет иметь значение 100.

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

Функция может, если хочет, при завершении вернуть какое-то значение с помощью return. Этот значение вызывающий код может сохранить в переменную или как-то использовать, например, вывести:

echo square(10); // 100
$x = add4(1, 2, 3, 4);
echo $x; // 10

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

square(100);

Хотя смысла в этом нет.

У меня в учебнике есть урок по функциям http://archive-ipq-co.narod.ru/l1/functions.html и задача к нему. Можешь почитать.

> $num - что это.


Это переменная-аргумент функции.

> На примере урока, это квадрат числа, который задается в $num.


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

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


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

> Каким образом при вызове этой функции, и написания в скобках число, переменная понимает, что это число её?


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

> До создании функции, мне надо создать переменную $num?


Если ты не передаешь ее в функцию, то не надо. Я не понял из твоего кода, square($num) - это кусок описания функции или это вызов? Если вызов то такая переменная должна существовать.

Что еще непонятно?
#741 #937405
>>937392

Функция - это подпрограмма (отдельная маленькая программа), которую мы используем так:

1) объявляем (определяем, создаем) функцию с помощью слова function, например function square($n) { return $n * $n ; }. Мы указали название функции square, список аргументов в круглых скобках, тело функции в фигурных скобках.
2) далее мы вызываем функцию с помощью указания имени и круглых скобок, например echo square(10);

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

function square($n) { ... - один аргумент $n
function add4($a, $b, $c, $d) { return $a + $b + $c + $d; } - 4 аргумента

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

square(100) - вызываем функцию и передаем ей 100 как значение $n
add4(10, $x, 100, 500 + 1) - вызваем функцию и передаем ей 4 значения как $a = 10, $b = $x, $c = 100 и $d = 501

При вызове начинает выполняться тело функции, а переменные-аргументы получают указанные в скобках значения. То есть если ты вызвал функцию как square(100), то внутри нее переменная $n будет иметь значение 100.

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

Функция может, если хочет, при завершении вернуть какое-то значение с помощью return. Этот значение вызывающий код может сохранить в переменную или как-то использовать, например, вывести:

echo square(10); // 100
$x = add4(1, 2, 3, 4);
echo $x; // 10

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

square(100);

Хотя смысла в этом нет.

У меня в учебнике есть урок по функциям http://archive-ipq-co.narod.ru/l1/functions.html и задача к нему. Можешь почитать.

> $num - что это.


Это переменная-аргумент функции.

> На примере урока, это квадрат числа, который задается в $num.


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

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


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

> Каким образом при вызове этой функции, и написания в скобках число, переменная понимает, что это число её?


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

> До создании функции, мне надо создать переменную $num?


Если ты не передаешь ее в функцию, то не надо. Я не понял из твоего кода, square($num) - это кусок описания функции или это вызов? Если вызов то такая переменная должна существовать.

Что еще непонятно?
937605938041
#742 #937406
>>937404

> АРгумент. Вот. Что это значит?



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

Аргумент - это переменная, которая указывается при объявлении функции. Она принимает значение, которое было передано в скобках в момент вызова функции.
937605
#743 #937408
>>937404

Давай я еще раз повторю:

function name($arg) { body; }

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

name(1) значит "вызвать функцию name, передав в качестве значения $arg значение 1".
$x = name(1); значит "вызвать функцию и сохранить значение, которое она вернет (через return), в $x".

"вызвать функцию" значит выполнить записанные в ее теле команды.

Со строками все работает так же как и с числами: name("Hello")
937605
#744 #937409
Ответьте лучше на мой ответ
>>937328
937411
#745 #937411
>>937328
>>937409
this

>Или сделать форму регистрации и редактирования шаблонами и использовать роутинг у условием?

#746 #937419
>>937393

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

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

Вот как это может выглядеть:

var popupCtl = new OkCancelPopupController('Повторить попытку?', parentView);
popupCtrl.show();
popupCtrl.onEvent(EVENT_CLOSE, function (answer) {
// вызывается при нажатии кнопки или закрытии окна
});
setTimeout(function () { popupCtrl.close() }, 5000);

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

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

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

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

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

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

Вот примеры такой программы на Ява, может что-то поймешь: https://ru.wikibooks.org/wiki/Java/Первое_окно

Там есть контроллеры или вью виджетов (JFrame, JButton), я не знаю, есть ли у них отдельные M, V и С, или там все объединено в одном классе в силу примитивности кода.

То есть каждое окно/вкладка/виджет в теории может иметь свои V и С. И при желании, M. Контроллер может отстутствовать, если с элементом нельзя взаимодействовать, или может быть встроен в View, если он очень примитивный.

Эти виджеты используются в языках вроде Java, С# при построении интерфейса, и в библиотеках вроде angular, react тоже предусмотрено разбиение интерфейса на отдельные компоненты, хотя и не совсем так. Ну например вместо создания виджетов в коде через new, они описываются в виде похожей на HTML разметки:

<Dialog>
<Button label="ОК"/>
</Dialog>

То есть если у тебя приложение большое и состоит из множества окон, вкладок, виджетов, то моделей/контроллеров/вьюшек может быть тоже много. И не обязательно одинаковое количество.
#746 #937419
>>937393

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

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

Вот как это может выглядеть:

var popupCtl = new OkCancelPopupController('Повторить попытку?', parentView);
popupCtrl.show();
popupCtrl.onEvent(EVENT_CLOSE, function (answer) {
// вызывается при нажатии кнопки или закрытии окна
});
setTimeout(function () { popupCtrl.close() }, 5000);

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

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

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

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

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

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

Вот примеры такой программы на Ява, может что-то поймешь: https://ru.wikibooks.org/wiki/Java/Первое_окно

Там есть контроллеры или вью виджетов (JFrame, JButton), я не знаю, есть ли у них отдельные M, V и С, или там все объединено в одном классе в силу примитивности кода.

То есть каждое окно/вкладка/виджет в теории может иметь свои V и С. И при желании, M. Контроллер может отстутствовать, если с элементом нельзя взаимодействовать, или может быть встроен в View, если он очень примитивный.

Эти виджеты используются в языках вроде Java, С# при построении интерфейса, и в библиотеках вроде angular, react тоже предусмотрено разбиение интерфейса на отдельные компоненты, хотя и не совсем так. Ну например вместо создания виджетов в коде через new, они описываются в виде похожей на HTML разметки:

<Dialog>
<Button label="ОК"/>
</Dialog>

То есть если у тебя приложение большое и состоит из множества окон, вкладок, виджетов, то моделей/контроллеров/вьюшек может быть тоже много. И не обязательно одинаковое количество.
938223
#747 #937422
>>937328

Если подумать, то форма регистрации и форма редактирования личных данных - это одна и та же форма. Для нее можно использовать один общий контроллер и один общий шаблон для view. Просто в нужных местах добавить ветвление в зависимости от того, редактируем мы или создаем пользователя.
#748 #937424
>>937292

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

Насчет вывода данных с помощью HTML. Не вижу никакой проблемы. Тебе надо 2 вещи:

- сделать HTML-шаблоны для вывода данных. По окончании вычислений PHP скрипт будет подготавливать переменные с результатами боя, параметрами героев и передавать их в шаблон, который их выведет. Читай http://www.phpinfo.su/articles/practice/shablony_v_php.html

- сделать запуск скрипта через браузер и веб-сервер (если ты их еще не используешь). Чтобы ты заходил на определенный адрес в браузере, запускался бы скрит и ты видел в окне результат боя. Читай https://github.com/codedokode/pasta/blob/master/soft/web-server.md

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

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

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

- в самой HTML-странице в форме можно сделать скрытое поле/поля, хранящее информацию о состоянии игры. Наш скрипт сохраняет информацию в это поле и после отправки формы игроком это сохраненное состояние отправится на веб-сервер вместе с введенными игроком данными
- в куках/сессии. Минус - куки/сессия общие для всех вкладок и нельзя вести 2 игры в 2 вкладках параллельно
- в файлах. Надо решить проблему, как различать игроков. Это почти то же, что и сессии.
- в базе данных.
#748 #937424
>>937292

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

Насчет вывода данных с помощью HTML. Не вижу никакой проблемы. Тебе надо 2 вещи:

- сделать HTML-шаблоны для вывода данных. По окончании вычислений PHP скрипт будет подготавливать переменные с результатами боя, параметрами героев и передавать их в шаблон, который их выведет. Читай http://www.phpinfo.su/articles/practice/shablony_v_php.html

- сделать запуск скрипта через браузер и веб-сервер (если ты их еще не используешь). Чтобы ты заходил на определенный адрес в браузере, запускался бы скрит и ты видел в окне результат боя. Читай https://github.com/codedokode/pasta/blob/master/soft/web-server.md

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

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

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

- в самой HTML-странице в форме можно сделать скрытое поле/поля, хранящее информацию о состоянии игры. Наш скрипт сохраняет информацию в это поле и после отправки формы игроком это сохраненное состояние отправится на веб-сервер вместе с введенными игроком данными
- в куках/сессии. Минус - куки/сессия общие для всех вкладок и нельзя вести 2 игры в 2 вкладках параллельно
- в файлах. Надо решить проблему, как различать игроков. Это почти то же, что и сессии.
- в базе данных.
937722
#749 #937425
>>937275

Проще всего указать ширину наример 65% + margin-right 5%.

Также, я советую убрать фиксированную высоту контента и сайдбара, так как она на практике неизвестна.
https://github.com/siqel/abiturientlist/ #750 #937429
>>936773

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

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

Я вижу, что структура твоего кода напоминает фреймворк Yii. Не уверен, что она тут хорошо подходит. Вот, что мне не нравится:

- нет отдельной публичной папки, все файлы по сути доступны извне. Это небезопасно, читай комментарии к студентам.
- папки templates и views - непонятно их различие. Обычно в веб-приложении HTML/PHP-шаблон это и есть вью
- components - непонятно, что это такое? Что ты называешь "компонент"? Контроллер - это не компонент?
- есть папка src (исходный код), но controllers и components почему-то не в ней.

Далее, я не вижу четкого разделения на PHP-код и шаблоны (Controller/View). Вот этот файл: https://github.com/siqel/abiturientlist/blob/master/index.php - он выполняет и функции фронт контроллера (вызвает роутер), и занимается выводом кусков HTML кода. Плохо. Лучше сделать так:

- подготовить все данные
- вывести их с помощью шаблона

У тебя подготовка и вывод данных идет вперемешку.

Также, у тебя почему-то в index.php идет какая-то работа с базой данных, если POST не пуст. Разве это не задача контроллера формы регистрации? Идея как раз в том, что каждый контроллер отвечает за свою страницу, а index.php это как бы общая точка входа (фронт контроллер) и она не должна выполнять обязанности одного конкретного контроллера вместо него.

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

> https://github.com/siqel/abiturientlist/blob/master/components/Db.php


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

Я не уверен, что класс Db нужен. Объясни, зачем он нужен, если мы можем просто писать $pdo = new PDO...

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

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

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

Код плохо выровнен: https://github.com/siqel/abiturientlist/blob/master/components/Router.php#L28

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

В роутере у тебя какой-то гигантский цикл foreach и гигантский if. Переделай код, чтобы они были небольшими.

Если URL не соответствует ни одной странице, надо выдавать ошибку 404.

> To change this license header, choose License Headers


Удали эту ерунду из кода.

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

> https://github.com/siqel/abiturientlist/blob/master/src/AbiturientDataGateway.php#L9


Тут опять нарушение разделения ответственности. Data Gateway - это класс для взаимодействия с БД, он ничего не должен знать про формы и $_POST. Перечитай мой урок по MVC и комментарии к задаче. Это нарушение принципа MVC.

> $result = $db->query('SELECT* from abiturients WHERE id='.$id);


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

Фукнции чтения данных из БД - не лучше ли, если они будут возвращать объекты Student, а не массивы?

> https://github.com/siqel/abiturientlist/blob/master/src/AbiturientDataGateway.php#L111


> function pdoSet($allowed, &$values, $source = array()) {


Что делает функция в файле с описанием класса? Почему она обращается к POST? У тебя реально все перемешано. Смотри, как должно быть:

- создаем объект Student
- отдельной функцией принимаем данные POST и записываем их в объект
- отдельной функцией проверяем на правильнсоть данные в объекте
- отдельной функцией сохраняем их в базу данных из объекта

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

> https://github.com/siqel/abiturientlist/blob/master/src/Init.php


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

> https://github.com/siqel/abiturientlist/blob/master/src/PageLinker.php


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

> https://github.com/siqel/abiturientlist/blob/master/controllers/AbiturientsController.php#L7


Тут непонятно, зачем у действия index сделан параметр id. Зачем передавать туда id? Если ты хотел сделать постраничный вывод, надо передавать номер страницы (и назвать переменную правильно), и из него рассчитывать offset/limit. И их уже передавать в DataGateway.

> while ($row = $result->fetch()) {


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

В общем, пока сделано на двойку с плюсом. Исправляйся.
https://github.com/siqel/abiturientlist/ #750 #937429
>>936773

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

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

Я вижу, что структура твоего кода напоминает фреймворк Yii. Не уверен, что она тут хорошо подходит. Вот, что мне не нравится:

- нет отдельной публичной папки, все файлы по сути доступны извне. Это небезопасно, читай комментарии к студентам.
- папки templates и views - непонятно их различие. Обычно в веб-приложении HTML/PHP-шаблон это и есть вью
- components - непонятно, что это такое? Что ты называешь "компонент"? Контроллер - это не компонент?
- есть папка src (исходный код), но controllers и components почему-то не в ней.

Далее, я не вижу четкого разделения на PHP-код и шаблоны (Controller/View). Вот этот файл: https://github.com/siqel/abiturientlist/blob/master/index.php - он выполняет и функции фронт контроллера (вызвает роутер), и занимается выводом кусков HTML кода. Плохо. Лучше сделать так:

- подготовить все данные
- вывести их с помощью шаблона

У тебя подготовка и вывод данных идет вперемешку.

Также, у тебя почему-то в index.php идет какая-то работа с базой данных, если POST не пуст. Разве это не задача контроллера формы регистрации? Идея как раз в том, что каждый контроллер отвечает за свою страницу, а index.php это как бы общая точка входа (фронт контроллер) и она не должна выполнять обязанности одного конкретного контроллера вместо него.

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

> https://github.com/siqel/abiturientlist/blob/master/components/Db.php


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

Я не уверен, что класс Db нужен. Объясни, зачем он нужен, если мы можем просто писать $pdo = new PDO...

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

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

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

Код плохо выровнен: https://github.com/siqel/abiturientlist/blob/master/components/Router.php#L28

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

В роутере у тебя какой-то гигантский цикл foreach и гигантский if. Переделай код, чтобы они были небольшими.

Если URL не соответствует ни одной странице, надо выдавать ошибку 404.

> To change this license header, choose License Headers


Удали эту ерунду из кода.

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

> https://github.com/siqel/abiturientlist/blob/master/src/AbiturientDataGateway.php#L9


Тут опять нарушение разделения ответственности. Data Gateway - это класс для взаимодействия с БД, он ничего не должен знать про формы и $_POST. Перечитай мой урок по MVC и комментарии к задаче. Это нарушение принципа MVC.

> $result = $db->query('SELECT* from abiturients WHERE id='.$id);


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

Фукнции чтения данных из БД - не лучше ли, если они будут возвращать объекты Student, а не массивы?

> https://github.com/siqel/abiturientlist/blob/master/src/AbiturientDataGateway.php#L111


> function pdoSet($allowed, &$values, $source = array()) {


Что делает функция в файле с описанием класса? Почему она обращается к POST? У тебя реально все перемешано. Смотри, как должно быть:

- создаем объект Student
- отдельной функцией принимаем данные POST и записываем их в объект
- отдельной функцией проверяем на правильнсоть данные в объекте
- отдельной функцией сохраняем их в базу данных из объекта

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

> https://github.com/siqel/abiturientlist/blob/master/src/Init.php


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

> https://github.com/siqel/abiturientlist/blob/master/src/PageLinker.php


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

> https://github.com/siqel/abiturientlist/blob/master/controllers/AbiturientsController.php#L7


Тут непонятно, зачем у действия index сделан параметр id. Зачем передавать туда id? Если ты хотел сделать постраничный вывод, надо передавать номер страницы (и назвать переменную правильно), и из него рассчитывать offset/limit. И их уже передавать в DataGateway.

> while ($row = $result->fetch()) {


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

В общем, пока сделано на двойку с плюсом. Исправляйся.
938954
#751 #937438
>>937156

А ты поменял именно тот файл php.ini, который используется? И ты перезапустил веб-сервер Апач после изменения настроек PHP (php ведь работает как модуль внутри Апача)?

Сделай php-файл с кодом <?php phpinfo(); , запусти его через браузер и посмотри там какой именно файл php.ini использовался. Отредактируй его, и перезапусти Апач.

>>937123

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

>>936255

А я за пару вечеров смог скомпилировать PHP7 под Windows XP. Пока только ядро, без большинства расширений. Тесты почти все проходят. Надо найти время, доделать все и выложить на гитхаб. Скажем нет навязыванию принудительных обновлений софта, не несущих выгоды пользователям.

>>936205

Может с интернетом проблемы или роскомнадзор подсуетился?
937645
Скидки #752 #937439
>>936005

У меня тут есть несколько идей, которые не требуются по условиям задачи, но которые, как мне кажется, могли бы пригодиться при разработке новых скидок. Хотя конечно на практике скидки бывают непредсказуемымми. Например, скидка (50 рублей) при предъявлении купона и превышении определенной суммы чека, в опредленные дни. Можно использовать до 5 купонов за раз. В нынешнюю модель она не укладывается.

> Тогда предлагаю ввести дополнительную абстракцию. Например, нужно добавить такую скидку: если среди товаров есть A и B, то снизить их суммарную стоимость на 20 единиц (не процентов). То есть раньше у нас было "снижение стоимости" основанное на процентах...



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

> $totalPrice += $discountResult->getPriceWithDiscount();



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

$discountResult = $discount->applyDiscount($notUsedProducts, $usedProducts);

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

И еще, насчет уменьшения цены, я бы может поменял вот это:

> $totalPrice += $matchedPrice - $discountResult->getDepreciation();



на это:

$totalPrice += $discountResult->getDepreciation()->decrementPrice($matchedPrice);

Это дает возможность объекту Depreciation делать произвольные операции с ценой, не только уменьшать ее на какую-то величину. А его интерфейс выглядел бы так: public function decrementPrice($originalPrice); Хотя так он не будет знать, с какими именно товарами работает.

Сам класс Calculator мне нравится тем, что он получился очень простым.

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


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

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


> А мне нужно это реализовывать?


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

> Так по условию требуется их комбинировать, там ещё написано "Скидки применяются последовательно в порядке описанном выше."



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

$discont = new CombinedDiscount([
new DiscountIfProductExists('A'),
new DiscountIfAnyProductExists(['B', 'C', 'D'])
]);

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

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

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

Вот тебе кстати статья по теме: https://habrahabr.ru/post/153225/

И еще, если ты поймешь Java (он похож на PHP): https://m.habrahabr.ru/company/abbyy/blog/173885/

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

> private function isCountDepreciationMapValid


Тут я поймал себя на мысли, что в языках вроде Ява эта проверка делается одним тайп-хинтом вроде Map<int, DepreciationInterface>. Может и в PHP когда-нибудь такое завезут (generic types). RFC с идеей уже есть: https://wiki.php.net/rfc/generics

Тут не исправлена проблема модификации переданной коллекции: https://bitbucket.org/learning_acc/discounts/src/91a4b811186aeef2d2041cca52b685c8f17a9a4b/src/Discount/CombinationDiscount.php?at=master&fileviewer=file-view-default#CombinationDiscount.php-31

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

Также, там вроде надо давать скидку на каждую найденную группу товаров, но у тебя дается скидка только на первую. Ну то есть для набора A, A, B, B и условия, что должны присуствовать A + B надо выдать 2 скидки, а ты выдаешь только одну. Вот я скопирую условие:

> Если одновременно выбраны А и B, то их суммарная стоимость уменьшается на 10% (для каждой пары А и B)



И вот тут еще я нашел подвох:

> Если пользователь выбрал одновременно 3 продукта, он получает скидку 5% от суммы заказа



Эта скидка применяется к итоговой сумме заказа, или только к этим 3 продуктам? У тебя второе, я в принципе не против, так как сама задача неточно сформулирована.

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

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

На мой взгляд, задачи на ООП должны быть с меняющимися со временем требованиями (имитирующие реальную разработку). Я у себя в задаче про Вектор так и постарался сделать, чтобы проверить, насколько гибкий получается код в итоге.
Скидки #752 #937439
>>936005

У меня тут есть несколько идей, которые не требуются по условиям задачи, но которые, как мне кажется, могли бы пригодиться при разработке новых скидок. Хотя конечно на практике скидки бывают непредсказуемымми. Например, скидка (50 рублей) при предъявлении купона и превышении определенной суммы чека, в опредленные дни. Можно использовать до 5 купонов за раз. В нынешнюю модель она не укладывается.

> Тогда предлагаю ввести дополнительную абстракцию. Например, нужно добавить такую скидку: если среди товаров есть A и B, то снизить их суммарную стоимость на 20 единиц (не процентов). То есть раньше у нас было "снижение стоимости" основанное на процентах...



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

> $totalPrice += $discountResult->getPriceWithDiscount();



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

$discountResult = $discount->applyDiscount($notUsedProducts, $usedProducts);

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

И еще, насчет уменьшения цены, я бы может поменял вот это:

> $totalPrice += $matchedPrice - $discountResult->getDepreciation();



на это:

$totalPrice += $discountResult->getDepreciation()->decrementPrice($matchedPrice);

Это дает возможность объекту Depreciation делать произвольные операции с ценой, не только уменьшать ее на какую-то величину. А его интерфейс выглядел бы так: public function decrementPrice($originalPrice); Хотя так он не будет знать, с какими именно товарами работает.

Сам класс Calculator мне нравится тем, что он получился очень простым.

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


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

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


> А мне нужно это реализовывать?


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

> Так по условию требуется их комбинировать, там ещё написано "Скидки применяются последовательно в порядке описанном выше."



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

$discont = new CombinedDiscount([
new DiscountIfProductExists('A'),
new DiscountIfAnyProductExists(['B', 'C', 'D'])
]);

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

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

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

Вот тебе кстати статья по теме: https://habrahabr.ru/post/153225/

И еще, если ты поймешь Java (он похож на PHP): https://m.habrahabr.ru/company/abbyy/blog/173885/

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

> private function isCountDepreciationMapValid


Тут я поймал себя на мысли, что в языках вроде Ява эта проверка делается одним тайп-хинтом вроде Map<int, DepreciationInterface>. Может и в PHP когда-нибудь такое завезут (generic types). RFC с идеей уже есть: https://wiki.php.net/rfc/generics

Тут не исправлена проблема модификации переданной коллекции: https://bitbucket.org/learning_acc/discounts/src/91a4b811186aeef2d2041cca52b685c8f17a9a4b/src/Discount/CombinationDiscount.php?at=master&fileviewer=file-view-default#CombinationDiscount.php-31

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

Также, там вроде надо давать скидку на каждую найденную группу товаров, но у тебя дается скидка только на первую. Ну то есть для набора A, A, B, B и условия, что должны присуствовать A + B надо выдать 2 скидки, а ты выдаешь только одну. Вот я скопирую условие:

> Если одновременно выбраны А и B, то их суммарная стоимость уменьшается на 10% (для каждой пары А и B)



И вот тут еще я нашел подвох:

> Если пользователь выбрал одновременно 3 продукта, он получает скидку 5% от суммы заказа



Эта скидка применяется к итоговой сумме заказа, или только к этим 3 продуктам? У тебя второе, я в принципе не против, так как сама задача неточно сформулирована.

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

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

На мой взгляд, задачи на ООП должны быть с меняющимися со временем требованиями (имитирующие реальную разработку). Я у себя в задаче про Вектор так и постарался сделать, чтобы проверить, насколько гибкий получается код в итоге.
#753 #937458
>>934915

У тебя там есть проблема. Там есть условие

if ($creditBalance <= 4000)

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

Ты наверно считал 4000 как 5000 - 1000. Но это неправильно, так как ты не учел проценты, добавляемые на остаток долга.

Задачу вообще можно решить так:

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

«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.

>>935535

Скорее всего у тебя не настроено в Апаче выполнение php-скриптов. То есть Апач просто отдает php скрипт, вместо того чтобы выполнить его с помощью mod_php.

Ты может как-то не так установил эти программы? Вроде по умолчанию в дебиане установка PHP добавляет нужные параметры в конфиг Апача.

>>934750

Это вряд ли связано с самой сессией, скорее с тем как ты их выводишь.

>>936752

Кидай, только тогда сразу стоит объяснить, чем мы занимаемся, что надо знать, и что за месяц "вкатиться" и выучить все нереально.
#753 #937458
>>934915

У тебя там есть проблема. Там есть условие

if ($creditBalance <= 4000)

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

Ты наверно считал 4000 как 5000 - 1000. Но это неправильно, так как ты не учел проценты, добавляемые на остаток долга.

Задачу вообще можно решить так:

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

«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.

>>935535

Скорее всего у тебя не настроено в Апаче выполнение php-скриптов. То есть Апач просто отдает php скрипт, вместо того чтобы выполнить его с помощью mod_php.

Ты может как-то не так установил эти программы? Вроде по умолчанию в дебиане установка PHP добавляет нужные параметры в конфиг Апача.

>>934750

Это вряд ли связано с самой сессией, скорее с тем как ты их выводишь.

>>936752

Кидай, только тогда сразу стоит объяснить, чем мы занимаемся, что надо знать, и что за месяц "вкатиться" и выучить все нереально.
#754 #937459
>>934429

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

Информация в них устаревает. Вот, что может произойти между индексированиями:

- может быть добавлена новая запись в БД
- может быть изменена запись в БД
- может быть удалена запись из БД

При этом в индексе остаются старые неактуальные данные.

А реалтайм-индексы менее оптимальные для хранения и поиска, но зато их можно менять в реальном времени, с помощью запросов INSERT, UPDATE, DELETE к SQL-интерфейсу сфинкса.

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

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

Мануал (англ) http://sphinxsearch.com/docs/current/rt-indexes.html

Логика работы с ними такая:

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

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

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


Да.

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


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

> Или нужно все поля в индекс загонять?


Только те, по которым ведется поиск.
#754 #937459
>>934429

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

Информация в них устаревает. Вот, что может произойти между индексированиями:

- может быть добавлена новая запись в БД
- может быть изменена запись в БД
- может быть удалена запись из БД

При этом в индексе остаются старые неактуальные данные.

А реалтайм-индексы менее оптимальные для хранения и поиска, но зато их можно менять в реальном времени, с помощью запросов INSERT, UPDATE, DELETE к SQL-интерфейсу сфинкса.

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

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

Мануал (англ) http://sphinxsearch.com/docs/current/rt-indexes.html

Логика работы с ними такая:

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

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

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


Да.

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


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

> Или нужно все поля в индекс загонять?


Только те, по которым ведется поиск.
937581
#755 #937461
>>934181

Школа + сам читал учебники + сериалы + сайты + мануалы на англ. В общем, довольно много времени вложено.

>>934039

У тебя $p очень маленький. Попробуй поставить его повыше, например, 257 или 1001, а то там все единицы получились и непонятно, это все правильно, или ошибка.

>>934007

По моему контроллер и есть обработчик запросов, нет? Что-то ты путаешь.

>>933802

У тебя формула расчета странная. Ты по идее должен сделать одно из двух:

- взять число произведенных всеми страниц и потратить на общую сумму зарплат
- либо посчитать среднее из 4 выше рассчитанных значений

То есть формула неправильная. Не надо делить на число департаментов, ибо получается не то.

>>933707

Может там включена подпись кук?

>>933684

Кнопки надо делать тегом button, а не тегом <a>. Ссылка - это то, где есть href указывающий на какую-то страницу.

>>933673

Это что? Пакет PEAR? Тогда тебе надо разобраться, как исользовать PEAR, учти что под линуксом и виндой могут быть различия. В ОП посте есть гайд по командной строке.

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

>>933639

MVC хоронят уже не первый раз, как и изобретают его альтернативы: MVVM, MVP и так далее.

>>933496

Проверь. Должен по идее.
#755 #937461
>>934181

Школа + сам читал учебники + сериалы + сайты + мануалы на англ. В общем, довольно много времени вложено.

>>934039

У тебя $p очень маленький. Попробуй поставить его повыше, например, 257 или 1001, а то там все единицы получились и непонятно, это все правильно, или ошибка.

>>934007

По моему контроллер и есть обработчик запросов, нет? Что-то ты путаешь.

>>933802

У тебя формула расчета странная. Ты по идее должен сделать одно из двух:

- взять число произведенных всеми страниц и потратить на общую сумму зарплат
- либо посчитать среднее из 4 выше рассчитанных значений

То есть формула неправильная. Не надо делить на число департаментов, ибо получается не то.

>>933707

Может там включена подпись кук?

>>933684

Кнопки надо делать тегом button, а не тегом <a>. Ссылка - это то, где есть href указывающий на какую-то страницу.

>>933673

Это что? Пакет PEAR? Тогда тебе надо разобраться, как исользовать PEAR, учти что под линуксом и виндой могут быть различия. В ОП посте есть гайд по командной строке.

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

>>933639

MVC хоронят уже не первый раз, как и изобретают его альтернативы: MVVM, MVP и так далее.

>>933496

Проверь. Должен по идее.
#756 #937581
>>937459
Спасибо, осознал.
Прошу помощи #757 #937592
ОП, помоги пожалуйста с проверкой одного приложения.
Изначально приложение делалось как тестовое задание на Yii2 для одной компании, но не получилось, было много ошибок. Поэтому я решил его поправить и оформить его как небольшой проект для портфолио и заодно натренироваться в php и yii. Прошу помощи от здешних профессионалов, что с их точки зрения неправильно в моем приложении. Это первое относительно серьезное приложение на yii и вообще на php, поэтому возможен говнокод.
Я получил список багов от тестировщиков компании. Проблема в том что часть из них я не смог отловить, у меня на локальном сервере все нормально работает, все проверятся, все процессы функционируют. Выкладываю список багов ниже, возможно, вы сможете объяснить мне, в чем я не прав, или указать на новые баги.
Проект - https://github.com/kiloman-76/TestMoneyApp
Список возможностей программы - http://pastebin.com/GRSiLBK5
Баги - http://pastebin.com/YEFZsrcd
939967
#758 #937605
>>937408
>>937406
>>937405
Большое спасибо, долгих вам лет жизни!
#759 #937645
>>937156
>>937438

Используется php.ini, в нем все изменения и делал.
#760 #937678
Даун в треде. Не получается понять в чем же отличие паттерна бд Table Data Gateway от DataMapper, ведь в обоих случаях используется один класс для работы с моделью и сущностью?
937679937745939967
#761 #937679
>>937678
Тоесть с одной только моделью*
быстрофикс
#762 #937722
>>937424
Спасибо большое, няш.
#763 #937745
>>937678
Например тут: https://martinfowler.com/eaaCatalog/tableDataGateway.html
Ты можешь увидеть, что TDG не обязательно должен работать с объектами, допустимы методы вроде $tdg->update(1, 'Вася', 21);

Датамаппер работает с объектами: https://martinfowler.com/eaaCatalog/dataMapper.html
Там код выше будет выглядеть так:
$user->setName('Вася');
$user->setAge(21);
$mapper->save($user); // Если у $user есть id, то вставляем новые данные, иначе - обновляем старые.

Итого: TDG - более простой, предоставляет только шлюз к БД. Маппер оперирует объектами (маппит объекты на данные БД и наоборот). Почему объекты лучше массивов: объект может понадобиться нам позже в каком-нибудь сервисе (например аутентификации), с объектами проще работать, так как они имеют чёткую структуру (если мы не используем магические свойства и методы), в отличии от массивов.
50 Кб, 604x446
#764 #937819
Аноняши прошу помощи. Заебался заниматься говнокодингом и писать велосипеды с костылями. Подскажите какие лучше цмс и фреймворки учить чтобы взяли хотябы стажером за еду? База есть. Что сейчас наиболее востребовано?
937906938191939967
6466 Кб, Webm
#765 #937906
>>937819

Б И Т Р И К С
И
Т
Р
И
К
С


Будешь хуже червя-пидора, но зато с работой червя-пидора.
938009
#766 #938009
>>937906
Бля, что за ужас на шебмке?
938044
#767 #938041
>>937405
return возвращает управление программой модулю, из которого была вызвана функция. Выполнение программы продолжается с инструкции, следующей за местом вызова.

Из мануала. Я вообще ничего не понял. И в твоём посте не понял. Я дурак. Умоляю, помоги на примере, как эта return работает. Ты уже показал пример, но я все равно ничего не понял.
938061938130939966
2185 Кб, Webm
#768 #938044
>>938009
Очевидные курсы 1С Битрикс.
938067
#769 #938055
>>937392

>Я уже неделю не могу осилить функции.


А что не понятно. Функция - это подпрограмма в твоей программе. Т.е. вызвая ф-ю в своей программе ты как бы используешь еще одну программу.

>function square($num)


>$num - что это. На примере урока, это квадрат числа, который задается в $num.


Это то, с чем твоя ф-я будет работать. Вот у любом программы есть входные данные и данные которые она возвращает с помощью оператора return. Например функция суммы двух чисел:
function sum($x, $y) {
$sum = $x + $y;
return $sum;
}
Да, только запомни что $sum, например, существует только внутри ф-и.
В данном случае sum это программа, входные данные(аргументы) которой это х и у. А переменная $sum это то, что программа отдает на выходе.
Теперь в своей программе, допустим homework.php тебе понадобилось подсчитать два сложных числа. Соответственно, ты делaешь следующее:
$num1 = 100500;
$num2 = 4564564;
$summa_chisel = sum($num1, $num2);
Вуаля, у тебя в переменной summa_chisel будет сумма переменных нам1 и нам2, ты решил домашку и можешь идти гулять.

>Но сама по себе. Вот эта вот переменная в скобках, она должна существовать до создания функции, или её можно указать впервые в этой скобки.


Да как угодно. Хоть прямо во время вызова ф-и.

>Каким образом при вызове этой функции, и написания в скобках число, переменная понимает, что это число её?


>Как это происходит? Вот мы вызвали функцию, написали в скобках число. Функция просчитала все и выдала ответ. Но как она поняла, что число именно приписывается к $num? >Точнее так. Смотрите. До создании функции, мне надо создать переменную $num?


Это задается при создании ф-и, только это называется определением ф-и. При определении ф-и в данном случае мы указали, что вызываться она должна с двумя аргументами, иначе она вернет тебе ошибку, попробуй на практике.
#770 #938061
>>938041

>Из мануала. Я вообще ничего не понял. И в твоём посте не понял. Я дурак. Умоляю, помоги на примере, как эта return работает. Ты уже показал пример, но я все равно ничего не понял.


Есть у тебя скрипт.
Допустим
function sum($x, $y) {
$sum = $x + $y;
return $sum;
echo "какое-то очень важное сообщение, которое обязаны увидеть все кто использует эту ф-ю";
}
$num1 = 100500;
$num2 = 4564564;
$num1 = 100500;
$num2 = 4564564;
$summa_chisel = sum($num1, $num2);
Твой код читает такая штуковина, которая называется интерпритатор. В данном случае он берет твой пхп скрипт, читает @ выполняет его и возвращает html-код. Так вот. Идет он такой по скрипту, и видит вызов ф-и. Смотрит потом код еще раз, находит ее определение и вызывает. Т.е. как-бы когда он видит ф-ю он входит внутрь нее и выполняет в качестве программы, и когда он видит оператор return он понимает, что ему надо взять то на что оператор указывает(в данном случае он берет $sum), выходит из подпрограммы, (т.е. ф-и) и переходит в программу, в которой был до этого, т.е. идет дальше по скрипту. Соответственно, что там дальше в ф-и его не заботит и пользователь не увидит это важное сообщение. Можешь для практики подумать, что надо сделать что бы пользователь увидел сообщение.
938071
#771 #938067
>>938044
Спасибо, начал изучение
#772 #938071
>>938061
Получается, с оператором return, интерпретатор игнорирует все, что не связано с той переменной, что указано при написании return?
Вот return $sum;. Значит он выполняет только то, где участвует переменная $sum, а остальное игнорирует?

Или он обрывает выполнение функции на команде return, а все, что ниже написано return - игнорируется?
938079938135939966
#773 #938079
>>938071
Нет же. Return просто забирает результат каких-то действий и указывает интерпретатору что вот оно, то что требуется вернуть. А что там дальше интерпритатора уже не ебет, после строчки с ретерном он уже не будет читать и выполнять подпрограмму, а до нее ты можешь сколько угодно действий выполнять.
938087
#774 #938087
>>938079
Благодарю. Спасибо. Примерно понял.
Но чтобы добить. На примере этого урока, http://php720.com/lesson/47
Цитирую:

> Т.е в нашем случае, мы посчитали нужное нам выражение, занесли его в переменную $res и вернули через оператор return. Если бы мы этого не сделали, то переменная $z была бы пустая.



А почему бы она была пустая? Исходя из этого, если я хочу получить какой-то результат при выполнении функции, я должен буду всегда в конце функции написать return с указанным аргументом в виде переменной, в которой я хочу получить результат?
938097938136939966
#775 #938097
>>938087

>> Т.е в нашем случае, мы посчитали нужное нам выражение, занесли его в переменную $res и вернули через оператор return. Если бы мы этого не сделали, то переменная $z была бы пустая.


Пустая она была бы потому, что без ретерна ф-я бы ничего не возвращала. Т.е. отработала бы в холостую и все. Интерпритатор штука прямая как шпала, понимает всё буквально, соответственно так в коде и надо выражаться.

>А почему бы она была пустая? Исходя из этого, если я хочу получить какой-то результат при выполнении функции, я должен буду всегда в конце функции написать return с указанным аргументом в виде переменной, в которой я хочу получить результат?


Ну да. Только не обязательно в ретерне отдавать переменную, можно что угодно - массив, объект или прямо на месте делать вычисление, т.е. можно даже написать return $x + $y в данном случае. Вообще ф-я может и не возвращать ничего, попробуй вместо ретерна написать echo, вызывать не для присваивания а просто так. Такие вещи вообще лучше всего на практике изучать.
939965
#776 #938126
Привет, анон. Я новичек в пыхе, и при чтении вводных гайдов возникает вопрос: зачем все рекомендуют устанавливать phpmyadmin? Какие он дает преимущества? Существуют ли задачи, когда его удобнее использовать по сравнению с обычным управлением бд, или же это просто графическая надстройка и без нее можно спокойно жить?
938141
#777 #938130
>>938041

return это команда выхода из функции (завершить выполнение подпрограммы). Ее можно использовать в 2 формах:

return; - выйти из функции и вернуть null
return значение; - выйти из функции и вернуть указанное значение. Это может быть число, строка, переменная, выражение.

return прекращает выполнение кода в функциии и возвращает управление к месту, откуда была вызвана функция.

Если return не ставить, то код функции выполняется до конца.
#778 #938135
>>938071

нет. return завершает выполнение функции и потому код после него не выполняется. Переменная тут не при чем.

Ты по моему пропустил самый первый, и самый важный урок - что такое программа. Программа это последовательность команд. Интерпретатор PHP по умолчанию просто выполняет записанные в программе команды последовательно, сверху вниз.

Но некоторые команды меняют порядок выполнения программы. Например, if позволяет не выполнять команды внутри него при опредленном условии, for позволяет выполнить одни и те же команды несколько раз подряд, а функции позволяют создать подпрограмму и позже ее вызывать. Подпрограмму можно вызвать, и из нее можно выйти раньше времени командой return.

Соответственно переменная тут не при чем. Просто return завершает выполнение функиции и команды ниже уже не выполняются.

У меня ощущение, что ты куда-то спешишь и пропускаешь изучение основ. И из-за этого не понимаешь более сложные темы. Я бы советовал взять учебник в ОП посте и прорешать там все задачи подряд, чтобы лучше разобраться, как вообще работают прогаммы, какие есть команды итд.
#779 #938136
>>938087

Если не вернуть из функции какое-то значение явно командой return, то она вернет значение по умолчанию - null. И в переменную сохранится этот null. В том учебнике это называют "переменная будет пустая".
#780 #938141
>>938126

Это программа-клиент для MySQL для опытных программистов, которые в совершенстве знают SQL. Начинающему надо писать запросы руками в консоли, чтобы запомнить синтаксис и научиться получать нужные данные.
938183
#781 #938183
>>938141

>для опытных программистов


Опытные юзают HeidiSQL или Workbench. Phpmyadmin как раз для нубов с вордпрессами, там тебе ни табов, ни сохранения запросов, ни биндинга, да, скорость черепашья и ошибки через одну валятся. Рекомендуют ее застрявшие в 90х старперы, не освоившие новых инструментов.
#782 #938191
>>937819
Бамп вопросу, че еще кроме Битрикса, Вордпресс нужен?
938205
#783 #938205
>>938191
Битриксы и вордпрессы в жопу, они для криворуких, учи нормальные фреймворки - Symphony, Yii, Laravel. Из cms можно Cake Php, typo3, для магазинов PrestaShop. Если фреймворк освоил, то тебе в принципе CMS и не нужен, можешь на фреймворке все то же самое быстро и легко написать, возможностей и контроля больше.
938214
#784 #938214
>>938205
А как же требования? Поддержка и написание функционала к магазинчикам по продаже дилдаков? Фреймворк однозначно стоит брать, но пока я его буду учить у меня кончатся все дошики и я помру с голода, а так устроиться хотябы куда нибудь
#785 #938223
>>937419

Я думаю, можно уже показать: https://github.com/greenTea242/MinesweeperMVC . Посмотри, пожалуйста. Пока что не стал всякие angular, knockout делать, попроще реализацию выбрал из задачи. Несколько вопросов:

Это нормально что я работаю со словарями в таком стиле: dict1.prototype.merge(dict2) изменит dict1 и ничего не возвращает. По другому будет Dict.merge(dict1, dict2) - вернется новый словарь, dict1 не изменится.

Что делать с символом единицы в верстке? Объясню. Если приглядеться, немножко кривые табло флагов и времени. Потому что в css файле я сдвинул span.digit через text-align вправо чтобы получился стиль калькулятора (ты поймешь о чем я, как увидишь). Может двигать только символ единицы?

Можно ли сделать dataset данные (которые цифры) в опциях зависимыми от моих констант? А то можно ошибиться.

Ну и конечно я хочу услышать твое мнение на счет Popup V/C. Не очень правильно реализовал, наверное, тяжеловато приходит понимание MVC. Для каждой менюшки, если по правильному, тоже нужно делать V/C?
#786 #938230
По саперу.

А что код на github pages не выложишь, чтобы сразу смотреть можно было?

> dict1.prototype.merge(dict2)


наверно dict1.merge(dict2)?

> По другому будет Dict.merge(dict1, dict2)


Почему? Можно var d = d1.merge(d2);

Вообще, есть 2 подхода:

- создается и возвращается новый объект
- модифицируется существующий

В разных ситуациях они имеют свои преимущества и недостатки.

В Руби для различения таких методов тем, которые модифицируют объект, добавляют в имя символ !, например dict1.merge!(dict2)

> Для каждой менюшки, если по правильному, тоже нужно делать V/C?


Логичнее сделать 1 конфигурируемый виджет меню (V/C), и в него передавать структуру меню.

> https://github.com/greenTea242/MinesweeperMVC/blob/master/public/minesweeper.html#L60


> Object.assign(MinesweeperGame.prototype, EventDispatcher.prototype);


Почему это не в фйле, где описан Minesweeper?Ты может и методы класса по нескольким файлам разбросаешь?

Ну и в общем, мне не нравится такой миксин, так как тут нет никакой защиты от того, что в 2 классах могут оказаться поля с одинаковыми именами. В реальном большом проекте с несколькими разработчиками такие конфликты будут, и замучаешься их распутывать. Один человек добавил метод в EventDispatcher и где-то в другом месте что-то сломалось.

PopupController ты реализовал нехорошо, на мой взгляд. Я тебе предложил идею сделать независимый виджет попапа, который ничего не знает про игру, а умеет только показывать/скрывать попап и сообщать о нажатии кнопок в нем. Но ты зачем-то отказался от идея разделения ответственности и влепил в контроллер попапа обращение к модели игры:

> this._parentView.getMinesweeperGame().reset();


Вдобавок ты еще и нагрузил View лишними обязанностями. Задача View - отображать данные, а не предоставлять всем желающим ссылку на объект модели. Однозначно у View не должно быть публичного метода getMinesweeperGame.

То же касается метода DomGameController.prototype.getMinesweeperGame(). Предоставлять ссылку на модель не входит в задачи контроллера.

То, как сделан вывод тут ConsoleGameView.js показывает, что у модели не очень удобный интерфейс предоставления данных:

> var visibleMines = this._minesweeperGame.getVisibleMines();


...

По моему так лучше сделать либо метод, дающий информацию по конкретной клетке:

game.hasMine(x, y)

Либо дающий объект клетки:

game.getCell(x, y).hasMine();

Это внутреннее знание модели, как именно хранится информация о клеточках. А ты ее выставляешь наружу и предлагаешь всем самостоятельно копаться в каких-то внутренних хранилищах.

Тот интерфейс, что я предложил, как мне кажется, лучше скрывает информацию о хранении данных внутри модели и при рефакторинге меньше придется менять.

> var spacesCounter = 3 - Util.getNumberLength(y);


> var pad = Util.repeatString(spacesCounter, " ");


Можно объединить в функцию padLeft()

> this._minesweeperGame.addEventListener(GameEvent.CELL_CHANGED


> this._minesweeperGame.addEventListener(GameEvent.SEVERAL_CELLS_CHANGED,


Только второго события по моему достаточно. Первое избыточно.

> var template = document.querySelector(".template-popup");


> this._popupView = new PopupView(this, template.innerHTML, message);


Шаблон попапа наверно должен получаться в PopupView, а не снаружи. То есть это только PopupView знает, где взять шаблон.

removePopup тоже должен быть частью PopupView. Как иначе его повторно использовать, везде копировать этот код?

Попап выгоднее центрировать средствами CSS.

> Dictionary


Правильнее назвать CellDictionary или CellList как-то так, это ведь не словарь для любых объектов. А, вспомнил! CellSet. Возможно, что Set - это как раз та структура данных, которая тут нужна: https://tproger.ru/translations/sets-for-beginners/

Set (множество) - это такая структура, куда можно добавлять данные и потом проверять, есть они там или нет.

И кстати, в новом JS они есть (точнее будут): https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Set - просто, чтобы ты знал.

Это я мельком глянул, может потом напишу подробнее.
#786 #938230
По саперу.

А что код на github pages не выложишь, чтобы сразу смотреть можно было?

> dict1.prototype.merge(dict2)


наверно dict1.merge(dict2)?

> По другому будет Dict.merge(dict1, dict2)


Почему? Можно var d = d1.merge(d2);

Вообще, есть 2 подхода:

- создается и возвращается новый объект
- модифицируется существующий

В разных ситуациях они имеют свои преимущества и недостатки.

В Руби для различения таких методов тем, которые модифицируют объект, добавляют в имя символ !, например dict1.merge!(dict2)

> Для каждой менюшки, если по правильному, тоже нужно делать V/C?


Логичнее сделать 1 конфигурируемый виджет меню (V/C), и в него передавать структуру меню.

> https://github.com/greenTea242/MinesweeperMVC/blob/master/public/minesweeper.html#L60


> Object.assign(MinesweeperGame.prototype, EventDispatcher.prototype);


Почему это не в фйле, где описан Minesweeper?Ты может и методы класса по нескольким файлам разбросаешь?

Ну и в общем, мне не нравится такой миксин, так как тут нет никакой защиты от того, что в 2 классах могут оказаться поля с одинаковыми именами. В реальном большом проекте с несколькими разработчиками такие конфликты будут, и замучаешься их распутывать. Один человек добавил метод в EventDispatcher и где-то в другом месте что-то сломалось.

PopupController ты реализовал нехорошо, на мой взгляд. Я тебе предложил идею сделать независимый виджет попапа, который ничего не знает про игру, а умеет только показывать/скрывать попап и сообщать о нажатии кнопок в нем. Но ты зачем-то отказался от идея разделения ответственности и влепил в контроллер попапа обращение к модели игры:

> this._parentView.getMinesweeperGame().reset();


Вдобавок ты еще и нагрузил View лишними обязанностями. Задача View - отображать данные, а не предоставлять всем желающим ссылку на объект модели. Однозначно у View не должно быть публичного метода getMinesweeperGame.

То же касается метода DomGameController.prototype.getMinesweeperGame(). Предоставлять ссылку на модель не входит в задачи контроллера.

То, как сделан вывод тут ConsoleGameView.js показывает, что у модели не очень удобный интерфейс предоставления данных:

> var visibleMines = this._minesweeperGame.getVisibleMines();


...

По моему так лучше сделать либо метод, дающий информацию по конкретной клетке:

game.hasMine(x, y)

Либо дающий объект клетки:

game.getCell(x, y).hasMine();

Это внутреннее знание модели, как именно хранится информация о клеточках. А ты ее выставляешь наружу и предлагаешь всем самостоятельно копаться в каких-то внутренних хранилищах.

Тот интерфейс, что я предложил, как мне кажется, лучше скрывает информацию о хранении данных внутри модели и при рефакторинге меньше придется менять.

> var spacesCounter = 3 - Util.getNumberLength(y);


> var pad = Util.repeatString(spacesCounter, " ");


Можно объединить в функцию padLeft()

> this._minesweeperGame.addEventListener(GameEvent.CELL_CHANGED


> this._minesweeperGame.addEventListener(GameEvent.SEVERAL_CELLS_CHANGED,


Только второго события по моему достаточно. Первое избыточно.

> var template = document.querySelector(".template-popup");


> this._popupView = new PopupView(this, template.innerHTML, message);


Шаблон попапа наверно должен получаться в PopupView, а не снаружи. То есть это только PopupView знает, где взять шаблон.

removePopup тоже должен быть частью PopupView. Как иначе его повторно использовать, везде копировать этот код?

Попап выгоднее центрировать средствами CSS.

> Dictionary


Правильнее назвать CellDictionary или CellList как-то так, это ведь не словарь для любых объектов. А, вспомнил! CellSet. Возможно, что Set - это как раз та структура данных, которая тут нужна: https://tproger.ru/translations/sets-for-beginners/

Set (множество) - это такая структура, куда можно добавлять данные и потом проверять, есть они там или нет.

И кстати, в новом JS они есть (точнее будут): https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Set - просто, чтобы ты знал.

Это я мельком глянул, может потом напишу подробнее.
945019
736 Кб, Webm
#787 #938323
Снова выхожу на связь. Исправил все, кроме неэффективного способа хранения комментариев. https://github.com/anotherCodeMunkey/fileshare
42 Кб, 657x239
62 Кб, 672x202
#788 #938453
ПХПач, обьясни, почему если использовать str_repeat() с символом пробела - функция не работает ?
В ideone и прочих онлайн компиляторах выводит табличку корректно.
938482938536
#789 #938482
>>938453
Интересно. Попробуй &nbsp вместо простого пробела.
938527
#790 #938527
>>938482
работает, спасибо. А в чем фишка ?

И еще вопрос. Как подружить апач с расширением mbstring ?
Если юзаю встроенный пхп сервер - работают скрипты нормально. Когда запускаю на апаче - выдает Fatal error: Call to undefined function mb_strlen().
938545938619938620
#791 #938536
>>938453
Content-type броузеру отрпавляешь? Если нет он вырезает лишние пробелы, а онлайн компиляторы транслируют тебе вывод консоли "как есть".
#792 #938545
>>938527

>работает, спасибо. А в чем фишка ?


Ну типа, обычные символ пробела может по разному интерпритироваться разными браузерами, или что-то там. А неразрывный проблем это везде неразрывный пробел.
#793 #938619
>>938527

ideone показывает тебе выведенный текст как есть.

Браузер по умолчанию воспринимает то, что выведет программа, как HTML. В языке HTML любое число пробелов равносильно 1 пробелу.

Чтобы переносы строк и пробелы нормально работали и в браузере и в ideone (и в консоли), можно в начале программы поставить

header("Content-Type: text/plain; charset=utf-8");

Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать пробелы и переносы строк в нем.
#794 #938620
>>938527

А ты в php.ini включил это расширение? Перезапустил Апач после этого?
#795 #938694
Можно ли интерпретатор PHP запустить в консоли, как тот же Python, Ruby или JS?
938742939965
#796 #938742
>>938694
Ты имеешь в виду REPL? Да, для PHP он есть встроенный, запускать через php -a в консоли. Если хочешь продвинутый автокомплит с историей, то погугли PsySH.
#797 #938811
>>919074 (OP)
Господа, еле откопал тред. Кто-нибудь пытался прописывать куки в CodeIgniter?? Почему, если я ставлю куку, то она сохраняется только в пределах одного контроллера??
А еще, если я пишу проверку на куку в каждом методе контроллера типа
if(!isset($cookie)){
redirect('/index/', 'refresh');
}
$post;
то меня при обновлении страницы (например, методом post из формы) выкидывает на главную страницу, т.е. кука удаляется? втф? при этом если страницу не обновлять, то кука типа хранится, но как тогда обновлять страницу не удаляя куку?
939965
#798 #938841
В PHP по умолчанию почему-то стоит значение error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED

То есть нотисы игнорируются. Если, к примеру, опечататься в имени переменной то PHP в конфигурации по умолчанию ничего не напишет. Ищи потом, где ошибка.

Потому я вынужден в первом уроке в первой программе ставить этот дурацкий error_reporting(-1), хотя без него программа бы смотрелась и короче и логичнее. И начинающим приходится отвлекаться на изучение каких-то магических заклинаний, которые они толком не поймут.

Почему нельзя поставить нормальные настройки по умолчанию? Почему нельзя выкинуть все эти варнинги и перейти на исключения?

В общем, пока убрать это не получится, придется потерпеть. Привыкайте с самого начала, что в работе PHP разработчика не все медом намазано.
938870939575
#799 #938870
>>938841
Я вообще первым языком Си учил, там для хеллоуворлда от новичка требуется гораздо больше заклинаний, не говоря уже о том, что сишка очень низкоуровневая по сравнению с PHP. С PHP новичок может уже в первый день написать что-то интересное, сишка радушно встречает новичка конструкциями fscanf(stdin, "%d", &array_size) и новичку придётся разбираться с указателями, если он хочется продвинуться хотя бы дальше циклов.

Ну и сейчас таки в PHP варнинги понемногу заменяют на исключения. Вот если новичок первым языком JS учит, то это плохо, будет в голове каша из функций как объектов и объектов как ассоциативных массивов, не говоря уже о конвертации типов. Так что error_reporting, как по мне, мелочь. Я когда PHP изучал по учебнику с анимешными картинками, то не придал error_reporting'у никакого значения, просто добавил бездумно.
#800 #938894
Посоветуйте сайт, где есть задачи по пхп с ответами, и где можно пройти тест, который укажет на твои ошибки в пхп.
1035 Кб, 1920x1080
#801 #938954
>>937429
>>937429
В общем начал переделывать код.
Класс DB нужен именно для те писать того чтобы не писать консрукцию $pdo = new PDO вместе с [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION], но в общем можно убрать позже.
не совсем понятно как bootstrap-файл поможет (настроить автозагрузчик, обработку ошибок, создать какие-то объекты)
938978
#802 #938978
>>938954

То есть если перефразировать то, что ты сказал, то получается, что класс DB нужен ради единственной функции в нем, которая создает объект PDO.

Но тогда напрашивается вопрос, во-первых, почему тогда его не назвать PDoFactory, во-вторых, а почему для других классов такого не сделано? То есть класс, создающий объекты Abiturient, класс создающий объекты AbiturientDataGAteway, объекты PageLinker и так далее?

Пока у меня ощущение, что ты просто скопировал эту идею из какого-то урока, не особо задумываясь.

Предлагаю почитать для начала, как другие люди решали проблемы зависимостей объектов и их создания: https://github.com/codedokode/pasta/blob/master/arch/di.md
939517
#803 #938982
Помогите ретурду с проблемой.
Поставил PhpStorm и xampp, потом столкнулся с проблемой " interpreter not configured phpstorm
Все сделал в точь точь, но нихуя не работает код.
https://www.youtube.com/watch?v=J-jn6yi3x0c
Что делать?
939004939008
#804 #938988
Какие таски пхп джуну обычно дают?
939965
5 Кб, 368x175
#805 #939004
>>938982
без вааас не справлюсь((
#806 #939008
>>938982

Опять надо клещи доставать. Поясни, что значит "не работает"? Что ты делаешь, что ожидаешь увидеть, что видишь? Если ты что-то открываешь в браузере, напиши какой URL в адресной строке, если запускаешь код, запости куда-нибудь его.

Также, если ты используешь веб-сервер, посмотри его логи ошибок. Для Апача под виндой они хранятся где-то в его папке, в линуксе в /var/log.

Видео пересматривать целиком и угадывать, где именно ты ошибся, это не вариант.
939021
40 Кб, 1117x482
42 Кб, 815x492
#807 #939021
>>939008
Я просто хочу запустить код, чтоб код отображался на экране, а я вижу 502x
В настройках я поставил все по дефолту как на видео.
939039
#808 #939039
>>939021

А окошко шторма с настройками веб-сервера?

У тебя показано окно CLI interpreters, интерпретатор для запуска в командной строке.

И что с логами? Для 502 ошибки в логе веб-сервера должна быть запись с пояснениями. Попробуй сам найти, где этот лог, если знаешь, если нет, я потом погуглю. Я пока что понятия не имею, какойв шторме использован веб-сервер и как он настроен.

Я у тебя там вижу упоминание xampp установленного на диск c:, поищи логи в его папке и посмотри есть ли там что-нибудь интересное.
939546
#809 #939196
Пыханы, поясните мне в чем сакральный смысл разработки на линуксе?
Ну серьезно, мне и в винде неплохо. Может быть я не знаю чего-то?
939965
#810 #939236
Друзья, объясните новичку, кто в Symfony шарит. Я думал с т.з. MVC вывод простой страницы (типа все новости) происходит так: в контроллер добавляем запрос к базе через модель типа

$news = \App\Models\Article::getAll();

Соответственно Article - это модель, которая наследуется от базовой абстрактной модели, где эти общие для моделей методы написаны. Например там же можно сделать манипуляции с этими данными, заменить что-то в тексте и т.д. И добавляем обращение ко view.

Но читаю мануалы по Symfony, там рекомендуют в контроллере делать обращение к доктрине типа

$em = $this->getDoctrine()->getManager();
$news = $em->getRepository('AppBundle:Article')->findAll();

Все работает, но если я допустим хочу к с этой выборкой предварительно сделать что-то до выведения в шаблон, например закешировать текст новости, в котором существуют markdown теги, то мне это где правильнее сделать?

Я бы сам ответил что в Entity, предварительно сделав родительский класс. Так как контроллер вроде как не должен с данными работать. Но скачал проект от них же с типа рекомендованным подходом https://github.com/symfony/symfony-demo и там вообще не подобного кода в моделях и они ни от чего не наследуются. И я хз как делать в итоге.

Короче объясните, куда правильнее добавлять код для манипуляции с данными?
939377939380939963
#811 #939377
>>939236

>Короче объясните, куда правильнее добавлять код для манипуляции с данными?


В репозиторий. Когда ты создаешь entity через консоль, она тебе автоматически генерит пустой repository в той же папке Entity. Туда ты записываешь все необходимые тебе методы работы с данными, для этого у доктрины есть прекрасный QueryBuilder. Потом в контроллере ты можешь получить репозиторий в отдельную переменную через ту же конструкцию $this->getDoctrine()->getRepository() и обращаться уже к тем методам, которым ты сам написал в нем. Встроенные методы типа findAll() и findBy() будут так же доступны.
939505939965
#812 #939380
>>939236
В твоих сущностях в идеале не должно быть методов работы с данными, это все работа доктрины.
939965
#813 #939400
Поясните за настройку апача. Как сделать отдельные настройки для каждого сайта? Если прописать как в задачке про студентов
<VirtualHost *:80>
# Имя сервера которое обслуживает этот VirtualHost
ServerName example.com
# Корневая папка сервера
DocumentRoot /var/www/example.com/public
# ....
это же все мои сайты на локалке заданет.
939414
#814 #939414
>>939400
Разобралдся, оказывается я что-то не так делал, раз сначала оно у меня на все сайты влияло. Однако теперь из-за этой хуиты отвалился .htacces. Прописал туда же AllowOverride All - сервер вообще перстал запускаться. ЧЯДНТ? Может мне лучше не париться, а просто через .htacces такое делать?
939480939604
#815 #939480
>>939414
Гугли apache virtual hosts по своему дистру, в мануалах все подробно описано. Если ты обмазался шпермой, то ничем помочь не могу.
939489939963
#816 #939489
>>939480
Да я то все понял. Осталось только разобраться почему .htacces не работает, хотя вроде как должно.

>Если ты обмазался шпермой, то ничем помочь не могу.


А какая разница? Ну кроме как того, что в шинде и красноглазиксах по разному директории пишутся.
#817 #939498
Ладненько. В результате гугления я решил прописать в конфиге для моего сайта вот такое:
<VirtualHost :80>
# Имя сервера которое обслуживает этот VirtualHost
ServerName students.local
# Корневая папка сервера
DocumentRoot путь\public
<Directory "путь">
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.
)$ index.php [QSA]
AddDefaultCharset UTF-8
</Directory>
</VirtualHost>
И работает. Однако все равно хотелось бы узнать, как заставить в данном случае исполнять директивы из .htacces, так по крайне мере удобней и не надо лезть в конфиги апача если что понадобится.
939852939963
#818 #939505
>>939377
Спасибо!
#819 #939517
>>938978
ну в общем я его действительно скопировал и хотел в итоге убрать, но new PDO не принимает больше 4 параметров, то бишь не получалось записать new PDO(host,dbname,user,pass,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION], я позже уберу этот метод.
еще хотел спросить про роутинг, как в мой метод run() в Router добавить 404 error, попробовал сделать такое если не существует вызываемого класса или метода, но выдает ошибку Cannot modify header information
function ErrorPage404()
{
$host = 'http://'.$_SERVER['HTTP_HOST'].'/';
header('HTTP/1.1 404 Not Found');
header("Status: 404 Not Found");
header('Location:'.$host.'404');
}
}
еще хотел спросить как мне сделать view для подготовки данных на вывод, может в гайде было, перечитаю еще раз
939963
5655 Кб, Webm
#820 #939526
Посоны, когда перекот? Утонет ведь.
57 Кб, 1069x704
196 Кб, 1905x761
#821 #939546
>>939039

>А окошко шторма с настройками веб-сервера?


>У тебя показано окно CLI interpreters, интерпретатор для запуска в командной строке.



Я может слепой, но нигде не нашел окно CLI interpreters
939549939962
#822 #939549
>>939546
А Error: document root is not specified or invalid тебе ни о чем не говорит?
939638
#823 #939550
Как в PhPStorm включить поддержку русских символов в коде? А то у меня там за место букв - одни вопросительные знаки.
Кодировку сменить?
939556939601939962
103 Кб, 450x450
#824 #939556
939557
#825 #939557
>>939556
Ну бля, мне диплом писать надо, перешел бы на линупс, но ворд с экселем нужен.
939559
#826 #939559
>>939557
Libreoffice тебе в бухту, юный падаван.
939563
#827 #939563
>>939559
Спасибо, не надо, я уже настрадался с этой хуйней. Принесешь курсач на этой херне преподу на флешке - либо все настройки разметки слетят и весь текст поедет, либо вообще не откроется файл.
И либре офис, и опенОфис. Пока пересилил лень и не поставил проксю, зашел на рутрекер и не купил там Мелкософт Офисе2013. Не нарадуюсь.
939564939962
#828 #939564
>>939563
У нас в государстве общепринятый стандарт .rtf, так что твой препод - пидор.
939566
#829 #939566
>>939564
Пидор не пидор, а сдавать ему предмет с курсачем и дипломом. У них там везде 2007 седьмого года офис стоит на спермерках.
Я даже со своим 2013 испытываю проблемы на их 2007, иногда приходится у них вручную текст доводить. Пиздец в общем.
939571939962
#830 #939571
>>939566
It hurts to be you. Попробуй нетбинс или эклипс что-ли, и воровать не надо.
#831 #939575
>>938841
Потому что ты, судя по всему, скачал версию для продакшена.
У меня, в ampps включены ошибки и различные предупреждения.
939962
#832 #939585
Где можно почитать за веб платформу? Что это вообще такое, с примерами?
Вообще не разбираюсь в этом.
939588
#833 #939588
>>939585
Что ты подразумеваешь под "веб-платформой"?
939591939592
131 Кб, 1705x895
#834 #939591
939592939601939961
314 Кб, 1919x1020
#835 #939592
>>939591
>>939588
Хочу вот здесь свои уроки делать. сейчас здесь делаю.
939595
#836 #939595
>>939592
Шапку треда почитай, фреймворки тебе рано еще.
939597
#837 #939597
>>939595
Ладно, я тогда на том же останусь, спасибо.
939599
#838 #939599
>>939597
Вместо phpdesigner я бы посоветовал phpstorm, netbeans и eclipse.
939601
#839 #939601
>>939599 => >>939550

>netbeans => >>939591



Дык я уже, только чето все сложно.
939607939608
#840 #939604
>>939414

Проверь лог ошибок Апача, там скорее всего написана причина ошибки.
939606
#841 #939606
>>939604
Да разобрался, то я каким-то образом умудрился нагадить в конфиги апача. Алсо, раз уж такие пляски, поясните - когда надо прописывать всякие директивы в .htacces, а когда лучше в конфиг сервера лезть?
939613
#842 #939607
>>939601
Не выбирай там ничего, жми далее. Тут идешка предлагает тебе сразу строить проект на одном из фреймворков, тебе оно не надо.
939610
#843 #939608
>>939601
Ничего там не выбирай, клацай "готово".
939610
16 Кб, 856x475
#844 #939610
>>939607
>>939608
Спасибо. А здесь просто приложение ПХП выбрать?
939611939961
#845 #939611
939618
#846 #939613
>>939606

Преимущество htaccess в том что он распространяется вместе с проектом и другому человеку не надо в настройки сервера что-то вставлять. При изменении настроек не надо перезапускать сервер.

Недостатки в том, что он поддерживается только Апачом, настройки в конфиге парсятся 1 раз, а не на каждый запрос, и их нельзя изменить без прав администратора (взломщикам чуть труднее навредить получается).
939614
#847 #939614
>>939613
А зачем пользоваться не апачем? Апач так-то намба уан.
939622
128 Кб, 1698x891
41 Кб, 1175x356
#848 #939618
>>939611
Отлично. Извини пожалуйста, но у меня тут проблема. Как запустить свою порнографию?
В первый раз при нажатии этой кнопки мне вылезло окошко с выбором php файла. Ну я и выбрал без задней мысли тот, на котором у меня все это написано. А теперь и найти это окно не могу.
939619939624939961
#849 #939619
>>939618
А ты сделал проект? Какой у тебя софт в качестве локального сервера установлен? Открывать как обычный сайт по ссылке.
939621
#850 #939621
>>939619
У меня просто строки кода с примерами выполнения функций, уроков, переменных.

В общем все то, что полные нубы тут пишут на Ideone. Я просто решил сохранять все, и вести одним большим файлом все то, что делаю.
939627
#851 #939622
>>939614
Ты сейчас сидишь на сосачике, который на nginx-e.
939629939961
#852 #939624
>>939618
Если нужно запустить отдельный файл, жми шифт-ф6
939628
#853 #939627
>>939621
Ну для исполнения пхп-скриптов тебе нужен сервер, который будет выполнять скрипты эмулируя веб-сервер, у оп-а в уроках это было. Можешь поставить какой-нибудь xamp, или вообще open server - готовая сборка, в которой все работает искаропки. Но для понимания наверное лучше сделать как у ОПа в уроках.
939630
64 Кб, 1344x601
10 Кб, 310x43
#854 #939628
>>939624
Тоже самое.
Я вот открыл пособие
939961
#855 #939629
>>939622
Это не ответ на мой ответ. Не срача ради, приведи аргументы для использования нгинкса вместо апача.
939632
#856 #939630
>>939627
Понял, спасибо.
Опен сервер у меня уже стоит, xamp стоял, но удалил - сложна. Но поставлю обратно, вернусь к урокам опа.
939635
#857 #939632
>>939629
Сам не знаю, но много народу использует и энгинкс.
#858 #939635
>>939630
Поставь дебиан и не еби себе голову.
939637
#859 #939637
>>939635
Да ты задолбал всем свои прыщи пихать.
939639
59 Кб, 1113x550
#860 #939638
>>939549

>А Error: document root is not specified or invalid


Что у тебя там стоит?можешь скинуть или показать какие должны стоять дефолтные настройки там, уже жалею что перешел на пхпшторм
939640939644939961
#861 #939639
>>939637
Прыщи не мои. Хочешь пердлолиться в сперму - твое право.
939644
#862 #939640
>>939638
Там должен быть путь к исполняеямому файлу php(экзешнику, ёба). В прыщах это /usr/bin/php, в сперме надо задать путь к тому что ты там себе понаставил.
939642
#863 #939642
>>939640
А стоп, я бухой и проебался. DocumentRoot это абсолютный путь к корню твоего сайта.
2378 Кб, Webm
#864 #939644
>>939639
Красноглазый называет кого-то пердольщиком.
>>939638
Пиздос. У тебя в конфиге сервака прописан документ рут(нгинкс), как там в апаче я не знаю в котором серв ищет индексный файл и вообще считает эту папку рутом кто бы блять мог подумать. Укажи этот рут в шторме.
939648
#865 #939648
>>939644
Ну так шперохлёбы пердольщики и есть. На линуксах всё подробно прописано в мануалах и вопросов что куда писать просто не возникает.
939654
223 Кб, Webm
#866 #939654
>>939648
Может быть я чего-то не понимаю, но о каком пердолингк идет речь? Я являюсь почетным спермобоярином и обладаю виртуальной машиной с прыщами. Ни в первом, ни во втором случае вопросов по установке пыхи/нгинкса/мускла не возникало. Я просто не понимаю о чем идет речь, когда кто-то говорит, что у него проблемы с настройкой/установкой на винде.
939660
#867 #939660
>>939654

>Я являюсь почетным спермобоярином


Это только твои проблемы, на них всем насрать.
939664
533 Кб, 459x612
#868 #939664
>>939660
Настолько насрать, что ты не мог не написать об этом.
939668
28 Кб, 320x318
#869 #939668
>>939664
Конечно не мог, ведь в интернетах кто-то неправ.
#870 #939743
Анонам, кто мучается с настройкой сервера и phpstorm

Пожалуйста, для начала прочитайте урок про то, что такое веб-сервер и зачем он нужен: https://github.com/codedokode/pasta/blob/master/soft/web-server.md

Если рассматривать PHP и Апач, то есть ровно 2 конфигурации:

- запускать PHP в режиме сервера, как описано в моем уроке. Информация об ошибках при этом пишется в консоль, где запущен сервер
- установить Апач, настроить в нем использование PHP, немного описано тут: https://github.com/codedokode/pasta/blob/master/soft/apache-install.md . Информация об ошибках пишется при этом в лог-файл Апача.

PhpStrorm не предлагает ничего нового, и не содержит в себе какого-то своего веб-сервера, он может делать лишь 2 вещи:

- запустить один из вариантов веб-сервера
- открыть в браузере страницу, которая будет загружена с запущенного веб-сервера

И настройки в PhpStorm как раз задают, какой вариант вы хотите использовать, где находится корневая папка сервера, где находится exe-файл PHP или Апача. То есть PhpStorm просто за вас может запустить сервер и открыть страницу в браузере. Если вы правильно пропишете настройки.

Обратите внимание, что задачи из учебника можно запускать также в консоли (командной строке). Сервер тут не требуется, так как мы запускаем интерпретатор PHP и наш скрипт напрямую, не используя браузер и веб-сервер. В PhpStrom встроена консоль, и вы можете настроить, чтобы по нажатию кнопки он запускал бы вашу программу и результат отображался в этой встроенной консоли. Так даже может быть проще для наичнающего.

Чтобы это сделать, вам надо сделать 2 вещи:

- указать путь к интерпретатору PHP
- настроить, чтобы phpstorm запускал ваш скрипт в режиме командной строки (CLI)

Как вручную запустить скрипт в командной строке, описано тут в конце: https://github.com/codedokode/pasta/blob/master/soft/php-install.md

Пожалуйста, ознакомьтесь с теорией, выберите вариант, который вам подходит, проверьте что у вас все установлено и настроено (например попробуйте запустить скрипт без phpstrom, руками) и если после этого вам что-то не понятно или не работает, опишиет вашу проблему подробно, что как настроено, что в логе ошибок и тд.
#870 #939743
Анонам, кто мучается с настройкой сервера и phpstorm

Пожалуйста, для начала прочитайте урок про то, что такое веб-сервер и зачем он нужен: https://github.com/codedokode/pasta/blob/master/soft/web-server.md

Если рассматривать PHP и Апач, то есть ровно 2 конфигурации:

- запускать PHP в режиме сервера, как описано в моем уроке. Информация об ошибках при этом пишется в консоль, где запущен сервер
- установить Апач, настроить в нем использование PHP, немного описано тут: https://github.com/codedokode/pasta/blob/master/soft/apache-install.md . Информация об ошибках пишется при этом в лог-файл Апача.

PhpStrorm не предлагает ничего нового, и не содержит в себе какого-то своего веб-сервера, он может делать лишь 2 вещи:

- запустить один из вариантов веб-сервера
- открыть в браузере страницу, которая будет загружена с запущенного веб-сервера

И настройки в PhpStorm как раз задают, какой вариант вы хотите использовать, где находится корневая папка сервера, где находится exe-файл PHP или Апача. То есть PhpStorm просто за вас может запустить сервер и открыть страницу в браузере. Если вы правильно пропишете настройки.

Обратите внимание, что задачи из учебника можно запускать также в консоли (командной строке). Сервер тут не требуется, так как мы запускаем интерпретатор PHP и наш скрипт напрямую, не используя браузер и веб-сервер. В PhpStrom встроена консоль, и вы можете настроить, чтобы по нажатию кнопки он запускал бы вашу программу и результат отображался в этой встроенной консоли. Так даже может быть проще для наичнающего.

Чтобы это сделать, вам надо сделать 2 вещи:

- указать путь к интерпретатору PHP
- настроить, чтобы phpstorm запускал ваш скрипт в режиме командной строки (CLI)

Как вручную запустить скрипт в командной строке, описано тут в конце: https://github.com/codedokode/pasta/blob/master/soft/php-install.md

Пожалуйста, ознакомьтесь с теорией, выберите вариант, который вам подходит, проверьте что у вас все установлено и настроено (например попробуйте запустить скрипт без phpstrom, руками) и если после этого вам что-то не понятно или не работает, опишиет вашу проблему подробно, что как настроено, что в логе ошибок и тд.
#871 #939758
>>939743
ОПчик, если у тебя когда будет кризис идей - знай, что есть как минимум один анон которому было бы интересно почитать уроки по настройке апача, нгинкса, про .htacces и подобное.
939766
#872 #939766
>>939758

А уроки по ссылкам ты все прочел? По Апачу согласен, целостного урока нет, но если знаком с английским, есть объемная документация на оф. сайте.

По PHP - у меня есть же урок про установку. Остальное в оф мануале, в том числе на русском.

По нгинксу документация на русском потому что его делает наш соотечественник.
939778
#873 #939778
>>939766
Документация на апач то обширная, но мне скорее хотелось бы понимать что надо знать и уметь обязательно, дабы не обосраться в неожиданной ситуации, мало ли когда оно вкатывальщику понадобится.
939857
#874 #939788
>>939743
ОП, если ты конечно ОП. Зачем ты что-то объясняешь днищам, которые даже конфигурацию апача осилить не могут, в то время как незабаненные в гугле товарищи эти проблемы решают по щелчку пальцев буквально?
939961
#875 #939852
>>939498
AllowOverride All добавь.
#876 #939857
>>939778
Туториалов по настройке апача и .htaccess море, доку можно не читать. Она правда неудобная и нужна только если что конкретное ищешь. Если в гугле не забанен, то за минуту штук 100 нормальных туториалов находится, я хз чего ты от ОПа еще нового хочешь, когда уже во всех подробностях расписано.
939945939961
#877 #939866
Можно ли наебать работодателя насчет опыта работы, кто-то так делал?
939947
#878 #939945
>>939857

>Если в гугле не забанен, то за минуту штук 100 нормальных туториалов находится, я хз чего ты от ОПа еще нового хочешь, когда уже во всех подробностях расписано.


Читать не умеешь? Я хочу понимать что надо обязательно знать и уметь вкатывальщику, а что в процессе джуниорства можно освоить.
#879 #939947
>>939866
Все так делают.
#880 #939961
>>939857

Лучше прочесть туториал, а потом команды из него посмотреть в документации.

>>939788

С гуглом не все так просто. Не везде объяснят что такое веб-сервер, как он работает. Часто просто дают конфиг который надо бездумно скопипастить и пользы от таких статей ноль.

>>939638

DocumentRoot это путь к корню сайта, где хранятся скрипты и файлы. Прочти это >>939743

>>939628

Веб-сервер либо не запущен, либо запущен на каком-то нестандартном порту и он не указан в URL. Прочти это сначала >>939743

>>939622

Нгинкс для продакшен-сайтов, а на компьютере разработчика он только усложняет все. Удобнее обычно либо Апач, либо встроенный в PHP веб-сервер.

>>939618

Прочитай сначала >>939743

>>939610

Тебе надо открыть докуменацию по этому окну и посмтреть, что там какая опция обозначает, так как это неочевидно.

>>939591

Это диалог для запуска композера и установки через него примера приложения от фреймворка. Тебе это не нужно. Как минимум тебе надо сначала изучить композер и нужный фреймворк, прежде чем использовать эту опцию.
#880 #939961
>>939857

Лучше прочесть туториал, а потом команды из него посмотреть в документации.

>>939788

С гуглом не все так просто. Не везде объяснят что такое веб-сервер, как он работает. Часто просто дают конфиг который надо бездумно скопипастить и пользы от таких статей ноль.

>>939638

DocumentRoot это путь к корню сайта, где хранятся скрипты и файлы. Прочти это >>939743

>>939628

Веб-сервер либо не запущен, либо запущен на каком-то нестандартном порту и он не указан в URL. Прочти это сначала >>939743

>>939622

Нгинкс для продакшен-сайтов, а на компьютере разработчика он только усложняет все. Удобнее обычно либо Апач, либо встроенный в PHP веб-сервер.

>>939618

Прочитай сначала >>939743

>>939610

Тебе надо открыть докуменацию по этому окну и посмтреть, что там какая опция обозначает, так как это неочевидно.

>>939591

Это диалог для запуска композера и установки через него примера приложения от фреймворка. Тебе это не нужно. Как минимум тебе надо сначала изучить композер и нужный фреймворк, прежде чем использовать эту опцию.
#881 #939962
>>939575

Я говорю про настройку по умолчанию, заложенную в PHP. При чем тут сборка ampps, в которую входит PHP? Если люди мой код будут запускать на ideone, то там ведь будут применяться настройки по умолчанию скорее всего.

И у PHP нет отдельных версий для продакшена и для разработки.

>>939566
>>939563

Можно в PDF сохранить. Ну или сохранить в опеноффисе в формате какого-нибудь старого Word 2003 и скорее всего все откроется.

Как это надо форматировать текст, чтобы оформление слетело? Ты наверно используешь каике-то фичи нестандартные просто.

>>939550

Из твоего описания непонятно, в чем проблема. Где буквы выводятся как вопросительные знаки? Что ты сделал? Скорее всего PhpStorm тут вообще не при чем. Ну и на всякий случай глянь ссылки тут, может что есть: >>939743

Обычно надо настроить везде utf-8: кодировку исходного кода в редакторе, тег meta charset, если используется браузер.

Вообще, вопросы по PhpStorm логичнее было бы адресовать в их техподдержку.

>>939546

Вот на этом твоем скришоте в заголовке написано CLI: https://2ch.hk/pr/src/919074/14878266574851.png (М)
#882 #939963
>>939517

> еще хотел спросить про роутинг, как в мой метод run() в Router добавить 404 error, попробовал сделать такое если не существует вызываемого класса или метода, но выдает ошибку Cannot modify header information


Прочти про протокол HTTP тут например https://github.com/codedokode/pasta/blob/master/soft/web-server.md

Прочти мануал по функции header().

Там в ответе сначала идут заголовки, потом тело ответа. Если ты вывел хоть один символ, хоть один пробел, то заголовки отравлять уже нельзя. В мануале это написано.

Некоторые делают ошибку, сохраняя файлы в кодировке utf-8 с BOM. BOM это невидимый символ, который вставляется в начало документа до <?php, выводится интерпретатором PHP и не позволяет отправлять заголовки.

Проверь, нет ли у тебя файлов с BOM или файлов с пробелом или еще чем-то, что выводится до заголовков.

Также, у тебя неправильный код. Почитай про пртокол HTTP. Почитай, что такое редирект. Если ты используешь Location то PHP автоматически меняет код статуса ответа на 3xx вместо 404. Соответственно это уже получаеся не страница 404, а что-то другое.

Ты как-то пропускаешь темы. Ну как можно использовать редирект, не изучив, что такое HTTP, как это работает, как его обрабатывает браузер итд. Надо изучать теорию, что происходит при вызове той или иной функции.

> еще хотел спросить как мне сделать view для подготовки данных на вывод, может в гайде было, перечитаю еще раз


Почитай это: http://www.phpinfo.su/articles/practice/shablony_v_php.html

>>939498

AllowOverride должно быть достаточно. Может, там где-то стоит запрещающий AllowOverride, или ты не перезапустил Апач поле правки конфига, или ты опечатался в названии файла .htaccess

>>939480

Если не можешь помочь, то не надо. Почитай второй пост. У нас тут не тред для хвастовства, у кого глаза краснее.

Ну и мне тоже есть чем похвастаться. Я например, всего за 2 вечера смог пропатчить и скопилировать PHP7 под Windows XP (правда немного костыльно и пока без расширений). Уверен, что в линуксе, даже в какой-нибудь генте с такими задачами сталкиваться не приходится.

>>939236

> $news = \App\Models\Article::getAll();


В Доктрине используется паттерн Data Mapper, а не Active Record. Тебе надо сначала изучить теорию про паттерны работы с БД: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Затем изучить документацию Доктрины внимательно, так как без ее хорошего знания в Симфони ты не разберешься.

> Все работает, но если я допустим хочу к с этой выборкой предварительно сделать что-то до выведения в шаблон, например закешировать текст новости, в котором существуют markdown теги, то мне это где правильнее сделать?


Правильно сделать сервис получения новостей, в нем настроить кеширование, а в контроллере вызвать его:

$news = $newsService->getLatestNews();

Ну то есть сделать это в модели (сервисы очевидно часть модели в MVC). Я тебе советую сначала почитать урок про MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md

Вообще, я советую зайти в мой гитхаб https://github.com/codedokode/pasta/ . Симфони это не фреймворк для чайников и для начинающих. Ты должен изучить процентов 90 из того, что у меня в гитхабе только для того, чтобы читать туториалы для начинающих по Симфони. надо знать MVC, ООП, DI. Ты видимо пропустил основы и взялся сразу за сложное, отсюда и непонимание.

И кстати. чтобы в ней разобраться, мало читать документацию, многие вещи можно узнать только из ее исходного кода. Надо его изучать и разбирать.

> бы сам ответил что в Entity, предварительно сделав родительский класс.


Неправильно. Entity просто представляет сущность и ни про какие кеши ничего знать не должна.

Ну и наследование там тоже не нужно.
#882 #939963
>>939517

> еще хотел спросить про роутинг, как в мой метод run() в Router добавить 404 error, попробовал сделать такое если не существует вызываемого класса или метода, но выдает ошибку Cannot modify header information


Прочти про протокол HTTP тут например https://github.com/codedokode/pasta/blob/master/soft/web-server.md

Прочти мануал по функции header().

Там в ответе сначала идут заголовки, потом тело ответа. Если ты вывел хоть один символ, хоть один пробел, то заголовки отравлять уже нельзя. В мануале это написано.

Некоторые делают ошибку, сохраняя файлы в кодировке utf-8 с BOM. BOM это невидимый символ, который вставляется в начало документа до <?php, выводится интерпретатором PHP и не позволяет отправлять заголовки.

Проверь, нет ли у тебя файлов с BOM или файлов с пробелом или еще чем-то, что выводится до заголовков.

Также, у тебя неправильный код. Почитай про пртокол HTTP. Почитай, что такое редирект. Если ты используешь Location то PHP автоматически меняет код статуса ответа на 3xx вместо 404. Соответственно это уже получаеся не страница 404, а что-то другое.

Ты как-то пропускаешь темы. Ну как можно использовать редирект, не изучив, что такое HTTP, как это работает, как его обрабатывает браузер итд. Надо изучать теорию, что происходит при вызове той или иной функции.

> еще хотел спросить как мне сделать view для подготовки данных на вывод, может в гайде было, перечитаю еще раз


Почитай это: http://www.phpinfo.su/articles/practice/shablony_v_php.html

>>939498

AllowOverride должно быть достаточно. Может, там где-то стоит запрещающий AllowOverride, или ты не перезапустил Апач поле правки конфига, или ты опечатался в названии файла .htaccess

>>939480

Если не можешь помочь, то не надо. Почитай второй пост. У нас тут не тред для хвастовства, у кого глаза краснее.

Ну и мне тоже есть чем похвастаться. Я например, всего за 2 вечера смог пропатчить и скопилировать PHP7 под Windows XP (правда немного костыльно и пока без расширений). Уверен, что в линуксе, даже в какой-нибудь генте с такими задачами сталкиваться не приходится.

>>939236

> $news = \App\Models\Article::getAll();


В Доктрине используется паттерн Data Mapper, а не Active Record. Тебе надо сначала изучить теорию про паттерны работы с БД: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Затем изучить документацию Доктрины внимательно, так как без ее хорошего знания в Симфони ты не разберешься.

> Все работает, но если я допустим хочу к с этой выборкой предварительно сделать что-то до выведения в шаблон, например закешировать текст новости, в котором существуют markdown теги, то мне это где правильнее сделать?


Правильно сделать сервис получения новостей, в нем настроить кеширование, а в контроллере вызвать его:

$news = $newsService->getLatestNews();

Ну то есть сделать это в модели (сервисы очевидно часть модели в MVC). Я тебе советую сначала почитать урок про MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md

Вообще, я советую зайти в мой гитхаб https://github.com/codedokode/pasta/ . Симфони это не фреймворк для чайников и для начинающих. Ты должен изучить процентов 90 из того, что у меня в гитхабе только для того, чтобы читать туториалы для начинающих по Симфони. надо знать MVC, ООП, DI. Ты видимо пропустил основы и взялся сразу за сложное, отсюда и непонимание.

И кстати. чтобы в ней разобраться, мало читать документацию, многие вещи можно узнать только из ее исходного кода. Надо его изучать и разбирать.

> бы сам ответил что в Entity, предварительно сделав родительский класс.


Неправильно. Entity просто представляет сущность и ни про какие кеши ничего знать не должна.

Ну и наследование там тоже не нужно.
#883 #939965
>>939377

Репозиторий это плохое место для кеширования так как репозитории не создаются через DI контейнер и сервис кеша ты туда так просто не внедришь. Репозиторий предназначен только для каких-то операций с БД.

> Туда ты записываешь все необходимые тебе методы работы с данными, для этого у доктрины есть прекрасный QueryBuilder.


Ты не понимаешь, зачем нужен QB. Почитай мой урок про паттерны: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Код с QB намного хуже читается чем SQL или DQL. QB используют там, где SQL/DQL использовать не получается.

>>939380

Работа Доктрины - только загружать и сохранять сущности в БД.

>>939196

Может кому-то просто нравится его использовать?

Если тебе в винде удобно, то используй ее. Но линукс изучить все равно надо, так как он на серверах используется.

>>938988

Баги исправить, добавить на сайт какую-нибудь страницу, сделать рассылку писем и тд, зависит от компании. Обычно только какие-то сложные вещи, вроде выбора архитектуры, фреймворков и тд, поручают опытным разработчикам, а все остальное можно и джуниору, почему нет, если задачу правильно поставить.

>>938811

У кук есть параметр path. По умолчанию он совпадает с URL страницы и может у тебя кука ставится не на весь сайт, а на его подраздел.

> то меня при обновлении страницы (например, методом post из формы) выкидывает на главную страницу, т.е. кука удаляется?


Скорее всего у тебя просто ошибки в коде.

>>938694

Встроенный REPL есть (-a), но очень убогий. Я им не пользуюсь. Если надо запустить что-то в консоли, пишу php -r 'echo "Yes!\n";'

>>938097

> что без ретерна ф-я бы ничего не возвращала


Правильнее сказать, что в PHP функция по умолчанию возвращает значение null.
#883 #939965
>>939377

Репозиторий это плохое место для кеширования так как репозитории не создаются через DI контейнер и сервис кеша ты туда так просто не внедришь. Репозиторий предназначен только для каких-то операций с БД.

> Туда ты записываешь все необходимые тебе методы работы с данными, для этого у доктрины есть прекрасный QueryBuilder.


Ты не понимаешь, зачем нужен QB. Почитай мой урок про паттерны: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Код с QB намного хуже читается чем SQL или DQL. QB используют там, где SQL/DQL использовать не получается.

>>939380

Работа Доктрины - только загружать и сохранять сущности в БД.

>>939196

Может кому-то просто нравится его использовать?

Если тебе в винде удобно, то используй ее. Но линукс изучить все равно надо, так как он на серверах используется.

>>938988

Баги исправить, добавить на сайт какую-нибудь страницу, сделать рассылку писем и тд, зависит от компании. Обычно только какие-то сложные вещи, вроде выбора архитектуры, фреймворков и тд, поручают опытным разработчикам, а все остальное можно и джуниору, почему нет, если задачу правильно поставить.

>>938811

У кук есть параметр path. По умолчанию он совпадает с URL страницы и может у тебя кука ставится не на весь сайт, а на его подраздел.

> то меня при обновлении страницы (например, методом post из формы) выкидывает на главную страницу, т.е. кука удаляется?


Скорее всего у тебя просто ошибки в коде.

>>938694

Встроенный REPL есть (-a), но очень убогий. Я им не пользуюсь. Если надо запустить что-то в консоли, пишу php -r 'echo "Yes!\n";'

>>938097

> что без ретерна ф-я бы ничего не возвращала


Правильнее сказать, что в PHP функция по умолчанию возвращает значение null.
939999
#884 #939966
>>938087

Там неправильно сформулировано. Если ты не вернешь значение явно командой return, то функция возвращает значение null. Неправильно говорить "переменная будет пустая".

> я должен буду всегда в конце функции написать return с указанным аргументом в виде переменной, в которой я хочу получить результат?



Невнимательно ты прочел мои объяснения.

Ты не можешь указать переменную, в которую ты хочешь получить результат, так как внутри функции внешние переменные не видны. Ты указываешь после return выражение, которое надо вычислить и значение которого надо вернуть из функции. Примеры:

return 1;
return 2 + 2;
$x = 1; return $x;
return "Yes";
return mt_rand(1, 100);

>>938071

Да, return завершает выполнение функции. После него идет возврат в то место, откуда была вызвана функция.

>>938041

Местами мануал не очень понятно написан. Давай разберем по словам.

> return возвращает управление программой модулю, из которого была вызвана функция....


Под "модулем" здесь имеется кусок кода, откуда была вызвана функция.

> Выполнение программы продолжается с инструкции, следующей за местом вызова.


Инструкция - это команда, из которых состоит программа и которые разделяются точкой с запятой. Вот примеры инструкций:

$x = 1;
echo "yes";
doSomething();

Имеется в виду то, что команда return завершает выполнение функции и выполнение программы продолжается с того места, откуда была вызвана функция.return значит "вернуться". Вернуться к месту, откуда была вызвана функция и продолжать выполнять код там.

Вот например код:

echo "1";
func(1);
echo "2";
func(2);
echo "3";
func(3);

Этот код выполняется так:

- выполняется echo "1"
- вызвается функция func с аругментом 1. Интерпретатор переходит к ней и выполняет записанные в ней команды
- затем, после того, как он выполнит все команды в функции или выйдет из нее по команде return, он возвращается к месту вызова (к строке func(1)) и продолжает выполнять код после нее.
- выполняется echo "2"
- снова вызвается функция func, но уже с аргументом 2. Выполняются записанные в ней команды
- выполняется echo "3"
- и так далее
#884 #939966
>>938087

Там неправильно сформулировано. Если ты не вернешь значение явно командой return, то функция возвращает значение null. Неправильно говорить "переменная будет пустая".

> я должен буду всегда в конце функции написать return с указанным аргументом в виде переменной, в которой я хочу получить результат?



Невнимательно ты прочел мои объяснения.

Ты не можешь указать переменную, в которую ты хочешь получить результат, так как внутри функции внешние переменные не видны. Ты указываешь после return выражение, которое надо вычислить и значение которого надо вернуть из функции. Примеры:

return 1;
return 2 + 2;
$x = 1; return $x;
return "Yes";
return mt_rand(1, 100);

>>938071

Да, return завершает выполнение функции. После него идет возврат в то место, откуда была вызвана функция.

>>938041

Местами мануал не очень понятно написан. Давай разберем по словам.

> return возвращает управление программой модулю, из которого была вызвана функция....


Под "модулем" здесь имеется кусок кода, откуда была вызвана функция.

> Выполнение программы продолжается с инструкции, следующей за местом вызова.


Инструкция - это команда, из которых состоит программа и которые разделяются точкой с запятой. Вот примеры инструкций:

$x = 1;
echo "yes";
doSomething();

Имеется в виду то, что команда return завершает выполнение функции и выполнение программы продолжается с того места, откуда была вызвана функция.return значит "вернуться". Вернуться к месту, откуда была вызвана функция и продолжать выполнять код там.

Вот например код:

echo "1";
func(1);
echo "2";
func(2);
echo "3";
func(3);

Этот код выполняется так:

- выполняется echo "1"
- вызвается функция func с аругментом 1. Интерпретатор переходит к ней и выполняет записанные в ней команды
- затем, после того, как он выполнит все команды в функции или выйдет из нее по команде return, он возвращается к месту вызова (к строке func(1)) и продолжает выполнять код после нее.
- выполняется echo "2"
- снова вызвается функция func, но уже с аргументом 2. Выполняются записанные в ней команды
- выполняется echo "3"
- и так далее
#885 #939967
>>937819

Чтобы изучать фреймворки нужны базовые знания - ООП, DI, MVC, работа с базой. У тебя их возможно нет, потому я советую изучить шапку треда и поизучать что-нибудь оттуда.

CMS предназначены для создания сайта с минимумом программирования. Они в разы проще, но их возможности могут быть ограничены.

Что востребовано, смотри на сайтах вакансий.

>>937678

Как я понимаю, Data Mapper предназначен в первую очередь для сохранения/загрузки объектов в БД и из нее (сопоставления/отображения объектов в памяти на строчки таблицы в базе данных).

TableDataGateway - это просто класс-сборник методов для работы с таблицей, не только загрузка/сохранение объектов туда, но и любые другие манипуляции. Удаление например или какая-нибудь хитрая обработка записей в базе.

С другой стороны, Data Mapper может быть более продвинутым. Ну например, он сам может находить изменившиеся объекты и записывать изменения в базу. Или например он может доставать не только объект из БД, но и позволять получить связанные с ним объекты.

Можно еще почитать подробные описания паттернов в книге Фаулера (Шаблоны разработки корпоративных приложений) и сравнить их.

>>937592

Может у тебя просто на локальном сервере отключен вывод ошибок (display_errors в php.ini), они идут в логи, но ты туда не смотришь и думаешь, что их нет? Проверь логи веб-сервера, логи Юи.
#886 #939968
>>919800

Я не вижу никакой ошибки на строке 12, но код по моему некорректный. Вот смотри:

> for ($i = 1; $i <= count($totalArray); $i++) {


> if ($i % $skip == 0) {


> unset($totalArray[$i]);


Эта штука просто удалит элементы, индекс которых делится на $skip. Ну то есть 5, 10, 15, 20, но остальные элементы она не тронет никогда. В PHP при удалении элемента через unset остальные индексы не перечитываются. Используй array_splice если хочешь, чтобы после удаления элементы заново нумеровались от 0 до N.

>>924207

Неудобно работать с гигантскими файлами из многих тысяч строк. Ну и вообще, библиотека в PHP это обычно не один файл, а много.

>>924834

Там задача про кредит сложная, на ней все спотыкаются. Твое решение считает верно, но я бы вынес из кода числа вроде 1000, 5000 и поместил бы их в переменные в начале программы, чтобы их можно было легко менять.

>>925011

> if (is_numeric($char)) $currNumber .= $char;


Не стоит экономить на фигурных скобках тут.

> exit();


Функция тут не должна делать exit, надо делать return, а то твою функцию 2 раза нельзя будет вызвать. Также, лучше, если функция не выводит ответ, а возвращает, чтобы вызывающий код мог делать с ним что хотел.

Само решение правильное.

>>925132

Вообще, лучше бы в первый раз было все самому ставить, чтобы разобраться как это все в связке работает.

>>925277

Наверно, баг, я не наблюдал.

>>925387

Да, ты описал все верно. Единственное, что $Line['text'][0] это скорее получение первого символа в строке (работает только с латиницей).

>>926076

http://www.phpinfo.su/articles/practice/shablony_v_php.html
#886 #939968
>>919800

Я не вижу никакой ошибки на строке 12, но код по моему некорректный. Вот смотри:

> for ($i = 1; $i <= count($totalArray); $i++) {


> if ($i % $skip == 0) {


> unset($totalArray[$i]);


Эта штука просто удалит элементы, индекс которых делится на $skip. Ну то есть 5, 10, 15, 20, но остальные элементы она не тронет никогда. В PHP при удалении элемента через unset остальные индексы не перечитываются. Используй array_splice если хочешь, чтобы после удаления элементы заново нумеровались от 0 до N.

>>924207

Неудобно работать с гигантскими файлами из многих тысяч строк. Ну и вообще, библиотека в PHP это обычно не один файл, а много.

>>924834

Там задача про кредит сложная, на ней все спотыкаются. Твое решение считает верно, но я бы вынес из кода числа вроде 1000, 5000 и поместил бы их в переменные в начале программы, чтобы их можно было легко менять.

>>925011

> if (is_numeric($char)) $currNumber .= $char;


Не стоит экономить на фигурных скобках тут.

> exit();


Функция тут не должна делать exit, надо делать return, а то твою функцию 2 раза нельзя будет вызвать. Также, лучше, если функция не выводит ответ, а возвращает, чтобы вызывающий код мог делать с ним что хотел.

Само решение правильное.

>>925132

Вообще, лучше бы в первый раз было все самому ставить, чтобы разобраться как это все в связке работает.

>>925277

Наверно, баг, я не наблюдал.

>>925387

Да, ты описал все верно. Единственное, что $Line['text'][0] это скорее получение первого символа в строке (работает только с латиницей).

>>926076

http://www.phpinfo.su/articles/practice/shablony_v_php.html
#887 #939999
>>939965
Прочёл твою заметку. Спасибо. Ответь тогда тому Анону на вопрос про кеширование, раз я ответил неправильно.
Вопрос по файлообменнику #888 #940144
ОП, ты писал о том, что валидацию загруженного файла лучше осуществлять в сервисе загрузки файла.
Выходит, что сервис загрузки файла должен делать такие вещи:
- загрузить файл на сервер, вернуть сущность File в случае успеха. Это сущность нужна контроллеру, чтобы он мог выполнить редирект на страницу с этой сущностью
- как-то обработать ошибки и если они есть, отдать их наверх. Получается, что метод upload может вернуть 2 разных объекта в зависимости от валидности файла? Это, наверное, неправильно: нужно делать проверки на instanceof в контроллере.
Не понимаю, как сюда вклинить обработку ошибок, набросок сервиса: https://ideone.com/ijUVZR
набросок контроллера: https://ideone.com/dgyVC5
Я использую такую абстракцию для файла: https://github.com/symfony/http-foundation/blob/master/File/File.php
Почему сразу не использую UploadedFIle: https://github.com/symfony/http-foundation/blob/master/File/UploadedFile.php
Его тоже можно переместить, даже если он получен не из HTTP (параметр $test в конструкторе), но, как я понял, параметр $test тут только для тестов.
940151940163944654
#889 #940151
>>940144

>чтобы он мог выполнить редирект на страницу с этой сущностью


А зачем?

>Получается, что метод upload может вернуть 2 разных объекта в зависимости от валидности файла? Это, наверное, неправильно: нужно делать проверки на instanceof в контроллере.


Зачем? Разве не логичней в случае ошибки вернуть false? Тоже делаю фйлообменник, если что.
940156
#890 #940156
>>940151

>> чтобы он мог выполнить редирект на страницу с этой сущностью


> А зачем?


Ну вот загрузил ты файл на файлообменник и хочешь поделиться ссылочкой. Логично сразу после загрузки произвести редирект. rghost тоже делает редирект на загруженный файл, можешь проверить.

>> Получается, что метод upload может вернуть 2 разных объекта в зависимости от валидности файла? Это, наверное, неправильно: нужно делать проверки на instanceof в контроллере.


> Зачем? Разве не логичней в случае ошибки вернуть false? Тоже делаю фйлообменник, если что.



А как ты донесёшь до пользователя причину ошибки? Фразой "Что-то пошло не так"? Я хочу давать внятные объяснения.
940172
3970 Кб, Webm
#891 #940163
>>940144
Если ты используешь силекс, то можешь воспользоваться уникальной возможностью прикрутить к нему симфониевские формы и валидатор. Если же нет, то советую сделать следующее:
Сделать контроллер страницы загрузки, куда попадает засубмиченая форма
Сразу валидировать форму с помощью сервиса валидации, который отправляет true/false в контроллер
Если форма валидна - сохранять файл и редиректить куда тебе надо
Если нет, то рендерить тот же шаблон с ошибкой
#892 #940172
>>940156

>А как ты донесёшь до пользователя причину ошибки? Фразой "Что-то пошло не так"? Я хочу давать внятные объяснения.


Вроде как такое должны делать исключения, не? Типа в контроллере траишь, и если всплыло исключение то вместо редиректа показываешь шаблон с ошибкой. Я бы как-то так делал.
944639
#893 #940269
Гайс.
Почему действие2 не выполняется?
$ears = 0;
for ($vklad = 10000; $vklad < 1000000; $vklad 1.1 ) {
$ears++;
}
$earsOld = 16 + $ears;
echo "Вкладчику будет $earsOld лет. В банке будет 1000000 через $ears лет.";

Если я его отдельно запилю, то все работает, а в самом цикле - нет.
$ears = 0;
for ($vklad = 10000; $vklad < 1000000; ) {
$ears++;
$vklad = $vklad
1.1;
}
$earsOld = 16 + $ears;
echo "Вкладчику будет $earsOld лет. В банке будет 1000000 через $ears лет.";
940270
#894 #940270
>>940269
пропустилзнак умножения, но с ним все равно не работает
$ears = 0;
for ($vklad = 10000; $vklad < 1000000; $vklad * 1.1) {
$ears++;
}
$earsOld = 16 + $ears;
echo "Вкладчику будет $earsOld лет. В банке будет 1000000 через $ears лет.";
940338
#895 #940338
>>940270

$x * 10 умножает $x на 10 но никуда не сохраняет результат, и $x остается неизменной

Надо писать $x = $x * 10 или  $x *=10 чтобы сохранить результат.
940613
#896 #940343
С куревом лучше учится. Бля буду.
#897 #940613
>>940338
Спасибо!
#898 #940667
>>919074 (OP)
Ребят, а у вас своего скайп-чата нету? Раньше был, вроде...
940736
#899 #940736
>>940667
Раньше был... ты про тот в котором я и ещё один анон который написал 4 сообщения и съебал?
940839
#900 #940772
Пыханы, делаю тестхаб на симфони и возник у меня вопрос. Есть 3 таблицы: User, Test и Question. Они все связаны внешними ключами по типу one to many User => many to one Test one to many Test=> many to one Question. Как вообще обычно делаются заполнения подобных таблиц? Это нужно как-то прописывать в репозитории или что? Пытаюсь передать id юзера в тест вручную, а доктрина при создании теста говорит, что туда нужно пихать инстанс юзера.

И вот допустим я создаю тест и нужно туда создать вопросов и тут 2 варианта:
1 создать сначала пустой тест, а потом по ссылке перейти на форму создания вопросов
2 создавать сразу тест с вопросами
В первом варианте недостаток в том. что юзер может спамить пустыми тестами, создавая их до бесконечности, а во втором не понятно как объединить форму теста с формой вопроса, при том, что тест еще не создан, а значит id его не известно(автогенерация) и вопросы не могут быть привязаны к этому тесту.
940856
#901 #940830
Есть такой чувак https://kwork.ru/links/1754/ssylki-c-bolee-1000-saytov-s-tits-10-650 который предлагает поставить 1000 ссылок на продвигаемый сайт с других сайтов всего лишь за 500 рублей. Само собой он не будет ставить их вручную а всё сделает автоматически. Для этого пишутся парсеры? Но если сайтов много и они разные выходит для каждого сайта нужно написать свой парсер? как найти подходящие сайты, с которых ссылки будут котироваться поисковыми системами?
#902 #940839
>>940736
Не знаю. Какой-то был точно. Нельзя ли снова создать?

>тот в котором я


Ты - оп?
940840
#903 #940840
>>940839
Нет, я Феликс.
940842
#904 #940842
>>940840

>я Феликс


Хм... Извини, не знаю тебя. Но ведь чат можно открыть повторно?
940844
#905 #940844
>>940842
Нет, он закрыт навсегда. Можно создать новый если хочешь.
940848
#906 #940848
>>940844

> закрыт навсегда


К хренам собачьим?

>Можно создать новый если хочешь.


Хочу. Только было бы неплохо, если бы там помимо меня был ещё кто-то. Вообще, помню, там людей было немало - человек 10-15, вроде.
940850
#907 #940850
>>940848
В телеграмме было 10-15 человек. Но там было по 1500 мужских членов в сутки, поэтому не взлетело.
940851
#908 #940851
>>940850

>по 1500 мужских членов в сутки


Зачем? Это гей-чат был?
940854
#909 #940854
>>940851
Там было 3 дебила которых никто не хотел банить, потому-что ШВАБОДА ОБЩЕНИЯ!!!! ШВАБОДА МНЕНИЯ!!! В итоге все адекватные аноны поливали.
940862
#910 #940856
>>940772

Тебе надо изучить мануал доктрины про отношения:

- (англ) http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html
- http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html
- перевод был на этом сайте http://archive.li/WreO6 но его отключили, а веб-архив не показывает страницы из-за robots.txt

Так как Доктрины пытается создать видимость, что все объекты находятся в памяти, то связи в них делают через поля с нужной аннотауцией. Если например у Теста есть Автор, то мы так и пишем:

class Test
{
// аннотация ManyToOne
protected $author;
}

И Доктрина сама подставит туда либо объект Пользователь, либо прокси-объект для ленивой загрузки.

Ну и ты можешь туда прописать объект Пользователя и при flush() соответствующие внешние ключи в базе может быть будут обновлены (там есть подвох, проверяется только один объект в отношении и надо понимать, какой).

Там надо изучить документацию, так как много особенностей, которые надо понимать. И про коллекции, и про ленивую загрузку и прокси-объекты.

Соответственно для установки связи тебе не нужны id и ты можешь создавать целые графы из объектов:

$author = new User;
$test = new Test;
$test->setAuthor($author);
$question = new Question;
$test->addQuestion($question);

$em->persist(...);
$em->flush();

> 1 создать сначала пустой тест, а потом по ссылке перейти на форму создания вопросов


> 2 создавать сразу тест с вопросами


А зачем создавать пустой тест? Что тебе мешает сразу переходить на форму создания теста, не создавая ничего в БД?

> а во втором не понятно как объединить форму теста с формой вопроса, при том, что тест еще не создан, а значит id его не известно(автогенерация) и вопросы не могут быть привязаны к этому тесту.


Если ты используешь аякс, то у тебя одна страница с которой ты никуда не уходишь, и проблемы нет (хотя даже в этом случае надо подумать, как сохранять данные на случай например закрытия браузера или неожиднного отключения питания). Если ты не используешь аякс, а используешь обычные формы то да, тебе надо где-то хранить пока еще не сохраненный тест. Тут много вариантов, у каждого свои недостатки:

- хранить все несохраненные данные в скрытых полях формы (например сериализованную версию графа объектов теста), и передавать с одной страницы на другую (сложновато, но зато соответствует идеям REST). В ASP по моему когда-то такая штука использовалась.
- хранить в БД, с пометкой, что это не сохраненный тест (чтобы не показывать его в списках). При желании можно написать сборщик мусора, удаляющий старые не сохраненные тесты, но я не уверен, что это хорошая идея. Может лучше их хранить под названием "черновики тестов"?
- сделать какое-то временное хранилище, вроде отдельной таблицы, и там хранить сериализованные данные. Что-то вроде сессий, только не на основе кук.
- сессии. Не нравится тем, что они удаляются через полчаса неиспользования, и тем что они общие для всех вкладок браузера, неудобно будет редактировать 2 теста одновременно.

Поясню про сериализацию. Доктрина позволяет связывать объекты без id, и ты можешь в конце скрипта сериализовать граф несохраненных в БД объектов теста, вопросов и тд и сохранять его например в скрытом поле формы, а в начале скрипта - восстанавливать его. Правда с восстановлением сохраненных в БД сущностей будут некоторые сложности, но их при желании можно решить.

Примерно так:

$serialized = serialize($test);
<input type="hidden" value="{{ serialized }}">

Тут правда есть проблема: десериализовывать данные, пришедшие от пользвоателя небезоасно, это может привести к уязвимости, были случаи. Так что хранить данные надо не в форме, а на сервере, либо надо их сериализовывать в какой-то безопасный формат вроде JSON и тщательно проверять при восстановлении.

> юзер может спамить пустыми тестами, создавая их до бесконечности,


А пустые можно не сохранять. А если юзер что-то ввел, то может он хочет чтобы эти данные сохранились и чтобы он мог продолжить редактирвать тест позже. Насчет места я бы не беспокоился - сейчас в ходу терабайтные диски. Фейсбук например сохраняет даже стертые и не отправленные посты и его это не беспокоит.
#910 #940856
>>940772

Тебе надо изучить мануал доктрины про отношения:

- (англ) http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html
- http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html
- перевод был на этом сайте http://archive.li/WreO6 но его отключили, а веб-архив не показывает страницы из-за robots.txt

Так как Доктрины пытается создать видимость, что все объекты находятся в памяти, то связи в них делают через поля с нужной аннотауцией. Если например у Теста есть Автор, то мы так и пишем:

class Test
{
// аннотация ManyToOne
protected $author;
}

И Доктрина сама подставит туда либо объект Пользователь, либо прокси-объект для ленивой загрузки.

Ну и ты можешь туда прописать объект Пользователя и при flush() соответствующие внешние ключи в базе может быть будут обновлены (там есть подвох, проверяется только один объект в отношении и надо понимать, какой).

Там надо изучить документацию, так как много особенностей, которые надо понимать. И про коллекции, и про ленивую загрузку и прокси-объекты.

Соответственно для установки связи тебе не нужны id и ты можешь создавать целые графы из объектов:

$author = new User;
$test = new Test;
$test->setAuthor($author);
$question = new Question;
$test->addQuestion($question);

$em->persist(...);
$em->flush();

> 1 создать сначала пустой тест, а потом по ссылке перейти на форму создания вопросов


> 2 создавать сразу тест с вопросами


А зачем создавать пустой тест? Что тебе мешает сразу переходить на форму создания теста, не создавая ничего в БД?

> а во втором не понятно как объединить форму теста с формой вопроса, при том, что тест еще не создан, а значит id его не известно(автогенерация) и вопросы не могут быть привязаны к этому тесту.


Если ты используешь аякс, то у тебя одна страница с которой ты никуда не уходишь, и проблемы нет (хотя даже в этом случае надо подумать, как сохранять данные на случай например закрытия браузера или неожиднного отключения питания). Если ты не используешь аякс, а используешь обычные формы то да, тебе надо где-то хранить пока еще не сохраненный тест. Тут много вариантов, у каждого свои недостатки:

- хранить все несохраненные данные в скрытых полях формы (например сериализованную версию графа объектов теста), и передавать с одной страницы на другую (сложновато, но зато соответствует идеям REST). В ASP по моему когда-то такая штука использовалась.
- хранить в БД, с пометкой, что это не сохраненный тест (чтобы не показывать его в списках). При желании можно написать сборщик мусора, удаляющий старые не сохраненные тесты, но я не уверен, что это хорошая идея. Может лучше их хранить под названием "черновики тестов"?
- сделать какое-то временное хранилище, вроде отдельной таблицы, и там хранить сериализованные данные. Что-то вроде сессий, только не на основе кук.
- сессии. Не нравится тем, что они удаляются через полчаса неиспользования, и тем что они общие для всех вкладок браузера, неудобно будет редактировать 2 теста одновременно.

Поясню про сериализацию. Доктрина позволяет связывать объекты без id, и ты можешь в конце скрипта сериализовать граф несохраненных в БД объектов теста, вопросов и тд и сохранять его например в скрытом поле формы, а в начале скрипта - восстанавливать его. Правда с восстановлением сохраненных в БД сущностей будут некоторые сложности, но их при желании можно решить.

Примерно так:

$serialized = serialize($test);
<input type="hidden" value="{{ serialized }}">

Тут правда есть проблема: десериализовывать данные, пришедшие от пользвоателя небезоасно, это может привести к уязвимости, были случаи. Так что хранить данные надо не в форме, а на сервере, либо надо их сериализовывать в какой-то безопасный формат вроде JSON и тщательно проверять при восстановлении.

> юзер может спамить пустыми тестами, создавая их до бесконечности,


А пустые можно не сохранять. А если юзер что-то ввел, то может он хочет чтобы эти данные сохранились и чтобы он мог продолжить редактирвать тест позже. Насчет места я бы не беспокоился - сейчас в ходу терабайтные диски. Фейсбук например сохраняет даже стертые и не отправленные посты и его это не беспокоит.
#911 #940862
>>940854
Никогда такого не делал. Как думаешь, где лучше сделать чат - в telegram или скайпе?каким файлообменником ты пользуешься?
940865
#912 #940865
>>940862
Скайп блокирует 80 и 443 порт, а они нужны апачу, вмваре и опенсерверу. Так что лучше телеграмм. Ну или ты будешь обьяснять как настраивать скаеп каждому новому ньюфагету.
940869940871
#913 #940869
>>940865

>Скайп блокирует


Погоди, разве он не так создается?: https://www.youtube.com/watch?v=yJfx_3m1Byg
#914 #940871
>>940865

Это отклчается в настройках.
940876
#915 #940876
>>940871

>ты будешь обьяснять как настраивать скаеп каждому новому ньюфагету.

940880940888
#916 #940880
>>940876
Скажи членораздельно - скайп-чат же создается и настраивается так, как эта женщина показала?
940884
#917 #940884
940888940905
#918 #940888
>>940884
>>940876

>>ты будешь обьяснять как настраивать скаеп каждому новому ньюфагету.


Это чат - пусть для новеньких - но, всё-таки, программистов. Если человек не может установить скайп и отправить заявку в группу, ему там, пожалуй, не место, разве нет?
#919 #940905
>>940884
Ну так давай создадим - в скайпе или телеграме.
941251
#920 #941111
+ за телеграм
941126
#921 #941126
>>941111
Как назовем? ))
941152
#922 #941152
>>941126
gay ass fuckers unite!!!
941169
#923 #941169
>>941152
Чтобы снова не взлетело? Нужно солидное что-то.
Вот, знаешь, любопытно, почему среди тестовых заданий опа ещё нет написания имиджборды, м?
#924 #941204
ОП, ты огромный красавчик, честно. Я вот сейчас так поглядел на количество представленного в шапке материала, думаю я бы в свое время гораздо быстрее бы пхп раздрочил + много вещей еще решил пересмотреть. громадный тебе +
#925 #941248
https://t.me/joinchat/AAAAAEK4I33x7_HF3IdOvQ
Телеграммочатик с автоинвайтом.
941252941255
#926 #941251
>>940905
https://goo.gl/67wB0A
Конфа есть уже, даже с голосом, просто там редко кто-то бывает.
941254
#927 #941252
>>941248
Добавился, но что-то не могу никак отправлять сообщения...
#928 #941254
>>941251

>даже с голосом


Я голосом боюсь.

>там редко кто-то бывает.


Неудивительно.
941256
#929 #941255
>>941248
Там только голосом можно, что ли?
#930 #941256
>>941254
Там голос опционально, только если на голосовой чат жмешь. Иначе текстом просто.
941258
452 Кб, 1809x1050
#931 #941258
>>941256

>попробуй сейчас отправить


Не могу. Может, ты как-то неправильно его настроил?
#932 #941260
Пойду посплю хоть немного. Завтра с чатом разберемся.
#933 #941269
Можно ли найти работу джуниором ПХП в 27 лет, если есть небольшой опыт на фрилансе?
941270941361
#934 #941270
>>941269
Можно.
941271
#935 #941271
>>941270
А если при этом не особо знаешь английский?
941272941273
#936 #941272
>>941271
Можно подучить английский.
#937 #941273
>>941271
1С ждет тебя.
941274
513 Кб, 604x604
#938 #941274
#939 #941289
https://geektimes.ru/post/286304/
Программисты скоро не нужны будут, DeepCoder от Microsoft сам пишет код из требований заказчика. Будущее за самопищущимся кодом.
941301
#940 #941301
>>941289
И сюда это притянули. Ты понимаешь, что даже человеку сложно облачить невнятные требования заказчика в формализованные задачи, что уже говорить о роботах.
Программистов если и заменят, то только в последнюю очередь.
64 Кб, 720x720
#941 #941310
Аноны блять помогите с этой хуетой
Административная панель:
Вывод всех студентов
ФИ
группа
курс
кол-во тестов на 3, 4, 5, общее кол-во
средний балл (% правильных ответов)
средняя оценка
с фильтрами по группам, курсам, предметам
Сортировки при выводе по ФИ, результатам, дате написания последнего теста, %правильных, по среднему баллу.
Добавление, удаление, редактирование записей студентов и о студентах при нажатии на ФИ студента.
Статистическую информацию по каждому студенту:
Сколько раз решал каждый тест
Лучший результат
Подробная информация о попытках (сколько ошибок, сколько времени затратил, дата решения теста) по каждой теме предмета и по общему тесту
Форма создания и редактирования тестов(вопросов)+перемещение между темами
Форма создания и редактирования предметов
Форма создания и редактирования тем
Предусмотреть что в теме уже могут быть вопросы. для того, чтобы удалить тему, нужно либо удалить вопросы этой темы или переместить в другую тему
я вообще хз как это делать
#942 #941325
Интересный пост про архитектуру вконтакте: https://m.habrahabr.ru/post/322562/
#943 #941341
Вопрос по критическим ошибкам в сценариях. Это не про ошибки, возникающие в процессе работы, которые можно бы было выловить с помощью try-catch или exception и обработать, а про ошибки типа fatal (php) typeerror, parsererror (js), которые прекращают текущий сценарий вообще.

PHP:
<?php
function shutdown() {
$error = error_get_last();
if ($error['type'] === E_ERROR) {
header("HTTP/1.1 503 Internal server error");
print json_encode([
'errors' => [
[
'code' => '503',
'message' => $error['message']
]
]
]);
}
}

--- остальной код

Пока использую нечто подобное.

JS:
Нет мыслей.
Тем более важно, что обычно при фатальных ошибках максимум что происходит - это ничего не происходит (кроме сообщения в консоль, но много ли вы видели людей которые лезут в инструменты разработчика, чтобы посмотреть, что же случилось?).

inb4: фатальные ошибки не могут произойти если всё протестировано отлажено... Возможно, могут? Довольно много лазаю по различным сайтам, иногда вижу php нотайсы, ошибки, бывает даже куски кода вылезают наружу. И это у дядек, которые зарабатывают программированием.
#943 #941341
Вопрос по критическим ошибкам в сценариях. Это не про ошибки, возникающие в процессе работы, которые можно бы было выловить с помощью try-catch или exception и обработать, а про ошибки типа fatal (php) typeerror, parsererror (js), которые прекращают текущий сценарий вообще.

PHP:
<?php
function shutdown() {
$error = error_get_last();
if ($error['type'] === E_ERROR) {
header("HTTP/1.1 503 Internal server error");
print json_encode([
'errors' => [
[
'code' => '503',
'message' => $error['message']
]
]
]);
}
}

--- остальной код

Пока использую нечто подобное.

JS:
Нет мыслей.
Тем более важно, что обычно при фатальных ошибках максимум что происходит - это ничего не происходит (кроме сообщения в консоль, но много ли вы видели людей которые лезут в инструменты разработчика, чтобы посмотреть, что же случилось?).

inb4: фатальные ошибки не могут произойти если всё протестировано отлажено... Возможно, могут? Довольно много лазаю по различным сайтам, иногда вижу php нотайсы, ошибки, бывает даже куски кода вылезают наружу. И это у дядек, которые зарабатывают программированием.
1892 Кб, 500x281
#944 #941347
#945 #941361
>>941269
Бессмысленный вопрос. Если хочешь вкатиться, должен быть подход "даже если все скажут, что нельзя, я все равно вкачусь и выебу этот стереотип" и т.д. и т.п.

Если ты придешь на собеседование и покажешь лучшее владение предметом, чем у всех остальных (а я так понимаю, на джуна большинство кандидатов околонулевого уровня), возьмут конечно тебя.
#946 #941362
Ребят, ну так что, есть желающие для telegram-канала? Создавать?
941370
#947 #941370
>>941362
Саздавай
941379
#949 #941387
>>941379
Добавляйтесь скорее :)
#950 #941459
>>941379
Ещё быстрее :)
38 Кб, 640x360
#951 #941471
>>941379
А если я добавлюсь, но писать ничего не буду?
941474941481
#952 #941474
>>941471
Мы всё равно будем тебе рады.
#953 #941481
>>941471
А если я у тебя спрошу что-нибудь?
#954 #941571
Как организовывают пагинацию? Я помню как с mysql я это делал, но в PDO как-то застрял. Ведь надо передавать параметры выборки. А я чот не понимаю как это делается.
941577
#955 #941577
>>941571
https://github.com/codedokode/pasta/blob/master/student-list.md#Постраничная-навигация/

> Я помню как с mysql я это делал, но в PDO как-то застрял.


А разница в чём? Запросы к базе ведь одинаковые в обоих случаях будут.
#956 #941619
ОПчик, чисто интересно, а ты никогда не думал запилить онлиан-курсы на платной основе по пхп? Просто ты и так дохуя время на всяких ньюфагов тратишь, а так мог бы еще и заработать неплохо. Просто я смотрел несколько таких курсов, и там по больше части либо учат жуткому говнокоду, либо дают набор несистематизированной инфы, я толко несколько годных нашел. У тебя же куча и уроков, и опыта обучения ньюфагов, мог бы сделать годноту. Срзли, подумай над такой возможностью.
941670
#957 #941670
>>941619
Платное обучение гораздо менее доступно.

P.S.: Добро пожаловать в наш чат!:
https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
#958 #941811
Повторное обращение, необходим взгляд со стороны:

Посмотрите, пожалуйста, как сделал задания. Заранее благодарю)

http://ideone.com/9wsu8g - Игра в кубики;
http://ideone.com/sRvu3e - мини "калькулятор";
http://ideone.com/8x1TeV - Игра в кубики с Пекой;
http://ideone.com/pJ4TO8 - Пхп без смс;
http://ideone.com/8GN4S3 - депозит;
http://ideone.com/O7tPEA - Айфон в кредит;
http://ideone.com/7SJzev - Задание со стихами;
http://ideone.com/MGrQkg - Регулярка на номера телефонов
#959 #941854
Что значит выражение "ванильный js-код"?
941860
#960 #941860
>>941854
Код без использования сторонних библиотек, фреймворков и т.п.
#961 #941923
>>941811

>Пхп без смс;


<?php

error_reporting(-1);

$answers = ['да','нет','не знаю','никогда','это зависит от тебя','спроси у анона'];
$question = 'выучил ли ты пхп без смс?';
$answer = $answers[array_rand($answers)];

echo "Вопрос: " . $question . PHP_EOL;
echo "Ответ: " . $answer . PHP_EOL;

#O_o
941934942031
#962 #941934
>>941923
>>941811

Зачем делать ответ массивом, если он только один?
941940
#963 #941937
>>941811

>Игра в кубики с Пекой;


<?php

error_reporting(-1);

$anonDice1 = rand(1,6);
$anonDice2 = rand(1,6);

$compDice1 = rand(1,6);
$compDice2 = rand(1,6);

echo "У анона выпало: $anonDice1 и $anonDice2." . PHP_EOL;
echo "У пеки выпало: $compDice1 и $compDice2." . PHP_EOL;

$anonSum = $anonDice1 + $anonDice2;
$compSum = $compDice1 + $compDice2;

if ($anonDice1 == $anonDice2 && $compDice1 == $compDice2) {
die("у вас выпала дабла" . PHP_EOL);
} elseif ($anonSum > $compSum) {
die("анон подебил" . PHP_EOL);
} elseif ( $anonSum < $compSum) {
die("пека подебил" . PHP_EOL);
}

die("дружба" . PHP_EOL);

#O_O
#963 #941937
>>941811

>Игра в кубики с Пекой;


<?php

error_reporting(-1);

$anonDice1 = rand(1,6);
$anonDice2 = rand(1,6);

$compDice1 = rand(1,6);
$compDice2 = rand(1,6);

echo "У анона выпало: $anonDice1 и $anonDice2." . PHP_EOL;
echo "У пеки выпало: $compDice1 и $compDice2." . PHP_EOL;

$anonSum = $anonDice1 + $anonDice2;
$compSum = $compDice1 + $compDice2;

if ($anonDice1 == $anonDice2 && $compDice1 == $compDice2) {
die("у вас выпала дабла" . PHP_EOL);
} elseif ($anonSum > $compSum) {
die("анон подебил" . PHP_EOL);
} elseif ( $anonSum < $compSum) {
die("пека подебил" . PHP_EOL);
}

die("дружба" . PHP_EOL);

#O_O
942031
#964 #941940
>>941934
Он не один. Насколько я понял, по условию задачи дан массив разных ответов. Из них нужно выбрать один случайный.
#965 #942031
>>941937
>>941923
Щас бы в тред код скинуть.
21 Кб, 841x407
#966 #942059
В задаче на палиндром что нужно использовать, дабы удалить пробелы? В интернете для этого много разных команд выдает.

И ещё вопрос. Вот на прикле я написал, он разве не должен выдать текст со всеми символами в нижнем регистре?
Не могу с палиндромом, постоянно ошибку выдает. Хотя предыдущие два задания решил без проблем.
942144942244943574
#967 #942144
>>942059
у тебя на 14 строке точки с запятой нет.
Пробелы в начале и конце строки удаляются функцией trim(). Если нужно удалить вообще все пробелы, то str_replace() или preg_replace()
28 Кб, 479x346
25 Кб, 827x331
#968 #942244
>>942059
У меня так получилось (см. пик №1):
http://sandbox.onlinephpfunctions.com/code/37e9bafb75f09c766bd25fb9bd66435a24ac9d5a

> он разве не должен выдать текст со всеми символами в нижнем регистре?


Чтобы пользоваться функциями mb_*, нужно установить соответствующее расширение: http://php.net/manual/ru/book.mbstring.php . На ideone, как видишь (см. пик №2), оно не установлено.

P.S.: А у нас ещё чат есть :3: https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
942343943574
#969 #942289
Привет аноны, кто нибудь подскажет как сделать админ панель с ip защитой? Возможно ли определить ip с помощью php и как это сделать?
942295
#970 #942295
>>942289

> Возможно ли определить ip с помощью php и как это сделать?


Ты бы хоть погуглить пару минут для приличия:
http://stackoverflow.com/questions/15699101/get-the-client-ip-address-using-php
942667
#971 #942343
>>942244

> А у нас ещё чат есть


А у меня телеграмма нет.
942391
#972 #942391
>>942343
Установи.
943574
#973 #942483
Скажите, если есть к примеру скрипт admin.php по адресу site.ru/admin, в нем есть переменная $n = 10. Если оттуда происходит переход к скрипту settings.php по адресу site.ru/admin/settings, то будет ли в скрипте settings.php видна переменная $n, как сделать, чтоб она была там видна.
942597942691
#974 #942597
>>942483

> Если оттуда происходит переход к скрипту settings.php


Переход это редирект? Если да - то переменная $n в том скрипте видна не будет, так как редирект - это новый HTTP-запрос, а PHP на каждый запрос заново инициализируется и умирает.

> как сделать, чтоб она была там видна.


- передавать как get-параметр: settings.php?n=10, либо хуже - писать $n в куки/сессию. В скрипте-получателе выковыривать.
943574
#975 #942667
>>942295
*погуглил
#976 #942691
>>942483
В admin.php делаешь file_put_contents('n', $n);
В settings.php делаешь $n = file_get_contents('n');
Получаешь переменную в обоих скриптах.
943574
#977 #942743
Внезапно столкнулся с проблемой с БД. Пишу себе бложик, никого не трогаю. Ну и в запись вставляю изображение. Тоесть идёт такое повествование, а потом раз, фотка и повествование продолжается. Причём фоток может бять от 0 до 100500. Соответственно выглядит оно как теги с ссылкой на фото <img src="img.jpg"> и вроде всё нормально, но последний Mysql начал адово глючить при виде любой кавычки в таблице. Как стоит поступать в таком случае?
942747942757942762
#978 #942747
>>942743

Скопируй сюда строку в которой делается запрос INSERT и пару соседних.
942760
#979 #942757
>>942743
Опытным путём выяснил что он ругается даже на <>
61 Кб, 443x249
#980 #942760
>>942747
А смысл?
Я Insert делаю через админ например. Ошибка нигде не проходит, сайт отображает всё отлично. Всё читается, работает и вообще всё отлично. Но вот PHPmyAdmin упорно говорит что я неправ при попытке отредактировать запись или при попытке отредактировать всё что после этой записи. Пикрил например.
.
942761942762943574
#981 #942761
>>942760
Ругается на запись <img src=img\1.jpg> если это важно
942762
#982 #942762
>>942761
>>942743
>>942760
Обтой. Это глюки самого майадмина.
942766
#983 #942766
>>942762
Короче, у кого новый оперсервер последней версии, можете смело на него накатывать Myadmin 4,6,6 и переносить конфиги. И будет вам счастье. Старый админ 4,5,7 глючит очень сильно.
8 Кб, 351x169
#984 #942789
Тут кто-то работает с Wordpress? начал изучать его пару дней назад и столкнулся с такой проблемой.
Писал на форум их, но ответа не получил. Без понятия, как решить это.
Суть проблема такова: хочу установить расширение для Unyson, а именно Конструктор страниц.
В треде JS, не помогли
942805942808942864
#985 #942805
>>942789
Заходишь в /web, там отдельный тред по WP.
#986 #942808
>>942789
Что конкретно тебе непонятно. По моему всё очевидно написано в описании ошибки. Не?
942850
560 Кб, 2322x1205
#987 #942850
>>942808
А как ее решить?я просто очень плохо разбираюсь в этом деле.
Не мог бы объяснить, пожалуйста ньюфагу. Спасибо.
942855943574
#988 #942855
>>942850
Освободи порт 1080 и попробуй снова.
942916
#989 #942864
>>942789
Там говорится о том, что при попытке подключиться на локальный порт 1080 твоего компьютера запрос на соединение отклоняется. Значит, то, что должно принять этот запрос, не работает. Что именно? Веб-сервер, может? Может, что-то ещё?
942868
#990 #942868
>>942864

Вообще, тут интересный случай. Порт 1080 используется для сервиса SOCKS (что-то вроде прокси для выхода в сеть через него). Не представляю, зачем расширению доступ к этгому порту.
#991 #942889
Опчик, а скажи.
Вот эти объектные паттерны, они применимы только к ПХП или они более абстарктны и их можно использовать в любом другом ОО языке, в котором ОО реализовано примерно как в ПХП?
943574
14 Кб, 1355x110
5 Кб, 347x117
#992 #942916
>>942855
А сейчас что не так?
942928942961943574
#993 #942928
>>942916
Лучше всего, конечно, глянуть в исходники и узнать, при каких условиях он вываливает ошибку.
942995
141 Кб, 1023x846
#994 #942961
>>942916
Слухай, а у тебя там URL правильный? Я нашел, вроде, файл, отвечающий за обновление. Если ошибку всё ещё не устранил, можно попробовать расставить там var_dump`ы и посмотреть на вывод.
942995943611943625
95 Кб, 1169x905
25 Кб, 400x225
#995 #942995
>>942928

> глянуть в исходники и узнать


Не понимаю о каком исходнике ты говоришь, ибо тупой:( Можешь название сказать этого исходника, если не затруднит.
>>942961
Я так понимаю эта папка отвечает за обнову, но какой файл ты имел ввиду?ведь там сотни их.
943044
#996 #943044
>>942995
Матерь Божья, у тебя Windows... Да уж...
Ладно, если для тебе сложно, проверь, правильно ли указан URL по которому происходит запрос на обновление.
943574943635
80 Кб, 999x610
#997 #943231
Товарищи. Решил освоить Laravel, написал простенький однопользовательский бложик, решил взяться за что-нибудь посерьезнее и накалякать имиджборду.

Примерно структура таблиц на пике. Так пойдет? Понимаю, что возможно не самая эффективная архитектура для борды, но 3НФ и с точки зрения моделей Eloquent правильно вроде.

Сейчас мне надо решить главные вопросы, как организовать номера постов, и порядок и смыв тредов. Если делать так как на пике, то порядковый номер треда будет храниться вместе с инфой о треде в колонке ordinal number. Соответственно при поднятии треда все остальные придется опускать и менять им ordinal_number. Можно вообще не хранить порядковые номера тредов, а например (если хранить в boolean сажу для поста) вычислять на ходу по последнему посту без сажи. По идее гораздо больше мороки, придется лопатить все посты и при чтении и при записи.
Та же история с номером последнего поста на доске. Можно хранить, можно вычислять.
Как кошернее будет? Впрочем любым советам рад буду.
943237943531
#998 #943237
>>943231
У постов и тредов Первичным Ключом id'шник, а не составной потому что Eloquent (местный ORM) составных ПК не понимает. У борд вместо id'шника можно сразу линк использовать, но так проще борды переименовывать.
#999 #943318
Поясните за обжект рилейшен мапинг. Хоть убей не могу понять в чем суть это хуиты и почему оно так важно. Это типа проецирование объектов-сущностей на БД и обратно? Может кто совсем простеньких примеров подкинуть?
943530
#1000 #943385
Анон, помоги разобраться. Разбираюсь сейчас с организацией файлов в проекте. И возник такой вопрос: каким образом ограничивается доступ ко всем директориям, кроме \web, если файл .htaccess сам хранится в директории \web и будет оказывать воздействия только на нее?
943413943530
#1001 #943413
>>943385
Можно через .htaccess, я же делал через настройки апача, или что у тебя там. Пишешь в конфиге
<VirtualHost :80>
# Имя сервера которое обслуживает этот VirtualHost
ServerName students.local
# Корневая папка сервера
DocumentRoot C:\OpenServer\domains\students.local\public
<Directory "C:\OpenServer\domains\students.local\public">
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.
)$ index.php [QSA]
AddDefaultCharset UTF-8
</Directory>
</VirtualHost>
В <directory> можешь скопипастить содержание .htaccess
И он уже считай тебе не нужен.
#1002 #943458
$pdoStatement->setFetchMode(\PDO::FETCH_CLASS, 'User');
Почему далее запрос возвращает массив? Поля совпадают (пробовал ставить public), все равно не работает
943469943530943569
#1003 #943469
>>943458
Он должен вернуть массив объектов я так понял.
#1004 #943530
>>943458

Покажи код, который идет дальше, где происходит получение данных.

>>943385

У веб-сервера есть такое понятие, как корневая директория (document root). Надо в конфиге сервера просто поставить корневой директорией нужную папку. Для Апача в конфиге надо найти нужный блок VirtualHost и внутри него поставить директиву

DocumentRoot "/var/www/example/public"

Там анон ниже привел пример конфига.

Если ты посмотришь документацию на DocumentRoot: https://httpd.apache.org/docs/2.4/mod/core.html#documentroot то там видно, где ее можно указывать:

Context: server config, virtual host

То есть в .htaccess нельзя, только в общем конфиге и в блоке VirtualHost.

>>943318

Это да, загрузка и запись в базу данных объектов. Если ты используешь ООП, то в твоем коде есть классы-сущности и надо как-то сохранять и загружать их из БД. Чтобы не писать все это с нуля и не мучаться, есть готовые библиотеки ORM вроде Доктрины. С нуля такое писать год можно, если не больше.

Вот тут в моем уроке это упомянуто: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Там конечно не все так просто, много подвохов, с производительностью могут быть проблемы, если тщательно не разобраться в используемой библиотеке.
#1004 #943530
>>943458

Покажи код, который идет дальше, где происходит получение данных.

>>943385

У веб-сервера есть такое понятие, как корневая директория (document root). Надо в конфиге сервера просто поставить корневой директорией нужную папку. Для Апача в конфиге надо найти нужный блок VirtualHost и внутри него поставить директиву

DocumentRoot "/var/www/example/public"

Там анон ниже привел пример конфига.

Если ты посмотришь документацию на DocumentRoot: https://httpd.apache.org/docs/2.4/mod/core.html#documentroot то там видно, где ее можно указывать:

Context: server config, virtual host

То есть в .htaccess нельзя, только в общем конфиге и в блоке VirtualHost.

>>943318

Это да, загрузка и запись в базу данных объектов. Если ты используешь ООП, то в твоем коде есть классы-сущности и надо как-то сохранять и загружать их из БД. Чтобы не писать все это с нуля и не мучаться, есть готовые библиотеки ORM вроде Доктрины. С нуля такое писать год можно, если не больше.

Вот тут в моем уроке это упомянуто: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Там конечно не все так просто, много подвохов, с производительностью могут быть проблемы, если тщательно не разобраться в используемой библиотеке.
943569944423
#1005 #943531
>>943231

Я советую проектироват базу так: сделать полностью нормализованное решение, а потом добавлять избыточные поля для оптимизации действий с таблицами.

Вообще, ordinal_number у треда это довольно неудачное решение. Это избыточная информация (так как порядковый номер треда можно вычислить через дату добавления последнего поста и наличие сажи). В принципе такие поля можно добавлять ради оптимизации выборки, например, но в твоем случае это довольно неудачное решение, так как при добавлении каждого поста нам надо обновлять все номера тредов, а базы не очень любят большое число операций записи. То есть от него вреда больше, чем пользы получается.

Я бы предложил добавить другое лишнее поле: дату обновления треда с учетом сажи (назовем ее bumpDate - момент последнего бампа треда). Если мы добавляем пост без сажи, и не достигли бамплимита, то мы обновляем bumpDate у треда. Соответственно, после этого мы можем сортировать посты по ORDER BY fixed DESC, bumpDate DESC (индекс по (fixed, bumpDate) отлично оптимизирует сортировку).

Конечно, номер хорош тем, что позволяет оптимизировать постраничную навигацию - мы можем сделать запрос WHERE number BETWEEN 10 AND 20 ORDER BY number, который идеально ложится на индекс. Без номера мы вынуждены использовтаь LIMIT, который не очень оптимально работает дальше N-й страницы (подробнее о недостатках LIMIT ниже).

Также, надо решить проблему вывода 3 последних постов треда. Для эффективной их выборки, скорее всего, надо добавлять дополнительные данные - например, таблицу связи между тредами и постами, или колонку, в которой через запятую хранятся id последних постов (тут правда не получится использовать внешние ключи).

Часть колонок у тебя я не понял. Зачем например колонка timestamps у треда и борды? Из названия понять ее назначение невозможно. Зачем last_post_nubmer у борды?

Зачем post_number у постов? Если тебе надо ставить номера при выводе, то может проще их считать в момент выовда? Хотя, вреда от него особого нет, так как номера не требуется пересчитывать при вставке поста, и получение номера последнего поста хрошо оптимизируется индексом.

Добавлю немного про LIMIT. Он используется повсеместно для пагинации, но у него есть недостатки:

- при очень большом OFFSET запросы получаются неэффективные
- в обновляющихся лентах, если ты идешь от 1-й страницы к последней, и добавляются новые посты, ты можешь натыкаться на уже просмотренные посты

Для борьбы с этими проблемами есть особая техника, когда мы используем вместо номера страницы значение поля, по которому сортируются записи, примерно так: /threads?page=4&bumpDate=2017-01-02T12:00:00. Подробнее от этом тут: http://use-the-index-luke.com/no-offset

Такой подход исплоьзуется например на reddit.

И еще, подозреваю, что выборка 500 объектов-постов через ORM будет работать не очень быстро. На таких объемах наверно выгоднее выбирать данные напрямую из БД.

Вообще, борда это довольно тяжелый (но интересный) случай с точки зрения оптимизации, так как тут при чтении треда идет выборка большого объема информации (500 постов - это может быть около 2 Мб текста), и ее трудно сделать быстрой. Мы должны прочитать из БД 2 Мб информации, засунуть ее в шаблон, отформатировать текст, отдать пользователю. Трафик, который может отдать база, он понятное дело, ограничен, и это может стать узким местом. И не только база, канал связи между пользователем и сервером - он тоже ограничен и конечно пересылать маленькие объемы данных было бы выгоднее.

С другой стороны, пользователь, получив тред, будет его долго читать, и может быть, не станет дальше беспокоить сервер запросами. А может он прочтет 2 поста и перейдет к другому треду.

Ну допустим у нас соединение с БД идет по 1 Гбит/с каналу. 2 мегабайта это 16 Мбит, значит мы в принципе не можем в такой ситуации в секунду отдать больше 60 больших тредов в секунду. Это в идеальном случае, если база способна генерировать данные с такой скоростью.

Я знаю, что некоторые борды хранят кеш HTML-кода треда, например в виде файла на диске. При чтении треда мы просто отдаем пользователю файл с диска, а при добавлении поста мы либо перегенерируем файл, либо как-то по-умному вставляем пост в конец треда (что может быть эффективнее). Но тут мы получаем другие проблемы:

- добавление одного поста может требовать перезапись огромного файла. Скорость записи на диск ограничена. То есть мы быстро вставляем 1 пост в базу и не спеша обновляем файл с кешем страницы, и это ограничивает скорость постинга. Более того, диски лучше всего принимают последовательную запись, а когда несколько потоков параллельно пишут треды - общая скорость проседает.
- перегенерация кеша треда требует блокировки. Так как если 2 потока одновременно будут перегенерировать один тред, может выйти что-то кривое.
- с другой стороны, отдача статических файлов - это то, с чем веб-сервера вроде nginx справляются отлично. То есть мы можем даже не дергать PHP приложение при запросе треда, плюс в линуксе есть разные оптимизации, которые позволяют например нгинксу отдавать файл в сеть, не читая его (ядро само этим займется).
- статический файл можно сжать gzip при записи, что снизит нагрузку на диск (так как данных будет меньше, текст хорошо жмется, раз в 5-10) и ускорит отдачу, снизит нагрузку на интернет-канал. С другой стороны, непонятно что тогда отдавать пользователям, не поддерживающим gzip? распаковывать для них файл на лету? Также, в сжатый тред нельзя вставить один новый пост, его можно только переписать целиком (или нет? я не эксперт по gzip).
- с третьей стороны, мы можем для кеша вместо реального диска использовать ram-диск (tmpfs в линукс). То есть хранить файлы в оперативной памяти, лучше наверно в сжатом виде. Запись в память идет с максимальной скоростью, и отдача файлов из памяти nginx будет очень эффективна. Мне кажется, что быстрее варианта, чем отдавать нгинксом файлы из памяти, в принципе нет.
- с четвертой стороны, кеш имеет те недостатки, что файл получается одинаков для всех пользователей. Представь, что мы хотим написать в углу "здравствуйте, Иван" или подсвечивать посты пользователя. Вся наша схема перестанет работать, так как HTML-код теперь разный для разных пользователей. Мы должны либо задейтствовать PHP, и возможно, базу, либо добавлять нужные данные яваскриптом в браузере. На этой борде используется подсветка через яваскрипт

То есть в итоге, я бы поэкспериментировал с кешированием тредов в tmpfs, может в сжатом виде, и посмотрел бы, можно ли при добавлении поста не перегенерировать тред целиком. Хотелось бы конечно иметь и сжатие, и добавление одного поста.

Некоторые борды также генерировали HTML-файлы для страниц со списком постов (главная, 2-я старница, 3-я и тд), но это по моему неэффективно, так как при каждом добавлении поста мы должны перегенерировать все файлы страниц. Это узкое место. Мне кажется, что страницы выгоднее генерировать на лету. Единственное, что тут можно оптимизировать - можно сделать HTML-кеш в памяти для треда (ОП-пост + 3 последних поста + HTML-обвязка). То есть из базы выбираем id тредов на текущей странице, затем из кеша берем их представление и отдаем пользователю. При обновлении треда либо дропаем кеш, либо обновляем.

Зато тут есть возможности для распараллеливания:

- разные борды никак не связаны друг с другом, и мы можем помещать их на отдельные сервера. Причем в базу друг к другу они не лезут и каждый может использовать свою БД
- отдача тредов из tmpfs не параллелится на несколько серверов
- отдача списков тредов методом база + кеш параллелится

Вообще, тут конечно мало рассуждать теоретически, надо брать сервер и делать эксерименты, измерения.

Если хочешь, можешь тоже над этим подумать. Можешь кстати потом померять свою борду.

И еще, вдруг пригодится, у меня есть готовая верстка для борды: https://github.com/codedokode/board-markup
#1005 #943531
>>943231

Я советую проектироват базу так: сделать полностью нормализованное решение, а потом добавлять избыточные поля для оптимизации действий с таблицами.

Вообще, ordinal_number у треда это довольно неудачное решение. Это избыточная информация (так как порядковый номер треда можно вычислить через дату добавления последнего поста и наличие сажи). В принципе такие поля можно добавлять ради оптимизации выборки, например, но в твоем случае это довольно неудачное решение, так как при добавлении каждого поста нам надо обновлять все номера тредов, а базы не очень любят большое число операций записи. То есть от него вреда больше, чем пользы получается.

Я бы предложил добавить другое лишнее поле: дату обновления треда с учетом сажи (назовем ее bumpDate - момент последнего бампа треда). Если мы добавляем пост без сажи, и не достигли бамплимита, то мы обновляем bumpDate у треда. Соответственно, после этого мы можем сортировать посты по ORDER BY fixed DESC, bumpDate DESC (индекс по (fixed, bumpDate) отлично оптимизирует сортировку).

Конечно, номер хорош тем, что позволяет оптимизировать постраничную навигацию - мы можем сделать запрос WHERE number BETWEEN 10 AND 20 ORDER BY number, который идеально ложится на индекс. Без номера мы вынуждены использовтаь LIMIT, который не очень оптимально работает дальше N-й страницы (подробнее о недостатках LIMIT ниже).

Также, надо решить проблему вывода 3 последних постов треда. Для эффективной их выборки, скорее всего, надо добавлять дополнительные данные - например, таблицу связи между тредами и постами, или колонку, в которой через запятую хранятся id последних постов (тут правда не получится использовать внешние ключи).

Часть колонок у тебя я не понял. Зачем например колонка timestamps у треда и борды? Из названия понять ее назначение невозможно. Зачем last_post_nubmer у борды?

Зачем post_number у постов? Если тебе надо ставить номера при выводе, то может проще их считать в момент выовда? Хотя, вреда от него особого нет, так как номера не требуется пересчитывать при вставке поста, и получение номера последнего поста хрошо оптимизируется индексом.

Добавлю немного про LIMIT. Он используется повсеместно для пагинации, но у него есть недостатки:

- при очень большом OFFSET запросы получаются неэффективные
- в обновляющихся лентах, если ты идешь от 1-й страницы к последней, и добавляются новые посты, ты можешь натыкаться на уже просмотренные посты

Для борьбы с этими проблемами есть особая техника, когда мы используем вместо номера страницы значение поля, по которому сортируются записи, примерно так: /threads?page=4&bumpDate=2017-01-02T12:00:00. Подробнее от этом тут: http://use-the-index-luke.com/no-offset

Такой подход исплоьзуется например на reddit.

И еще, подозреваю, что выборка 500 объектов-постов через ORM будет работать не очень быстро. На таких объемах наверно выгоднее выбирать данные напрямую из БД.

Вообще, борда это довольно тяжелый (но интересный) случай с точки зрения оптимизации, так как тут при чтении треда идет выборка большого объема информации (500 постов - это может быть около 2 Мб текста), и ее трудно сделать быстрой. Мы должны прочитать из БД 2 Мб информации, засунуть ее в шаблон, отформатировать текст, отдать пользователю. Трафик, который может отдать база, он понятное дело, ограничен, и это может стать узким местом. И не только база, канал связи между пользователем и сервером - он тоже ограничен и конечно пересылать маленькие объемы данных было бы выгоднее.

С другой стороны, пользователь, получив тред, будет его долго читать, и может быть, не станет дальше беспокоить сервер запросами. А может он прочтет 2 поста и перейдет к другому треду.

Ну допустим у нас соединение с БД идет по 1 Гбит/с каналу. 2 мегабайта это 16 Мбит, значит мы в принципе не можем в такой ситуации в секунду отдать больше 60 больших тредов в секунду. Это в идеальном случае, если база способна генерировать данные с такой скоростью.

Я знаю, что некоторые борды хранят кеш HTML-кода треда, например в виде файла на диске. При чтении треда мы просто отдаем пользователю файл с диска, а при добавлении поста мы либо перегенерируем файл, либо как-то по-умному вставляем пост в конец треда (что может быть эффективнее). Но тут мы получаем другие проблемы:

- добавление одного поста может требовать перезапись огромного файла. Скорость записи на диск ограничена. То есть мы быстро вставляем 1 пост в базу и не спеша обновляем файл с кешем страницы, и это ограничивает скорость постинга. Более того, диски лучше всего принимают последовательную запись, а когда несколько потоков параллельно пишут треды - общая скорость проседает.
- перегенерация кеша треда требует блокировки. Так как если 2 потока одновременно будут перегенерировать один тред, может выйти что-то кривое.
- с другой стороны, отдача статических файлов - это то, с чем веб-сервера вроде nginx справляются отлично. То есть мы можем даже не дергать PHP приложение при запросе треда, плюс в линуксе есть разные оптимизации, которые позволяют например нгинксу отдавать файл в сеть, не читая его (ядро само этим займется).
- статический файл можно сжать gzip при записи, что снизит нагрузку на диск (так как данных будет меньше, текст хорошо жмется, раз в 5-10) и ускорит отдачу, снизит нагрузку на интернет-канал. С другой стороны, непонятно что тогда отдавать пользователям, не поддерживающим gzip? распаковывать для них файл на лету? Также, в сжатый тред нельзя вставить один новый пост, его можно только переписать целиком (или нет? я не эксперт по gzip).
- с третьей стороны, мы можем для кеша вместо реального диска использовать ram-диск (tmpfs в линукс). То есть хранить файлы в оперативной памяти, лучше наверно в сжатом виде. Запись в память идет с максимальной скоростью, и отдача файлов из памяти nginx будет очень эффективна. Мне кажется, что быстрее варианта, чем отдавать нгинксом файлы из памяти, в принципе нет.
- с четвертой стороны, кеш имеет те недостатки, что файл получается одинаков для всех пользователей. Представь, что мы хотим написать в углу "здравствуйте, Иван" или подсвечивать посты пользователя. Вся наша схема перестанет работать, так как HTML-код теперь разный для разных пользователей. Мы должны либо задейтствовать PHP, и возможно, базу, либо добавлять нужные данные яваскриптом в браузере. На этой борде используется подсветка через яваскрипт

То есть в итоге, я бы поэкспериментировал с кешированием тредов в tmpfs, может в сжатом виде, и посмотрел бы, можно ли при добавлении поста не перегенерировать тред целиком. Хотелось бы конечно иметь и сжатие, и добавление одного поста.

Некоторые борды также генерировали HTML-файлы для страниц со списком постов (главная, 2-я старница, 3-я и тд), но это по моему неэффективно, так как при каждом добавлении поста мы должны перегенерировать все файлы страниц. Это узкое место. Мне кажется, что страницы выгоднее генерировать на лету. Единственное, что тут можно оптимизировать - можно сделать HTML-кеш в памяти для треда (ОП-пост + 3 последних поста + HTML-обвязка). То есть из базы выбираем id тредов на текущей странице, затем из кеша берем их представление и отдаем пользователю. При обновлении треда либо дропаем кеш, либо обновляем.

Зато тут есть возможности для распараллеливания:

- разные борды никак не связаны друг с другом, и мы можем помещать их на отдельные сервера. Причем в базу друг к другу они не лезут и каждый может использовать свою БД
- отдача тредов из tmpfs не параллелится на несколько серверов
- отдача списков тредов методом база + кеш параллелится

Вообще, тут конечно мало рассуждать теоретически, надо брать сервер и делать эксерименты, измерения.

Если хочешь, можешь тоже над этим подумать. Можешь кстати потом померять свою борду.

И еще, вдруг пригодится, у меня есть готовая верстка для борды: https://github.com/codedokode/board-markup
#1006 #943569
>>943458
>>943530

public function getUserByEmail ($email) {
$pdoStatement = $this->pdo->prepare("SELECT * FROM users WHERE `email` = :email;");
$pdoStatement->bindValue(":email", $email);
$pdoStatement->execute();
$pdoStatement->setFetchMode(\PDO::FETCH_CLASS, 'User');
$user = $pdoStatement->fetch();
// var_dump($user);
return $user;
}

И еще насчет авторизации: сделал, что, авторизовавшись, пользователь получает код в куки, и он же (код) идет в БД.
И в суперкласс Контроллеров добавил свойство Юзер и метод, который по коду в куках возвращает Юзера; метод вызывается в констукторе, но это как-то криво, так как пришлось для Маппера и класса Авторазации добавить поля в супер класс Контроллера, но этого, навеное, можно избежать: лишние зависимости. Что еще можно придумать?
943581
#1007 #943574
>>943044

В чем проблема с виндоуз? PHP кроссплатформенн.

>>942916

Погугли HTTP код 400: это значит Bad Request. То есть гитхабу что-то не нравится.

Для диагностики надо посмотреть, какой запрос отправляет скрипт, правильный ли он, и отправить его вручную и посмотретьт ответ - может там есть намек.

А может конечно гитхаб просто не рад тому, что его пытаются использовать в качестве сервера обновлений. Трафик не бесплатный все таки.

>>942889

В любом языке. ООП в разных языках использует одни и те же принципы, и тщательно выучив ООП в PHP, решив мои задачки по ООП, а также задачу про скидки, ты сможешь легко разобрться с ООП кодом на других языках.

>>942850

Обратиться за поддержкой к разработчикам темы. Либо разобраться, что там происходит и почему ошибка.

>>942760

Да, запрос получился странный.

>>942691

Ты не учел что с сайтом может работать несколько пользователей и у каждого могут быть свои данные. Лучше передавать через GET/POST. сессии/куки имеют тот недостаток, что они общие для всех вкладок в браузере, а URL в каждой вкладке свои.

>>942597

Надо учесть что куки и сессии общие для всех вкладок браузера.

>>942391

Мне кстати не нравится телеграм тем, что надо сдать свою персональную информацию Дурову. Никакой надобности, кроме желания следить за пользователями, в этом нет. Он и вконтакте собирал все, что можно, и тут собирает. Уверен, у него где-нибудь есть бекап базы ВК.

>>942244

Неработающий mstring на ideone - скорее всего результат обновления на PHP7.

>>942059

У тебя в коде ошибка, там лишняя ошибочная строчка есть.
#1007 #943574
>>943044

В чем проблема с виндоуз? PHP кроссплатформенн.

>>942916

Погугли HTTP код 400: это значит Bad Request. То есть гитхабу что-то не нравится.

Для диагностики надо посмотреть, какой запрос отправляет скрипт, правильный ли он, и отправить его вручную и посмотретьт ответ - может там есть намек.

А может конечно гитхаб просто не рад тому, что его пытаются использовать в качестве сервера обновлений. Трафик не бесплатный все таки.

>>942889

В любом языке. ООП в разных языках использует одни и те же принципы, и тщательно выучив ООП в PHP, решив мои задачки по ООП, а также задачу про скидки, ты сможешь легко разобрться с ООП кодом на других языках.

>>942850

Обратиться за поддержкой к разработчикам темы. Либо разобраться, что там происходит и почему ошибка.

>>942760

Да, запрос получился странный.

>>942691

Ты не учел что с сайтом может работать несколько пользователей и у каждого могут быть свои данные. Лучше передавать через GET/POST. сессии/куки имеют тот недостаток, что они общие для всех вкладок в браузере, а URL в каждой вкладке свои.

>>942597

Надо учесть что куки и сессии общие для всех вкладок браузера.

>>942391

Мне кстати не нравится телеграм тем, что надо сдать свою персональную информацию Дурову. Никакой надобности, кроме желания следить за пользователями, в этом нет. Он и вконтакте собирал все, что можно, и тут собирает. Уверен, у него где-нибудь есть бекап базы ВК.

>>942244

Неработающий mstring на ideone - скорее всего результат обновления на PHP7.

>>942059

У тебя в коде ошибка, там лишняя ошибочная строчка есть.
#1008 #943575
>>941811

> http://ideone.com/9wsu8g - Игра в кубики;


Все верно.

> http://ideone.com/sRvu3e - мини "калькулятор";


Там внизу ошибка: ты забыл поставить скобки после error_reporting(-1);

В остальном все верно.

> http://ideone.com/8x1TeV - Игра в кубики с Пекой;


Тут вместо кучи exit лучше было сделать большой блок if/esleif/elseif/else. В таком блоке может выполниться только одно из условий и exit не нужен.

> http://ideone.com/pJ4TO8 - Пхп без смс;


Верно.

> http://ideone.com/8GN4S3 - депозит;


Нет скобок после error_reporting, также в задаче требовалось ответить, когда накопится миллион на счету. Видимо ты не очень внимательно прочел условие.

> http://ideone.com/O7tPEA - Айфон в кредит;


Верно.

> http://ideone.com/7SJzev - Задание со стихами;


Верно, хотя там какой-то отступ добавился у 2-й и 3-й строки.

> http://ideone.com/MGrQkg - Регулярка на номера телефонов



> (\\s|\\-|\\(|\\)


Тут наверно было бы удобнее использовать квадратные скобки, тем более что внутри них круглые скобки можно писать без бекслешей.

А так, решено правильно.
#1008 #943575
>>941811

> http://ideone.com/9wsu8g - Игра в кубики;


Все верно.

> http://ideone.com/sRvu3e - мини "калькулятор";


Там внизу ошибка: ты забыл поставить скобки после error_reporting(-1);

В остальном все верно.

> http://ideone.com/8x1TeV - Игра в кубики с Пекой;


Тут вместо кучи exit лучше было сделать большой блок if/esleif/elseif/else. В таком блоке может выполниться только одно из условий и exit не нужен.

> http://ideone.com/pJ4TO8 - Пхп без смс;


Верно.

> http://ideone.com/8GN4S3 - депозит;


Нет скобок после error_reporting, также в задаче требовалось ответить, когда накопится миллион на счету. Видимо ты не очень внимательно прочел условие.

> http://ideone.com/O7tPEA - Айфон в кредит;


Верно.

> http://ideone.com/7SJzev - Задание со стихами;


Верно, хотя там какой-то отступ добавился у 2-й и 3-й строки.

> http://ideone.com/MGrQkg - Регулярка на номера телефонов



> (\\s|\\-|\\(|\\)


Тут наверно было бы удобнее использовать квадратные скобки, тем более что внутри них круглые скобки можно писать без бекслешей.

А так, решено правильно.
#1009 #943581
>>943569

Попробуй поставить setFetchMode перед execute. Если это поможет, проверь что при перестановке обратно проблема вернулась, и напиши тут об этом. Я хочу в этом случае написать разработчикам PHP, чтобы они либо добавили предупреждение в код при неправильном использовании функции, либо хотя бы задокументировали это. Давайте поможем сделать PHP лучше.

> И в суперкласс Контроллеров добавил свойство Юзер и метод, который по коду в куках возвращает Юзера;



Вообще, это, мне кажется, неправильно. На каком основании ты решил этот код внедрить во все контроллеры? Не логичнее ли сделать отдельный класс, отвечающий за авторизацию?

Вот это плохая идея, сегодня ты добавил авторизацию, завтра еще что-нибудь и у тебя базовый контроллер превратится в god object.

Что касается зависимостей, в Симфони например контроллер получает DI контейнер (через метод setContainer) и может сам брать из него что нужно. Хотя никто не запрещает использовать DI и передавать зависимости контроллеру в конструктор.

Док-я англ:

- http://api.symfony.com/3.0/Symfony/Component/DependencyInjection/ContainerAwareInterface.html
-
943640944003
#1010 #943611
>>942961
Подскажи, пожалуйста, название шрифта на пике.
943614
119 Кб, 1010x983
#1011 #943614
#1012 #943625
>>942961

И название темы тоже подскажи... Другой анон.
943788
14 Кб, 546x172
#1013 #943635
>>943044
Я сдаюсь, слишком мало скиллов, чтоб понять что от меня хотят.
Пошел Drupal пытаться осваивать, может там повезет больше, спасибо за ответы :p
#1014 #943640
>>943581
Ой, чот тред утонул
1326 Кб, 1641x764
#1015 #943646
Посоветуйте сайт или паблик вк, где можно узнавать всякие новости о программировании(можно и зарубежный источник)
943661
#1016 #943661
>>943646

Я читаю:

Русские: habr, geektimes
Западный: news.ycombinator.com

Еще есть украинский dou.ua, но там многовато нытья про зарплаты, про вам перезвонят, малолетних сеньоров итд.
#1017 #943696
Какая замечательная система линукс. Обожаю когда ничего не работает. Даже не хочется писать что не получается.

Поставил апач, пхп. Пытаюсь создать "Hello World", сохраняю в дефолтную папку var/www/html - "Нет доступа". КАЕФ.

Решил поступить другим путем: поменять директорию. Открываю etc/apache2/apache2.conf, пытаюсь изменить <Directory /var/www/> Хм, странно. Индексная странница находиться в /var/www/html/, а прописано что в www Ха, нельзя сохранить - нет доступа.

Гуглю как получить доступ, затем пишу в терминале хаахаххахаха в терминале редактирую файл))00000))) sudoedit... Ничего не сработало, корневая директория по прежнему осталась стандартной.

Гуглю дальше, пишут что нужно поменять ещё в etc/apache2/sites-enabled/000-default.conf Очень странно.
Пытаюсь его отредактировать выдается ошибка:
sudoedit: etc/apache2/sites-enabled/000-default.conf: editing symbolic links is not permitted

В гугле не очень нашлось по этому. Попробовал написать иначе sudo nano... Хах, редактор открылся, причем тот же самый что и при sudoedit. Но ничего не поменялось.

Использовал вот эти гайды:
http://www.tecmint.com/change-root-directory-of-apache-web-server/
https://www.digitalocean.com/community/tutorials/how-to-move-an-apache-web-root-to-a-new-location-on-ubuntu-16-04 У меня в файле sites-enabled/000-default.conf нету даже строки с <Directory /var/www/html/>, она есть в apache2.conf

Так как поменять корневую директорию?) У меня стоит свежая версия убунту.

Ой всё, даже жить не хочется что такие проблемы возникают. Что я не так сделал бля?

Извиняюсь за кривой почерк, я просто ничего не понимаю как так может быть.
943711943815
#1018 #943711
>>943696
1) Убунта кусок говна. Ставь федорку
2) Если поменяешь бубунту на норм дистр, то сможешь использовать su и su - c " " вместо sudo
3) В sites-enabled лежат симлинки на конфиги из sites-available, правь их там
943713943719
#1019 #943713
>>943711
Чтобы сохранять нормально в папку дай себе на нее права таки.
chown -R user:group /path/to/folder (рекурсивно сменить владельца)
chmod -R 777 /path/to/folder (рекурсивно выставить максимальные права доступа для всех на все что лежит в папке)
943715
#1020 #943715
>>943713
А вообще правильнее так будет:
1) владельцем ставишь себя
2) группой владельца группу под которой запущен апач
3) себе ставишь полный доступ
4) остальным можешь вооще закрыть
6) группе апача чтение на все и запись на папку куда загружаешь файлы (uploads какой-нибудь)

Вроде так будет прально. Могу ошибаться впрочем.
943721
#1021 #943719
>>943711

> Убунта кусок говна. Ставь федорку


Это много говорит о твоем уровне компетентности. Ты пост-то читал?
943723
#1022 #943721
>>943715

Костыли. Как организовать работу (права) над сайтом, если надо дать доступ нескольким пользователям + запускать cli программы? И гарантировать, что из-за дефолтного umask 022 например не получатся защищенные от записи файлы и каталоги?

В гайде Симфони рекомендуют использовать ACL, так как стандартные юниксовые права там плохо работают.
#1023 #943723
>>943719
Пост читал, следущие два ответа тоже мои.
Убунта реально глючный кусок говна. Fedora тоже не сахар, как-никак тестовый полигон красношапки, но бубунта умудряется быть даже более глючный чем тестовый полигон. К тому же дистр, который за меня решает можно ли мне логиниться под рутом или нельзя ненужон и место его в мусорном ведре.
И не костыли, а стандартная рабочая схема. Права на создаваемые файлы тоже редактируются если правильно помню.
Нескольким пользователям с такой моделью доступа никак.
#1024 #943765
Еще один вопрос по Laravel'у, хотя скорее по самой MVC

Как будет правильнее? Вопрос всего касается, но на примере вывода списка тредов.

1)
тонкая модель с только Eloquent'овскими отношениями
тонкий контроллер, который берет все треды для доски и передает их во вьху

$board = \App\Board::where('link', $board_link)->firstOrFail();

$threads = $board->threads()->get();

return view('threads.index', ['threads' => $threads]);

И во вьюхе уже по отношению, мы вытаскиваем
$thread->posts()->where('op_post', true)->first()->topic

2) моделька пожирнее, где мы скажем довляем функцию op_post, а во вьюхе пользуем просто
$thread->op_post()->topic

3) В контроллере или модели собрать структуру данных не являющуюся отражением модели, но хранящую всю нужную информацию для построения вьюхи и передавать вьюхе уже ее, чтобы она сама БД не дергала
11465 Кб, Webm
#1026 #943815
#1027 #943885
Представляете, а у меня все работает на убунте, после того как я заново запустил виртуальную машину. Я клянусь, я делал рестарт апача apache2 -k restart

А ещё и кусок кода начал работать после перезагрузки.

Всем спасибо за помощь. Все советы были полезными.
#1028 #943915
Аноны, RewriteCond %{REQUEST_FILENAME} !-f исключает из редиректа не только статические файлы, но .php. В итоге есть доступ ко всему. Из-за чего такое может быть?
943931
#1029 #943931
>>943915
Эм.. а ты как хотел? Почему пхп файлы должны были убираться из редиректа по твоему?
943934
#1030 #943934
>>943931
Я в этом новичок, думал -f уберет все статические файлы, а .php оставит. Конструкция !\.(css|js) работает как надо. Но тогда непонятно зачем -f и -d во все гайды добавляют. Разве из-за этого не может возникнуть дыра в безопасноти?
#1031 #943973
Если я получил на сайте, путем щалости с параметрами sql код - это значит что я теоретически могу юзать инъекции?
943974943979
#1032 #943974
>>943973
Твою мамку я в зад могу юзать.
943977
28 Кб, 967x175
#1033 #943977
>>943974
Вот такое гавно на сайте в компании, где кореш работает
#1034 #943979
>>943973
Что за код, как получил? Вполне вероятно, что да, если переписать можешь. Но таки подробности нужны.
943986
#1035 #943986
>>943979
http://url.ru/uslugi.php?id=1
Не хочу все-таки палить ребят, а то налетят опытные ребята

если вместо 1, написать 2, то 404. Если 1+1, то страница ошибки, если 2-1, то 404. То есть обработка есть.
Если от 8 до 22, то будут выводиться услуги
#1036 #944003
>>943581

>Попробуй поставить setFetchMode перед execute.


Не вышло, попробую сегодня студентов начать делать, может, увижу косяк, когда на ясную голову.

>Вообще, это, мне кажется, неправильно. На каком основании ты решил этот код внедрить во все контроллеры? Не логичнее ли сделать отдельный класс, отвечающий за авторизацию?


Я понимаю, что это неправильно, и класс у меня для авторизации есть, только так как вызывать мне нужно было его каждый раз при переходе на страницы, то я и сделал создание объекта класса Авторизация и его вызов в конструкторе Контроллера, чтобы всегда проверялось, авторизован ли пользователь.

>Что касается зависимостей, в Симфони например контроллер получает DI контейнер.


А разве это не становится тем самым ServiceLocator, то есть лишней зависимостью, от которой должен по идее избавлять DI Container?
Я так понимаю в файле инициализации создается DI Container (например, Pimple), которому задаются все схемы зависимостей (функции), а далее с ним как в идеале? Или констуктору нужного Контроллеру передавать или глобальный объект, что плохо? Просто опять-таки не вижу разницы между ServiceLocator, кроме удобного интерфейса, который и не относится к самой идее DI Container. Думаю, у меня в этом вопросе некоторое недопонимание.
И еще несколько вопросов:
Как эффективнее назначать класс active текущей странице из навигационного меню.
Можно в контроллере иметь поле name, а в шаблоне шапки сайта константы (можно ли такое в шаблоне хранить?), в самом меню условие:
<li <?=($name==HOME)?'class="active"':''?>><a href="/">Главная</a></li>
<li <?=($name==GOODS)?'class="active"':''?>><a href="/goods">Товары</a></li>
944008944114944595
#1037 #944008
>>944003
...И передавать аргументом свойство name при рендере шаблона

>Контроллеру


Контроллера*
#1038 #944064
Оьясните, зачем в preg_match требуется добавлять в начало и конец строки дополнительные символы?
944595
#1039 #944114
>>944003
Когда-то тоже задавал вопрос по поводу внедрения DI-контейнера прямо в контроллер.
Да, это именно сервис-локатор, так как зависимости контроллера скрываются, непонятно что нужно класть в контейнер, чтобы контроллер работал. В Symfony/Slim есть такое понятие как controller-as-a-service: https://symfony.com/doc/current/controller/service.html
То есть в контейнер кладётся контроллер и в качестве его зависимостей указываются нужные сервисы. В Slim можно писать как-то так:
$container['UserController'] = function ($container) {
____return new \UserController($container->get('renderer'));
};
Тогда контроллер будет иметь прозрачные зависимости. Но в этом не очень много смысла так как хороший тонкий контроллер юнит-тестировать не нужно: он выступает лишь прослойкой между HTTP и моделью. Если возникает желание юнит-тестировать контроллер, то он скорее всего содержит что-то лишнее.
944595
#1040 #944228

>имеет высокий уровень пользования ПК


Что они имеют ввиду "высокий уровень пользования пк", что я должен уметь и знать?
944546944547
#1041 #944423
>>943530

>Вот тут в моем уроке это упомянуто: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md


Спасибо. И вопрос конечно же платиновый наверняка, но я чет не понял чем TDG от дата маппера отличается.
944598
#1042 #944431
Статья про промисы с картинками: https://m.habrahabr.ru/company/nixsolutions/blog/323066/

Вот кстати, эта схема с кучей вложенных коллбеков действительно сложная. В PHP, в React promise сделано интереснее: там есть 2 объекта: Deferred и Promise. И Deferred как раз используется для разрешения или отклонения промиса.

Для тех, кто не в курсе, промисы - это абстракция для асинхронных операций, то есть операций, которые выполняются в фоне в течение какого-то времени. Например, скачивание файла. Функция скачивания файла запускает процесс и возвращает промис, не дожидаясь его окончания. Когда файл скачается, промис разрешится в его содержимое, или в исключение, если произойдет ошибка. Получатель промиса может подписаться на событие, и указанная функция будет вызвана, когда результат будет готов.

Вот как это выглядит в PHP:

$deferred = new Deferred; // объект, управляющий промисом
$promise = $deferred->promise(); // получаем промис
return $promise;
.....

// когда операция завершится, мы задаем ее результат через deferred
$deferred->resolve($result);

По моему, намного нагляднее чем схема с кучей коллбеков в JS.
944562
#1043 #944546
>>944228

Понятия не умею, но могу предположить. Программы устанавливать уметь например, удалять, перемещать и копировать файлы, убивать зависшие программы, обновлять драйвера, не пугаться панели управления Windows. В общем-то то, что наверно сегодня каждый школьник умеет так как без этого в ГТА не поиграть.
944549
#1044 #944547
>>944228

И почему бы тебе этот вопрос не задать авторам вакансии?
#1045 #944549
>>944546

> Программы устанавливать


Скорее понимать почему их не надо устанавливать, лол.
#1046 #944562
>>944431
Кек, только что прочитал и хотел запостить сюда. А ты няша :3
По поводу наглядности: в JS уже если привычно работать то не задумываешься над сложностью конструкций, тем более фреймворки предоставляют свою встроенную реализацию промисов, есть библиотеки опять же (Q)...
944598
#1047 #944578
https://ideone.com/InOBOk
Есть такой вот метод с подстановкой данных через плесйхолдеры. Данные передаются хорошо, однако вот такая ошибка в итоге
0SELECT name, second_name, group_number, summary FROM students ORDER BY :sort LIMIT :start, :limit
Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '5'' at line 5 in C:\OpenServer\domains\students.local\app\Models\StudentsGateaway.php:78 Stack trace: #0 C:\OpenServer\domains\students.local\app\Models\StudentsGateaway.php(78): PDOStatement->execute() #1 C:\OpenServer\domains\students.local\app\Controllers\FrontController.php(42): models\StudentsGateaway->getAll('name', 0, 5) #2 C:\OpenServer\domains\students.local\app\Controllers\FrontController.php(27): Controllers\FrontController->actionIndex() #3 C:\OpenServer\domains\students.local\public\index.php(4): Controllers\FrontController->route() #4 {main} thrown in C:\OpenServer\domains\students.local\app\Models\StudentsGateaway.php on line 78
ЧЯДНТ? Данные передаются правильно, если просто вставить без всяких бинд велью - работает.
944610944617
#1048 #944595
>>944003

> Я понимаю, что это неправильно, и класс у меня для авторизации есть, только так как вызывать мне нужно было его каждый раз при переходе на страницы, то я и сделал создание объекта класса Авторизация и его вызов в конструкторе Контроллера, чтобы всегда проверялось, авторизован ли пользователь.


Это не то что бы неправильно, недостаток использования конструктора в том, что этот код вообще всегда будет вызываться, даже если мы не будем выводить шапку с информацией о пользователе.

Может стоит в конструкторе сохранять ссылку на сервис авторизации, а также сделать функцию, собирающую данные для шапки, если там будет не только авторизация. Но если у тебя там только проверка авторизации, можно конечно и в конструкторе ее оставить.

Вопрос про контролллеры и ServiceLocator

Тут есть 2 подхода. Первый: контроллер - это сервис, надо использовать DI, класть его в контейнер. Все красиво и логично, но требует лишней писанины. Второй: контроллер - это не совсем сервис, это скорее стартовая точка приложения и проще использовать тут паттерн ServiceLocator.

Главная проблема ServiceLocator это то, что класс становится зависимым от контейнера со всем его содержимым. Мы не можем этот класс в другой проект перенести или оформить как независимую библиотеку. И мы не можем поменять контейнер, не трогая класс. Ну и некрасиво, что зависимости неточно указаны.

Но контроллер это не повторно используемый код. Он намертво привязан к конкретному проекту и значит, ничего плохого в том, что он знает о контейнере и использует его, нет.

Выбирай сам, какой вариант тебе лучше подходит.

> Просто опять-таки не вижу разницы между ServiceLocator, кроме удобного интерфейса, который и не относится к самой идее DI Container


Никто не запрещает в DI контейнере тоже сделать такой интерфейс, я думаю.

> Можно в контроллере иметь поле name, а в шаблоне шапки сайта константы (можно ли такое в шаблоне хранить?), в самом меню условие:


В шаблоне точно константы объявлять непраивльно. Сделай какой-нибудь класс с вспомогательными функциями и в нем объяви лучше. Либо можно использовать встроенную константу SomeController::class (или CLASS), содержащую имя класса. Вообще, не надо делать константы, соответствующие классам, так как такие константы уже есть.

Вместо поля с именем контроллера лучше просто передавать в шаблон переменную с названием текущего пункта меню.

>>944064

Это ограничители. Они нужны, чтобы отделить шаблон регулярного выражения от флагов, которые идут в конце.

/выражение/флаги
!выражение!флаги

>>944114

Выше написал мнение.

> Но в этом не очень много смысла так как хороший тонкий контроллер юнит-тестировать не нужно: он выступает лишь прослойкой между HTTP и моделью.



Это непрактично и сложно, так как контроллер вызывает кучу других методов и мы можем лишь протестировать его работу в сочетании с другими классами. Ну и да, логики как правило там минимум и тестировать особо нечего.
#1048 #944595
>>944003

> Я понимаю, что это неправильно, и класс у меня для авторизации есть, только так как вызывать мне нужно было его каждый раз при переходе на страницы, то я и сделал создание объекта класса Авторизация и его вызов в конструкторе Контроллера, чтобы всегда проверялось, авторизован ли пользователь.


Это не то что бы неправильно, недостаток использования конструктора в том, что этот код вообще всегда будет вызываться, даже если мы не будем выводить шапку с информацией о пользователе.

Может стоит в конструкторе сохранять ссылку на сервис авторизации, а также сделать функцию, собирающую данные для шапки, если там будет не только авторизация. Но если у тебя там только проверка авторизации, можно конечно и в конструкторе ее оставить.

Вопрос про контролллеры и ServiceLocator

Тут есть 2 подхода. Первый: контроллер - это сервис, надо использовать DI, класть его в контейнер. Все красиво и логично, но требует лишней писанины. Второй: контроллер - это не совсем сервис, это скорее стартовая точка приложения и проще использовать тут паттерн ServiceLocator.

Главная проблема ServiceLocator это то, что класс становится зависимым от контейнера со всем его содержимым. Мы не можем этот класс в другой проект перенести или оформить как независимую библиотеку. И мы не можем поменять контейнер, не трогая класс. Ну и некрасиво, что зависимости неточно указаны.

Но контроллер это не повторно используемый код. Он намертво привязан к конкретному проекту и значит, ничего плохого в том, что он знает о контейнере и использует его, нет.

Выбирай сам, какой вариант тебе лучше подходит.

> Просто опять-таки не вижу разницы между ServiceLocator, кроме удобного интерфейса, который и не относится к самой идее DI Container


Никто не запрещает в DI контейнере тоже сделать такой интерфейс, я думаю.

> Можно в контроллере иметь поле name, а в шаблоне шапки сайта константы (можно ли такое в шаблоне хранить?), в самом меню условие:


В шаблоне точно константы объявлять непраивльно. Сделай какой-нибудь класс с вспомогательными функциями и в нем объяви лучше. Либо можно использовать встроенную константу SomeController::class (или CLASS), содержащую имя класса. Вообще, не надо делать константы, соответствующие классам, так как такие константы уже есть.

Вместо поля с именем контроллера лучше просто передавать в шаблон переменную с названием текущего пункта меню.

>>944064

Это ограничители. Они нужны, чтобы отделить шаблон регулярного выражения от флагов, которые идут в конце.

/выражение/флаги
!выражение!флаги

>>944114

Выше написал мнение.

> Но в этом не очень много смысла так как хороший тонкий контроллер юнит-тестировать не нужно: он выступает лишь прослойкой между HTTP и моделью.



Это непрактично и сложно, так как контроллер вызывает кучу других методов и мы можем лишь протестировать его работу в сочетании с другими классами. Ну и да, логики как правило там минимум и тестировать особо нечего.
#1049 #944598
>>944562

Ты скорее всего не задумываешься, так как ты только пишешь код. А ты попробуй разобрать чужой код, где много коллбеков.

Я в PHP кое-что писал на промисах и там можно голову сломать от сложности, которая получается (асинхронный запуск разных внешних процессов с разными ветвлениями и таймаутами).

>>944423

Data Mapper заточен именно на загрузку и сохранение объектов (он пытается сделать видимость, что базы нет, а есть просто набор объектов в памяти), а TDG это класс с набором любых действий с таблицей. Также, Data mapper может быть более продвинутым, например, сам уметь обнаруживать изменения в объектах и сохранять их в БД.

Более точные различия можно поискать в книге Фаулера "Шаблоны проектирования корпоративных приложений", где они и описаны.
#1050 #944610
>>944578
Разобрался, лол. Оказывается, без дополнительных указаний PDO эмулирует строки(добавляет кавычки) на основе всего этого. Соответсвенно, мне надо сделать такой финт -
$sth->bindValue(":start", $start, \PDO::PARAM_INT);
Однако все равно не работает сортировка, и вот тут я уже не пойму. Даже если вырубить эту эмуляцию через $this->dbh->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false ); все равно сортировка не работает.
944618
#1051 #944617
>>944578

Через плейсхолдеры вставляются только значения, цифры и строки в кавычках. Имена полей нельзя. Их придется вставлять напрямую, перед этим проверив по белому списку разрешенных полей, чтобы избежать уязвимостей.
944622
#1052 #944618
>>944610

Выключение эмуляции значит, что PDO не будет подставлять данные в запрос сам, а попросит базу это сделать, при условии что она поддерживает такую возможность (иначе он все равно подставит сам).
944622
#1053 #944622
>>944617
Понял, что-то уже слышал об этом.
>>944618
Значит для безопасности мне надо написать код, который проверяет значение $order на существование такого поля в таблице? Бля, у меня и без того есть всякие методы, которые выглядят как не пришей к пизде рукав.
944628
#1054 #944628
>>944622

Можно просто массивом сделать список.
944630
#1055 #944630
>>944628
А как проверить на несоответствие какому-то элементу массива? Да в любом случае мне надо делать метод, т.к. сортировка у меня не один раз будет, а копипаст это западло, не?
#1056 #944639
В треде за тысячу постов и вопрос скорее всего утонет, так что напомню: >940144

>>940172
Тоже насчёт исключения думал.
1. В FileService валидируем файл.
2. Если есть ошибки - кладём их в исключение, выбрасываем наверх
3. Наверху кладём ошибки в форму? Они ведь в ней и так содержатся.
944654
#1057 #944648
В чем разница между двумя знаками равно и между тремя?
944783
#1058 #944654
>>940144

Бывают ситуации, когда надо вернуть нескоько результатов. Тут есть такие варианты:

- можно вернуть массив вида ['error' => null, 'file' => $file]
- можно вернуть массив вида [$file, $error] - его удобно распаковать через list(..) = ...
- можно вернуть $file через return, а ошибку как аргумент переданный по ссылке:

$error = null;
$file = upload(..., &$error);

- можно сделать объект UploadResult с 2 полями (больше всего писанины)

Не очень удобно конечно, в других языках вроде Го есть синтаксис для возврата нескольких значений с указанием типов: func something() (File, Error) { ... }

Насчет кода - стоит ли FileNameGenerator делать полноценной зависимостью? Может проще метод вроде generateName поместить в этот же класс?

> Почему сразу не использую UploadedFIle: https://github.com/symfony/http-foundation/blob/master/File/UploadedFile.php


> Его тоже можно переместить, даже если он получен не из HTTP (параметр $test в конструкторе), но, как я понял, параметр $test тут только для тестов.


UploadedFile это именно что загруженный в $FILES файл, хранящийся во временной папке, его возвращать нелогично.

> как я понял, параметр $test тут только для тестов.


Именно так.

>>944639

Насчет исключений есть разные мнения. Есть те, кто считает что исключения мжно выбрасывать при валидации, есть мнение что неправильно.

Мне больше нравится идея возвращать объект исключения, если это не фатальная ошибка и выбрасывать, если что-то например передано неправиьно. Например, в комментарии не указан IP адрес автора.
#1058 #944654
>>940144

Бывают ситуации, когда надо вернуть нескоько результатов. Тут есть такие варианты:

- можно вернуть массив вида ['error' => null, 'file' => $file]
- можно вернуть массив вида [$file, $error] - его удобно распаковать через list(..) = ...
- можно вернуть $file через return, а ошибку как аргумент переданный по ссылке:

$error = null;
$file = upload(..., &$error);

- можно сделать объект UploadResult с 2 полями (больше всего писанины)

Не очень удобно конечно, в других языках вроде Го есть синтаксис для возврата нескольких значений с указанием типов: func something() (File, Error) { ... }

Насчет кода - стоит ли FileNameGenerator делать полноценной зависимостью? Может проще метод вроде generateName поместить в этот же класс?

> Почему сразу не использую UploadedFIle: https://github.com/symfony/http-foundation/blob/master/File/UploadedFile.php


> Его тоже можно переместить, даже если он получен не из HTTP (параметр $test в конструкторе), но, как я понял, параметр $test тут только для тестов.


UploadedFile это именно что загруженный в $FILES файл, хранящийся во временной папке, его возвращать нелогично.

> как я понял, параметр $test тут только для тестов.


Именно так.

>>944639

Насчет исключений есть разные мнения. Есть те, кто считает что исключения мжно выбрасывать при валидации, есть мнение что неправильно.

Мне больше нравится идея возвращать объект исключения, если это не фатальная ошибка и выбрасывать, если что-то например передано неправиьно. Например, в комментарии не указан IP адрес автора.
944756
#1059 #944756
>>944654
Тогда как насчёт такого алгоритма:
- собрать форму без валидатора
- если форма отправлена - вытащить из неё файл и передать его в FileService#upload, получить результат с объектами ConstraintViolationList и Entity\File
- если список ошибок пуст, перенаправить пользователя на страницу с файлом
- если не пуст, положить ошибки в форму, отрисовать страницу с формой
Если ничего не упустил, то такой FileService можно и из консоли запускать.

>Может проще метод вроде generateName поместить в этот же класс?


Думаю, что проще, раз FileGenerator больше ни одному из сервисов не нужен.
#1060 #944783
>>944648
оператор == использует (неявное) приведение типов, а оператор === не использует его.
#1061 #944796
ОПчик, ты недавно проверял моих судентов, поясни зачем вот это

>тут не очень хорошо сделано. Если ты хочешь требовать регистрацию, то надо не выводить форму на любой странице, а делать редирект на страницу регистрации. Если ты хочешь потом вернуться назад, то надо еще передавать URL исходной страницы (а перед редиректом назад проверять, что он на твоем сайте, иначе это будет открытый редирект).


Я то понял как, только зачем?
#1062 #944800
В чем ошибка? strlen выводит всегда на 2 единицы больше. Как я понял это связанно с fgets(STDIN)
Вот код:
<?php

class Test
{

public $text;

public function __construct()
{
$this->text = fgets(STDIN);
}

public function strln()
{
echo strlen($this->text);
}

}

$a=new Test;
$a->strln();

sleep(20);
944805
#1063 #944805
>>944800
Что за хуита?
class Test
{

public $text;

public function __construct()
{
$this->text = fgets(STDIN);
}

public function strln()
{
echo strlen($this->text);
}
}

$a=new Test;
$a->strln();

sleep(20);
944819
#1064 #944819
>>944805
Ты кириллицу туда вводишь? Простой strlen() показывает тебе количество байтов, тогда как кириличный символ два байта занимает, т.е. длину кириличной строки ты так не определишь, юзай mb_strlen().
944822
#1065 #944822
>>944819
Я латиницу вводил. Попробую mb_strlen()
944841
#1066 #944841
>>944822
Я все-таки был прав, это проблемы с fgets(STDIN);
var_dump вывел
string<5> "aaa
"
Как это фиксить?
944914
#1067 #944906
куда развиваться? зделол свой интернет магазин на локалхосте без фреймворков. Ну, сделаю такой же на йи. И что?
944907
#1068 #944907
>>944906
Ну ты его покажи нам сначала, а дальше мы посмотрим куда тебе развиваться.
944910
#1069 #944910
>>944907

когда поправлю читабельность от своих привычек - покажу. Но мне интересен теоретический необходимый баланс знаний.
944942
#1070 #944914
>>944841

2 байта это символы конца строки \r \n (CR LF). То есть нажатие клавиши Enter.
#1071 #944942
>>944910
Знаний для чего? Для вката на работу?
945005
#1072 #945005
>>944942

ну хотя бы так. Или путь ноль-джун-мидуль-синьорпомидор-????
945009
#1073 #945009
>>945005
Делай пару пет-проектов начинай искать работу.
945482
#1074 #945019
>>938230

http://ideone.com/BKOWHE

Я не понимат, кому выше и каким образом кидать виджет-ивенты, если я использую сложные V/C виджеты.

Попробовал вот так: в методе PopupController.prototype._attachToPopupView я кину искусственное событие в parentView. Правильно?

Так же вопрос #2, как ловить вот такие события. Так как popup у меня вроде как динамический, я решил сделать количество кнопок по выбору. Их количество и текст внутри зависит от параметра массива optionTxt и его длины, соответственно. Ну а как мне обозначать тип таких событий вот здесь - см. строку "вопрос 2" в коде? Мне всего лишь надо передать номер в старший класс (DomGameView в моем случае) где уже с выбранной опцией вызовется нужный метод из модели. Не делать же заранее 100 констант с номером опций попапа?

Пока не проверяй на гитхабе моего сапера, я коммит готовлю с исправлениями твоих первых правок.
945024945063
#1075 #945024
>>945019

Уточню на счет второго вопроса. В методе dispatcher.addEventListener(EVENT.SOME, func) (его код кстати здесь https://github.com/greenTea242/MinesweeperMVC/blob/master/src/models/EventDispatcher.js , напоминаю что это не нативный addEventListener) первое событие уникальное. А у меня может n-ое количество ивентов, так как кнопок может быть много.
});
945026
#1076 #945026
>>945024

> первое событие



Первый аргумент. Фикс.
#1077 #945063
>>945019

Ну с кнопками я бы предложил например такой вариант:

назначить каждой кнопке свой id и при нажатии передавать его в событии:

var popupCtrl = new PopupCtrl(...);

popupCtrl.addButton(SOME_ID, 'Do something');
popupCtrl.addButton(BTN_YES, 'Yes');

или:

popupCtrl.setButtons([
{ id: SOME_ID, title: 'Do Something'},
...
]);

и далее мы подписываемся на события попапа:

popupCtrl.getDispatcher().addEventListener(Popup.EVENT_SELECT, function (buttonId) {
...
});

Вот этот код выше можно прописать в контроллере игрового поля. View игрового поля про попап тогда знать не обязательно.

Также, я не вижу смысла передавать в контроллер попапа объект его view. Можно наверно создавать view прямо в нем. Все равно ведь никто другой этот view использовать не будет.

Еще может быть стоит подумть об объединении PopupView и PopupCtrl, например в PopupView. В случае с игровым полем - может смысл есть разделять, так как там относительно сложный код, мы можем использовать view без контроллера для отображения данных итд. А тут не очень понятно, в чем выгода.

Может сделать один класс с такими методами?

- addButton() или setButtons() - задают кнопки
- show() - создает HTML-код и ставит обработчики на кнопки
- destroy() - закрывает попап
- getDispatcher() - позволяет подписаться на событие закрытия попапа кнопкой

Вариант с таким кодом: parentViewDispatcher.dispatchEvent(new PopupEvent(PopupEvent.CLOSE_OPTION)); явно сомнительный, так как мы лезем в другое вью и от его имени выбрасываем какие-то события. Это нарушение инкапсуляции, один объект не должен выбрасывать события от имени другого.

И также тут не нужен this._parentContainer.addEventListener("click" - события логично ловить в самом попапе. А твой код пытается ловить события и в родительском вью.

> Не делать же заранее 100 констант с номером опций попапа?


Делать или не делать константы - это задача того, кто вызывает попап, а не попапа.

> напоминаю что это не нативный addEventListener) первое событие уникальное. А у меня может n-ое количество ивентов, так как кнопок может быть много.



Можно сделать единственное событие, соответствующее закрытию попапа, хранящее, какой опцией или кнопкой он закрыт.

Вообще, у нас конечно сложноватая схема получилась. Такие иерархии из виджетов обычно используются при построении GUI в десктопных приложениях.

Для сравнения, напишу, как это реализуется в HTML-фремворках вроде angular/react:

- там мы не пишем код для view в виде класса, не пишем код создания дочерних виджетов, а только делаем HTML-шаблон для компонента, в котором могут указываться ссылки на другие компоненты примерно такого вида:

<div>
{$text}
<SomeWidget x={$x} y={$y}/>
<button onclick={doDomething}>Do domething</button>
</div>

Вот это весь view. Нет кода, только разметка.

- вместо явной подписки на события мы указываем название метода-обработчика из контроллера в HTML-разметке

- для обновления данных на странице и чтения данных с нее используется data-binding, когда мы например можем привязать инпут к переменной и она будет автоматически обновляться при вводе туда данных, и наоборот, при изменении значения переменной обновляется инпут.

Это в сумме позволяет избавиться от написания рутинного кода работы с DOM (поиск элементов по селектору, подписка на события, обновление HTML), в итоге view у нас просто представлен куском HTML-подобной разметки, и controller не содержит работы с DOM. Ну к примеру, чтобы обновить текст на экране, мы в контроллере просто меняем значение переменной, которая привязана к этому блоку текста.

Примерно так получается (тут используется синтаксис ES6):

// компонент (по сути контроллер из MVC)
class Counter extends React.Component {

constructor() {
this.setState({
count: 0
});
}

// обработчик нажатия на кнопку
increment() {
this.setState({ count: this.state.count + 1 });
}

// в реакте view описывается разметкой прямо в компоненте
render() {
return <div>Count: {this.state.count}</div>
<button onclick={increment}>+1</button>
}
}

Как видишь, много рутинного кода для работы с DOM здесь выкинуто. Ну это конечно такой простой пример, где мы данные храним прямо в контроллере. Если ты захочешь добавить какую-то сложную модель, то код конечно усложнится, придется городить всякие хранилища, преобразователи (redux) и прочее, так как сама по себе эта штука отслеживать изменения в модели не умеет.

Но для попапа, у которого нет модели, этот подход дал бы такой же простой код, как в примере выше.

Надеюсь я тебя заинтересовал после реализации MVC без фреймворков посмотреть на react. Но сначала с тем, что есть, разберись.
#1077 #945063
>>945019

Ну с кнопками я бы предложил например такой вариант:

назначить каждой кнопке свой id и при нажатии передавать его в событии:

var popupCtrl = new PopupCtrl(...);

popupCtrl.addButton(SOME_ID, 'Do something');
popupCtrl.addButton(BTN_YES, 'Yes');

или:

popupCtrl.setButtons([
{ id: SOME_ID, title: 'Do Something'},
...
]);

и далее мы подписываемся на события попапа:

popupCtrl.getDispatcher().addEventListener(Popup.EVENT_SELECT, function (buttonId) {
...
});

Вот этот код выше можно прописать в контроллере игрового поля. View игрового поля про попап тогда знать не обязательно.

Также, я не вижу смысла передавать в контроллер попапа объект его view. Можно наверно создавать view прямо в нем. Все равно ведь никто другой этот view использовать не будет.

Еще может быть стоит подумть об объединении PopupView и PopupCtrl, например в PopupView. В случае с игровым полем - может смысл есть разделять, так как там относительно сложный код, мы можем использовать view без контроллера для отображения данных итд. А тут не очень понятно, в чем выгода.

Может сделать один класс с такими методами?

- addButton() или setButtons() - задают кнопки
- show() - создает HTML-код и ставит обработчики на кнопки
- destroy() - закрывает попап
- getDispatcher() - позволяет подписаться на событие закрытия попапа кнопкой

Вариант с таким кодом: parentViewDispatcher.dispatchEvent(new PopupEvent(PopupEvent.CLOSE_OPTION)); явно сомнительный, так как мы лезем в другое вью и от его имени выбрасываем какие-то события. Это нарушение инкапсуляции, один объект не должен выбрасывать события от имени другого.

И также тут не нужен this._parentContainer.addEventListener("click" - события логично ловить в самом попапе. А твой код пытается ловить события и в родительском вью.

> Не делать же заранее 100 констант с номером опций попапа?


Делать или не делать константы - это задача того, кто вызывает попап, а не попапа.

> напоминаю что это не нативный addEventListener) первое событие уникальное. А у меня может n-ое количество ивентов, так как кнопок может быть много.



Можно сделать единственное событие, соответствующее закрытию попапа, хранящее, какой опцией или кнопкой он закрыт.

Вообще, у нас конечно сложноватая схема получилась. Такие иерархии из виджетов обычно используются при построении GUI в десктопных приложениях.

Для сравнения, напишу, как это реализуется в HTML-фремворках вроде angular/react:

- там мы не пишем код для view в виде класса, не пишем код создания дочерних виджетов, а только делаем HTML-шаблон для компонента, в котором могут указываться ссылки на другие компоненты примерно такого вида:

<div>
{$text}
<SomeWidget x={$x} y={$y}/>
<button onclick={doDomething}>Do domething</button>
</div>

Вот это весь view. Нет кода, только разметка.

- вместо явной подписки на события мы указываем название метода-обработчика из контроллера в HTML-разметке

- для обновления данных на странице и чтения данных с нее используется data-binding, когда мы например можем привязать инпут к переменной и она будет автоматически обновляться при вводе туда данных, и наоборот, при изменении значения переменной обновляется инпут.

Это в сумме позволяет избавиться от написания рутинного кода работы с DOM (поиск элементов по селектору, подписка на события, обновление HTML), в итоге view у нас просто представлен куском HTML-подобной разметки, и controller не содержит работы с DOM. Ну к примеру, чтобы обновить текст на экране, мы в контроллере просто меняем значение переменной, которая привязана к этому блоку текста.

Примерно так получается (тут используется синтаксис ES6):

// компонент (по сути контроллер из MVC)
class Counter extends React.Component {

constructor() {
this.setState({
count: 0
});
}

// обработчик нажатия на кнопку
increment() {
this.setState({ count: this.state.count + 1 });
}

// в реакте view описывается разметкой прямо в компоненте
render() {
return <div>Count: {this.state.count}</div>
<button onclick={increment}>+1</button>
}
}

Как видишь, много рутинного кода для работы с DOM здесь выкинуто. Ну это конечно такой простой пример, где мы данные храним прямо в контроллере. Если ты захочешь добавить какую-то сложную модель, то код конечно усложнится, придется городить всякие хранилища, преобразователи (redux) и прочее, так как сама по себе эта штука отслеживать изменения в модели не умеет.

Но для попапа, у которого нет модели, этот подход дал бы такой же простой код, как в примере выше.

Надеюсь я тебя заинтересовал после реализации MVC без фреймворков посмотреть на react. Но сначала с тем, что есть, разберись.
#1078 #945065
Новый тред >>945059 (OP)

Тут будут только ответы на старые вопросы. Если вас пропустили - напомните о себе в новом треде.
#1079 #945482
>>945009

ну а куда развиваться то?
на работе будет тоже самое, что курс хохла про интернет магазин же, я хз. Как они синьоров отличают? Три сайта в день шлепает вместо одного?
#1080 #945935
Будет ли полезен учебник по php сейчас?или он уже не актуален?
947023
#1081 #947023
>>945935
Да. Нет.
#1082 #947266
http://ideone.com/qBu9Bo
Правильно ли?
947302
#1083 #947302
>>947266
Нет.
Во втором банке должно получиться как в задаче про Айфон - 61270.
947841
#1084 #947841
>>947302
Ошибка в функции?
#1085 #948208
Приглашаем в нашу группу в Telegram !:
https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
Десятки опытных программистов без труда ответят на любой ваш вопрос!
#1086 #950824
Йов пачаны. Вот код для определения администратора на сайте. Он норм? или можно все проще сделать?

include_once 'connect.php';
$ip = $_SERVER['REMOTE_ADDR'];
$stmt = $pdo->query("SELECT * FROM admins WHERE admin_ip='$ip'");
while ($row = $stmt->fetch())
{
$ad = $row["admin_ip"];
}
if ($ad == $ip){
echo 'Йов битч ты админ';
}
else {
echo 'Ты не админ, ухади';
}
951062951202
#1087 #951062
>>950824
Эм... Админ определяется по айпишнику?
951413
#1088 #951202
>>950824

Новый тред тут >>945059 (OP)
#1089 #951413
Тред утонул или удален.
Это копия, сохраненная 15 марта 2017 года.

Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски