Это копия, сохраненная 18 августа 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это не чат! Пожалуйста старайтесь постить только вопросы, решения и ответы по теме. Сколько лет вы не можете найти работу никому не интересно. Высказывайтесь одним большим постом, а не цепочкой мелких
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: >>769611 (OP)
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост прежде чем писать код).
Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 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/Yii2: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование
- Если ты все решил, переходи к 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://gist.github.com/codedokode/10539213
Что почитать
- Мануал по 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
Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Если тебе лень выравнивать код руками, закачай его на 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/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Если тебе лень выравнивать код руками, закачай его на 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/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
>> $this->sign ^= true;
> ^ это не булев, а целочисленный (побитовый) оператор. Он работает с числами а не true/false.
У меня была идея использовать его вот так: вот есть знак, допустимое множество принимаемых им значений: ['+', '-']. В таком случае логичнее знак выразить через булевый оператор, да и в PHP нет enum'ов. Знак дроби нужно будет менять. Для смены знака можно использовать код вроде "Если знак true, выставить ему false, если знак false - выставить true".
А можно сделать без условий вот так: $this->sign ^= true; Этот код будет всегда менять знак на противоположный, пример на пике [NUMBER]
На пике часть его таблицы истинности.
XOR ведь ещё для шифрования из-за обратимости используется, поскольку false ^ true ^ true даст false. Если знак инвертировать 2 раза, то мы получим тот же знак, что и был у нас изначально. Я в упор не вижу какого-то более простого и очевидного решения?
В любом случае, как я и говорил, это подразумевает необходимость возиться со знаками. Хотя ещё была идея абсолютно все действия выражать через Addition (Power выражается через Multiplication, который в свою очередь выражается через Addition). Это позволило бы возню со знаками сконцентрировать в одном месте, в классе Addition.
> Чему равен корень из 2? Это так называемая бесконечная дробь, которую нельзя представить в виде рационального числа.
Получается, надо либо запретить возводить в дробные степени, либо запретить возводить в степени, которые дают иррациональное число (метод Роскомнадзора), либо придумать метод выразить результат приближенно (увы, теряя точность).
> Неплохо бы помечать полученные в результате округления значения специальной пометкой.
То есть делать для каждой SimpleFraction флаг, отвечающий за точность/неточность? И исходить из того, что точная дробь оператор неточная дробь даст неточную дробь?
Всё-таки склоняюсь к тому, чтобы запретить возводить число в степень дроби, предварительно делая проверку на логарифм.
То есть 9 ^ 1/2 возводить можно, потому что 2 - логарифм 9-и по основанию 3.
9 ^ 1/3 возводить уже нельзя, потому что ни одно число в 3-й степени не равно 9-и.
>> return (string) floatval(bcdiv(...))
> floatval делает преобразование в float. float даже в 64-битном пхп сохраняет не более 14 значащих цифр
Там precision у bcdiv 20, то есть он всегда дробную часть добивает нулями. Тогда нули убирать регулярками/фунциями для манипуляций со строками?
И ещё раз спасибо большое за дельные советы по остальному.
Алсо, ссылка на https://swtch.com/~rsc/regexp/ не работает.
>> $this->sign ^= true;
> ^ это не булев, а целочисленный (побитовый) оператор. Он работает с числами а не true/false.
У меня была идея использовать его вот так: вот есть знак, допустимое множество принимаемых им значений: ['+', '-']. В таком случае логичнее знак выразить через булевый оператор, да и в PHP нет enum'ов. Знак дроби нужно будет менять. Для смены знака можно использовать код вроде "Если знак true, выставить ему false, если знак false - выставить true".
А можно сделать без условий вот так: $this->sign ^= true; Этот код будет всегда менять знак на противоположный, пример на пике [NUMBER]
На пике часть его таблицы истинности.
XOR ведь ещё для шифрования из-за обратимости используется, поскольку false ^ true ^ true даст false. Если знак инвертировать 2 раза, то мы получим тот же знак, что и был у нас изначально. Я в упор не вижу какого-то более простого и очевидного решения?
В любом случае, как я и говорил, это подразумевает необходимость возиться со знаками. Хотя ещё была идея абсолютно все действия выражать через Addition (Power выражается через Multiplication, который в свою очередь выражается через Addition). Это позволило бы возню со знаками сконцентрировать в одном месте, в классе Addition.
> Чему равен корень из 2? Это так называемая бесконечная дробь, которую нельзя представить в виде рационального числа.
Получается, надо либо запретить возводить в дробные степени, либо запретить возводить в степени, которые дают иррациональное число (метод Роскомнадзора), либо придумать метод выразить результат приближенно (увы, теряя точность).
> Неплохо бы помечать полученные в результате округления значения специальной пометкой.
То есть делать для каждой SimpleFraction флаг, отвечающий за точность/неточность? И исходить из того, что точная дробь оператор неточная дробь даст неточную дробь?
Всё-таки склоняюсь к тому, чтобы запретить возводить число в степень дроби, предварительно делая проверку на логарифм.
То есть 9 ^ 1/2 возводить можно, потому что 2 - логарифм 9-и по основанию 3.
9 ^ 1/3 возводить уже нельзя, потому что ни одно число в 3-й степени не равно 9-и.
>> return (string) floatval(bcdiv(...))
> floatval делает преобразование в float. float даже в 64-битном пхп сохраняет не более 14 значащих цифр
Там precision у bcdiv 20, то есть он всегда дробную часть добивает нулями. Тогда нули убирать регулярками/фунциями для манипуляций со строками?
И ещё раз спасибо большое за дельные советы по остальному.
Алсо, ссылка на https://swtch.com/~rsc/regexp/ не работает.
Привет, аноны-мастера. Есть тут кто-то, кто поможет не опытному разобраться с проблемой? Суть, собственно вот в чем:
делаю сайт на Codeigniter(ТЗ, на должность джуниора) и все в общем хорошо получается, но вот не могу раздуплиться с Базой Данных. Мне нужно создать БД с тремя таблицами - не вопрос. создал (написал запрос SQL и отправил на сервак) и дальше прекрасно с ней работаю, но я не пойму как мене отправить это работодателю. Просто вложенный файл с запросом, или написать дополнительный метод метод и объяснить им что он делает. Собственно не имея опыта я и хочу разобраться как лучше сделать
Напиши отдельный скрипт, с названием что-то типа sql-shema , который будет накатывать таблицы, если их нет.
Апну вверх.
>>773648
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php
>Далее, нет логики в наследовании хелперов. Вот у тебя есть Helper и есть LoginHelper, который его наследует. Непонятно, а зачем? Там все равно почти все методы статические. Точнее, часть статическая, а часть нет, и почему, непонятно.
В контроллерах нужны оба этих класса. Если наследовать их, то можно будет обойтись только одним.
>>773648
>И наконец, в некоторых местах, ты обращаешься к массивам вроде $_GET или $_COOKIE, не проверяя перед этим, есть ли в них такой элемент:
>Helper::redirect($_GET['go']);
>Но ведь он может и отсутствовать. Лучше использовать функцию, вроде $this->getQuery('go'), которая делает нужную проверку.
А куда поместить метод getCookie('cookieName')? Мы скорее обращаемся к ним и на заглавной странице и в хелперах, а не в контроллере.
И нужен ли метод getPost('postName')? Все равно данные пришедшие из $_POST обрабатываются в классе формы: https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Forms/RegisterStudentForm.php#L19
>>773648
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php#L6
>Редирект, кстати, я подумал, логичнее было бы поместить в базовый класс контроллера. Тогда редиректить можно будет только из контроллеров.
А это разве не задача модели? Контроллер же должен только работать с пришедшими данными и обращаться к модели.
В твиттере и фейсбуке разлогинивание происходит тоже через форму. Правда там какой-то странный синтаксис.
Выглядит это примерно так:
<button type="button">Exit</button>
<form method="POST" action="/logout">
<input type="hidden" name="token" value="...">
</form>
Как это сделано? Ведь тэг button и форма никак не связанны. С помощью js? А если пользователь отключил его то такой способ не подходит? Почему нельзя просто добавить <input type="button"> внутри формы?
>>773648
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php
>Далее, нет логики в наследовании хелперов. Вот у тебя есть Helper и есть LoginHelper, который его наследует. Непонятно, а зачем? Там все равно почти все методы статические. Точнее, часть статическая, а часть нет, и почему, непонятно.
В контроллерах нужны оба этих класса. Если наследовать их, то можно будет обойтись только одним.
>>773648
>И наконец, в некоторых местах, ты обращаешься к массивам вроде $_GET или $_COOKIE, не проверяя перед этим, есть ли в них такой элемент:
>Helper::redirect($_GET['go']);
>Но ведь он может и отсутствовать. Лучше использовать функцию, вроде $this->getQuery('go'), которая делает нужную проверку.
А куда поместить метод getCookie('cookieName')? Мы скорее обращаемся к ним и на заглавной странице и в хелперах, а не в контроллере.
И нужен ли метод getPost('postName')? Все равно данные пришедшие из $_POST обрабатываются в классе формы: https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Forms/RegisterStudentForm.php#L19
>>773648
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php#L6
>Редирект, кстати, я подумал, логичнее было бы поместить в базовый класс контроллера. Тогда редиректить можно будет только из контроллеров.
А это разве не задача модели? Контроллер же должен только работать с пришедшими данными и обращаться к модели.
В твиттере и фейсбуке разлогинивание происходит тоже через форму. Правда там какой-то странный синтаксис.
Выглядит это примерно так:
<button type="button">Exit</button>
<form method="POST" action="/logout">
<input type="hidden" name="token" value="...">
</form>
Как это сделано? Ведь тэг button и форма никак не связанны. С помощью js? А если пользователь отключил его то такой способ не подходит? Почему нельзя просто добавить <input type="button"> внутри формы?
Макаке, я думаю вообще переживать не стоит по этому поводу, а специалисту - конечно нужно.
Есть скрипт который добавляет строку в таблицу Базы Данных.
Запускаю чего через CRON каждую минуту. Настройки выставлены правильно, техподдерка моего хостинга так же говорит что проблема с моей стороны.
Итак как видно на пике, я выставляю как положено настройки чтобы скрипт запускался каждую минуту, но вот каждый час скрипт запускается лишний раз. Я так понимаю, скорее всего и каждый день\месяц и т.д. будет лишний запуск.
Возможно я неправильно пишу команду? Может wget здесь нужно заменить на что-то другое? С кроном никогда не работал, гугл молчит, схожих проблем я там не смог найти, как починить не знаю, уже отчаялся, спасайте.
Читать шапку ты не хочешь из принципа?
(SELECT FROM `filmmeta`
WHERE id =10) union (select ,null,null,null from filmfields where filmid=10)
Все задания по регулярке.
Задача про телефонные номера:
http://ideone.com/k4Man9
"усложненная" задача про номера:
http://ideone.com/5qNwL9
Автозамена:
http://ideone.com/uxO9zY
Продолжение потом закину
Сапер https://jsfiddle.net/mayzx8qt/ >>794739
Антикризисные меры, вектор http://ideone.com/IXqHnc >>794740
https://github.com/never3ver/studentslist >>794742
Вектор | http://ideone.com/H5DCfT >>794743
Зайдите, посмотрите.
Если про вас забыли - можете напомнить тут о себе в этом треде.
Напомню себе что надо будет глянуть https://github.com/applejacky/students
> А можно сделать без условий вот так: $this->sign ^= true;
Нельзя, попробуй сдампить var_dump(true ^ false ) - будет число а не булевое значение. Можешь еще заодно посмотреть например чему равно 35 ^ 63. ^ работает с числами.
Знак представляют в виде +1/-1 и тогда его можно умножать. Но тут в этом нет смысла, можно сделать чтобы знаменатль был всегда положительным и тогда знак дроби зависит только от числителя.
> Хотя ещё была идея абсолютно все действия выражать через Addition (Power выражается через Multiplication, который в свою очередь выражается через Addition).
Это будет нереально медленно.
> То есть делать для каждой SimpleFraction флаг, отвечающий за точность/неточность? И исходить из того, что точная дробь оператор неточная дробь даст неточную дробь?
Да, как вариант. И такие неточные дроби всегда выводить как десятичные например.
> Всё-таки склоняюсь к тому, чтобы запретить возводить число в степень дроби, предварительно делая проверку на логарифм.
А нельзя проверять что получилось целое число? Хотя, при работе с float гарантий что оно дейсивтельно целое, нету... Можно попробовать получившееся число возвести обратно в квадрат с bcmul и проверить что ответ совпадает с исходным, точным числом.
> Там precision у bcdiv 20, то есть он всегда дробную часть добивает нулями. Тогда нули убирать регулярками/фунциями для манипуляций со строками?
У тебя по идее знаменатель и числитель целые ведь. Зачем что-то добивать?
> Алсо, ссылка на https://swtch.com/~rsc/regexp/ не работает.
У меня работает. Попробуй чрез гуглокеш ( http://webcache.googleusercontent.com/search?q=cache:https://swtch.com/~rsc/regexp/&ie=UTF-8&gws_rd=cr&ei=gUGFV4yrCsifsgGQpLnoBQ ) или прокси открть или другим браузером - в фаерфоксе у меня 100% работает.
> В контроллерах нужны оба этих класса. Если наследовать их, то можно будет обойтись только одним.
Это не повод для наследования. Наследование это отношения вида "А является Б" и тут это явно 2 отдельных не связанных друг с другом класса.
> А куда поместить метод getCookie('cookieName')?
В хелпер например.
> И нужен ли метод getPost('postName')?
Можешь сделать если хочешь.
>>Редирект, кстати, я подумал, логичнее было бы поместить в базовый класс контроллера. Тогда редиректить можно будет только из контроллеров.
> А это разве не задача модели? Контроллер же должен только работать с пришедшими данными и обращаться к модели.
ты не понимаешь MVC. Модель не взаимодействует с внешним миром и не отвечает за интерфейс пользователя. Она управляет данными, внутренним состоянием программы (в твоем случае - списком стдентов).
Редирект это взаимодейсвтие с браузером пользователя, это интерфейс. Вот представь что мы работаем с твоей программой из командной строки. Какой смысл имеет в командной строке редирект? Никакого, это часть протокола HTTP. Значит, в модели ему делать нечего так как модель - это код, который не зависит от способа взаимодействия пользоваетля с программой.
> Как это сделано? Ведь тэг button и форма никак не связанны. С помощью js? А если пользователь отключил его то такой способ не подходит?
Да, наверно через js. Хотя в HTML5 вроде есть какой-то атрибут чтобы привязать кнопку к форме по id.
> Почему нельзя просто добавить <input type="button"> внутри формы?
Не знаю, спроси у автора кода.
А хуле в вакансиях пишут по 5-8к хрювен? Или я что то не так делаю и не там смотрю(смотрю сайты типа работы.юа, доу.юа и т.д.)? Как "правильно" искать первую работу? Мб есть какие-то вакансии о которых я не знаю? Мне говорят в моем городе есть дохуя вакансий и типа все ищут но на том же доу и работе нихуя нет вообще.
1) Джун это 0.5-1 год опыта работы, зп обычно 600-800
2) Тебе нужна стажировка/интернатура/трейни, там как раз платят 300 баксов и тебя скорее УЧАТ чем ты работаешь
Где искать? В любой крупной компании. Циклум, люкс, софтсерв, епам и глобал по 200-400 человек в год набирают.
Упс, слегонца тредом ошибся, думал это в МЫ ВАМ ПЕРЕЗВОНИМ, лол.
Ну, на пхпшников они набирают заметно меньше, но если ты хорошо знаешь жс, то можно найти и там нечто подобное. Обычно на пхп набирают компании попроще, ибо в сириус интерпрайз говне пхп особо не живёт.
Значит город у тебя маленький или ты смотришь вакансии на которых оформляют по трудовой. Нормальная ЗП джуна в украинском городе с населением от миллиона это начиная от $500.
Есть еще вакансии стажеров, но это вообще рабский труд, не рекомендую.
Это пиздец какой плюс, особенно если ты можешь по ним всё объяснить и это не хеллоу ворлд.
Проектик на фреймворке, с тестиками и прочим в глазах работодателя будет выглядеть просто збс.
user (id, name) values
(1, 'Иванов Иван Иванович'),
(2, 'Иван Иванович Иванов'),
...
(33, 'иван(несколько пробелов)иванович иванов')
Задача: как убрать повторяющиеся записи, если они не посимвольно совпадают?
Хорошо хоть не регулярки.
Нет, это делается средствами sql.
Возможно полнотекстовый поиск, затем удалять по релевантности.
Мимо собираюсь учить пыху паралельно с джавой аналог книги которую я хочу это хуйня по джаве от Г. Шилдта
То чувство, когда пошел качать книги порекомендованные оп-ом, они в формате djvu, полез качать ридер под это дело, зашел на первый в списке гугла сайт с приятной наружностью. Скачал их читалку, а эти пидоры поимели меня, установив кучу параши уровня амиго, мейл.ру, одноклассников и вообще блядь просто реально около 10 софтин без спроса в том числе новый какой-то сраный браузер и блядь сломали старые браузеры. Сука я от злобы нахуй аж винду снес блядь.
То чувство, когда дибил не может скачать простой windjview с сайта разработчика
Вот ты на своем примере убедился насколько убого сделаны с точки зрения безопасности настольные ОС. Любая установленная программа получает полный доступ к твоему компьюетру. С таким подходом ставить можно только какие-то широко известные программы с открытым кодом.
Мне в этом плане нравится как сделаны айфоны (где все модерируется), ну и андроид (он похуже: разрешения при установке показывает но отключить например доступ в интернет не позволяет).
Не забудь после удаления программ переустановить браузеры и сменить пароли - возможно что доступы к сайтам тоже украдены.
Для чтения djvu есть windjview.
Робин Никсон "Создаём динамические сайты на Вашей досточтимой матушке".
А вообще учебник ОПа как раз для новичков.
SELECT * FROM stat WHERE datetime_now = (SELECT max(datetime_now) FROM stat)
Достает из базы строку с последней датой.
Как мне достать теперь строку с датой на минуту меньше? Всякие dateadd не работают, ну или я рукожоп.
Тип DATETIME если что.
Зачем тебе парсер, если PHP сам парсер?
На сайте должен быть каталог с его недвигой и собственно поиск по этому каталогу с помощью ключевых тегов.
Самому риелтору нужна админка, чтобы добавлять и удалять недвигу из каталога.
Какая цмс для такого лучше подойдёт?
> попробуй сдампить var_dump(true ^ false )
Я забыл скастовать в bool. Примеры на пике. Но я таки увидел простое и очевидное решение - это оператор отрицания.
В таком случае операция смены знака могла бы выглядеть так: $this->sign = !$this->sign.
Стыдно, что раньше не заметил, сам оператор даже называется "отрицание".
>> Всё-таки склоняюсь к тому, чтобы запретить возводить число в степень дроби, предварительно делая проверку на логарифм.
> А нельзя проверять что получилось целое число? Хотя, при работе с float гарантий что оно дейсивтельно целое, нету...
Да, var_dump(pow(9, 1/2)) выдаёт float(3).
А вот JavaScript для Number.isInteger(Math.pow(9, 1/2)) выдаёт true.
> Можно попробовать получившееся число возвести обратно в квадрат с bcmul и проверить что ответ совпадает с исходным, точным числом.
Не понял что значит "возвести обратно в квадрат с bcmul" и зачем там bcmul.
Возьмём пример 9^1/2
Исходное число 9 нужно возвести в степень 1/2, делается только так: pow(9, 1/2). Как я уже писал раннее, функция pow - единственная функция, которая может возводить в дробные степени, но она ограничена битностью ОС, на которой запущена.
Короче от pow(9, 1/2) получили float(3). Теперь нужно проверить, что 3^2 === 9. Опять берём pow, bcpow не подходит, так как:
1) Отдаёт результат в строке, проверка float(3) === string(3) не пройдёт;
2) Мы изначально пользовались pow, может возникнуть ситуация, когда pow(очень_длинное_число) != bcpow(то_же_самое_очень_длинное_число)
Вот взял я pow, но pow(3, 2) !== int(9), так как pow возвращает float. Использовать нестрогое равенство (==) нельзя, так как pow(pow(9, 1/3), 3) == 9, что неправильно.
Вот здесь подробнее: https://ideone.com/I6onbw
Да и что делать с очень большими числами, которые pow не может обработать?
Чувствую, что во мне говорит леность и слабость, но всё-таки: может PHP не самый удачный язык для настолько точных расчётов и больших чисел?
Алсо, если вводить ограничение на длину вводимых чисел, как определять, что число слишком большое для данной битности ОС?
> попробуй сдампить var_dump(true ^ false )
Я забыл скастовать в bool. Примеры на пике. Но я таки увидел простое и очевидное решение - это оператор отрицания.
В таком случае операция смены знака могла бы выглядеть так: $this->sign = !$this->sign.
Стыдно, что раньше не заметил, сам оператор даже называется "отрицание".
>> Всё-таки склоняюсь к тому, чтобы запретить возводить число в степень дроби, предварительно делая проверку на логарифм.
> А нельзя проверять что получилось целое число? Хотя, при работе с float гарантий что оно дейсивтельно целое, нету...
Да, var_dump(pow(9, 1/2)) выдаёт float(3).
А вот JavaScript для Number.isInteger(Math.pow(9, 1/2)) выдаёт true.
> Можно попробовать получившееся число возвести обратно в квадрат с bcmul и проверить что ответ совпадает с исходным, точным числом.
Не понял что значит "возвести обратно в квадрат с bcmul" и зачем там bcmul.
Возьмём пример 9^1/2
Исходное число 9 нужно возвести в степень 1/2, делается только так: pow(9, 1/2). Как я уже писал раннее, функция pow - единственная функция, которая может возводить в дробные степени, но она ограничена битностью ОС, на которой запущена.
Короче от pow(9, 1/2) получили float(3). Теперь нужно проверить, что 3^2 === 9. Опять берём pow, bcpow не подходит, так как:
1) Отдаёт результат в строке, проверка float(3) === string(3) не пройдёт;
2) Мы изначально пользовались pow, может возникнуть ситуация, когда pow(очень_длинное_число) != bcpow(то_же_самое_очень_длинное_число)
Вот взял я pow, но pow(3, 2) !== int(9), так как pow возвращает float. Использовать нестрогое равенство (==) нельзя, так как pow(pow(9, 1/3), 3) == 9, что неправильно.
Вот здесь подробнее: https://ideone.com/I6onbw
Да и что делать с очень большими числами, которые pow не может обработать?
Чувствую, что во мне говорит леность и слабость, но всё-таки: может PHP не самый удачный язык для настолько точных расчётов и больших чисел?
Алсо, если вводить ограничение на длину вводимых чисел, как определять, что число слишком большое для данной битности ОС?
У меня идея такая:
$a = '9';
$b = '1'/'2';
// $a и $b преобразуются во float - возможная потеря точности
$result = pow($a, $b);
// $result имеет тип float - он неточный
Затем мы делаем такой трюк: возводим $result в квадрат с помощью bcpow (без потерь точности). Сравниваем результат возведения (строку) с $a (строкой). Если они совпали - результат (после преобразования в строку) оказался точный, если нет - мы потеряли где-то на конвертации во флоат или при взятии корня и имеем приблизительный результат.
Вообще, конечно, правильнее не писать это самому, а искать готовую библиотеку. Но с дробями сложность в том что корень из некоторых чисел (например корень из 2) в принципе невозможно посчитать точно. Он будет бесконечной непериодичной дробью, иррациональным числом, не представимым в виде a/b. Потому библиотека вроде bcmath ничем помочь не может.
Я уже писал выше, что чтобы работать с иррациональными числами, нам нужно хранить их как есть, то есть "корень степени a из b" и это приведет нас к тому что надо оперировать не числами, а выражениями вида "корень из 3 плюс корень из 2".
В твоем примере результат неточный, потому после возведения в куб не совпадает с исходным числом.
> Да и что делать с очень большими числами, которые pow не может обработать?
Ничего не поделать. Хотя имея точное представление числа можно определять что оно выходит за диапазон флоата.
> Чувствую, что во мне говорит леность и слабость, но всё-таки: может PHP не самый удачный язык для настолько точных расчётов и больших чисел?
Сам по себе - не удачный, нужна мат. библиотека.
> Алсо, если вводить ограничение на длину вводимых чисел, как определять, что число слишком большое для данной битности ОС?
Посмотреть пределы в мануале или погуглить IEEE 754. на хабре есть статья.
У меня идея такая:
$a = '9';
$b = '1'/'2';
// $a и $b преобразуются во float - возможная потеря точности
$result = pow($a, $b);
// $result имеет тип float - он неточный
Затем мы делаем такой трюк: возводим $result в квадрат с помощью bcpow (без потерь точности). Сравниваем результат возведения (строку) с $a (строкой). Если они совпали - результат (после преобразования в строку) оказался точный, если нет - мы потеряли где-то на конвертации во флоат или при взятии корня и имеем приблизительный результат.
Вообще, конечно, правильнее не писать это самому, а искать готовую библиотеку. Но с дробями сложность в том что корень из некоторых чисел (например корень из 2) в принципе невозможно посчитать точно. Он будет бесконечной непериодичной дробью, иррациональным числом, не представимым в виде a/b. Потому библиотека вроде bcmath ничем помочь не может.
Я уже писал выше, что чтобы работать с иррациональными числами, нам нужно хранить их как есть, то есть "корень степени a из b" и это приведет нас к тому что надо оперировать не числами, а выражениями вида "корень из 3 плюс корень из 2".
В твоем примере результат неточный, потому после возведения в куб не совпадает с исходным числом.
> Да и что делать с очень большими числами, которые pow не может обработать?
Ничего не поделать. Хотя имея точное представление числа можно определять что оно выходит за диапазон флоата.
> Чувствую, что во мне говорит леность и слабость, но всё-таки: может PHP не самый удачный язык для настолько точных расчётов и больших чисел?
Сам по себе - не удачный, нужна мат. библиотека.
> Алсо, если вводить ограничение на длину вводимых чисел, как определять, что число слишком большое для данной битности ОС?
Посмотреть пределы в мануале или погуглить IEEE 754. на хабре есть статья.
Я уже написал что знак числа удобнее представлять не в виде true/false а в виде +1/-1 и делать с ним нужные операции. Но тебе это не нужно.
Сам пиши библиотеку. Все говно
> то есть "корень степени a из b" и это приведет нас к тому что надо оперировать не числами, а выражениями вида "корень из 3 плюс корень из 2".
Я не смогу это реализовать. Даже если я добавлю объект "Иррациональное число" с дробью и подкоренным выражением. Как вклинить, например, выражение "V(2) + V(3)" (Корень из 2-х + корень из 3-х) в алгоритм сортировочной станции, это выражение не вычисляется.
Просто игнорировать сортировочная станция его не может, так как потом может появится ещё один корень из 3-х и его уже нужно будет считать вместе с предыдущим V(3).
Может быть более сложное выражение, вроде того, что на пике, нужно из начального 3-х этажного корня получить упрощённый.
хороший ты парень
И желательно несколько, что бы не сидеть на одной вечность в случае чего, а решить например 2 из 10, и вроде как и не совсем отбитый.
Если что, то заача с иксом:
Дано число на ввод например 5, нужно на выходе сделать вот такую хуйню:
|
|
|
|
| *
В общем решил вкатиться в PHP. И посему ищу себе для этого дела наставника\преподавателя который обьяснит мне что к чему и куда идти. Мои навыки довольно плачевны и опыт работы с PHP наверное чуть больше 10 чсасов.
Моя конечная цель - написать полноценный блог.
Написать магазин. Написать форум.
Если кто-то из местных заинтересован, пожалуйста отзовитесь.
За работу плачу деньгами. Связь будем держать по скайпу или RC. Для наставничества есть TeamViever. Если кто-то заинтересован - отпишитесь пожалуйста.
Почему бы тебе не посмотреть видеокурсы "Специалист"
бесплатно без смс с торрентов? Они как раз там в процессе пишут бложек вроде и интернет-магазин примитивный.
<symbol id="svg-5-star" viewBox="0 0 5120 1024">
<path d="M0,1v1024h1024V1H0z M982.029,44.....
в таком виде, добавил их в футер, почему отображается только на главном домене и на поддоменах без параметров в адрессе? (Только на site.com, *.site.com и соответственно не отображаются уже если site.com/index.php или site.com/?blabla=x)
http://acm.timus.ru/problemset.aspx?space=1&page=all&skipac=False&sort=difficulty и по порядку пошел решать.
1. http://ideone.com/VgrS51
2. http://ideone.com/XS106Q
Завтра продолжу, спасибо за сайт. Вторую понравилось решать, вспомнил пару функций и погуглил.
Вторая неверно. Там надо в обратном порядке корни выводить. С последнего к первому.
Прошел учебник в ОП-посте, очень понятный и оформлен круто, жаль что там мало. Спасибо тому кто это сделал. Перешел к задаче с абитуриентами, возник вопрос какую sql-api мне юзать? mysql, говорят, устарел и к применению не рекомендуется.
Остановился на mysqli, он как то проще выглядит. Чет я немного подохуел с резкого скачка сложности между уроками ОП-поста и документацией sql-api. Но в целом норм.
Я тоже в ожидании
https://github.com/TheSidSpears/Students/commit/313174bec98cf7ecfb774ffaebe25e30aef6b36d
Как правильно сделать переменную глобальной?
Если так, то Enchant выводится только в теле цикла.
global $items_userdata;
while( $items_userdata = mysqli_fetch_assoc($item) ){
...
}
echo $items_userdata['Enchant'];
Пиши обсудим, чего да, как.
Говорят, наставничество хороший способ держать себя в форме
phpwoZ4ambatANUShmam@:VailPUNCTUMco'Eim
>Редирект это взаимодейсвтие с браузером пользователя, это интерфейс.
Я не знал об этом. Хоть это и логично, я не смотрел на это с такой стороны. Спасибо.
https://github.com/codedokode/pasta/blob/master/student-list.md#Постраничная-навигация
>Можно сделать удобный класс для расчета числа страниц и формирования ссылок на переход на нужную страницу. В конструктор мы передаем общее число записей, число записей на странице, шаблон для ссылки, после чего может генерировать ссылки для перехода:
>$pager = new Pager($totalPages, $recordsPerPage, 'index.php?page={page}');
А обязательно шаблон для ссылки передавать? Ведь можно в самом шаблоне писать <a href="?page=<?= $page ?>">, и ссылка будет перенаправлять на текущую страницу + запрос с гетом.
Какой пиздец.
Аноны, расскажите какой верх мечтаний у пхп погромиста? 99% вакансий это гавностудии, что поддерживают интернет магазины с женским бельем и штопают разовые сайты-визитки.
Завтра ищешь в интернете книжку Джанед Вайленд "PHP5 для чайников" - полное руководство, похуй если ничего не поймешь. Затем идешь на http://php.net/manual/ru/ и изучаешь стандартную библиотеку от корки до корки. Потом зубришь, именно, сука, вызубриваешь конвенцию по написанию питоньего кода - PSR-2, чтобы от зубов отскакивало. Когда напишешь свою первую имиджборду, по пути изучив верстку на html+css, скачиваешь и изучаешь любой асинхронный вебсервер, рекомендую nginx. Как переделаешь имиджборду, чтобы выдавала по крайней мере 5 тысяч запросов в секунду, можешь идти дальше - тебя ждет увлекательный мир фриланса. CRM'ки, стартапы, сверхбыстрые HTML5 браузерные игры, MySQL. Отсос хиккующих выблядков / просто неудачников типа рейфага или сисярп/джава-хуесосов, которые сосут хуй по жизни не заставит себя ждать и уже через пол года ты будешь получать такие суммы, что любая баба будет теч при одном упоминании твоей зарплаты.
Переделал вторую и вот пара последующих.
2. http://ideone.com/qFJOX5
3. http://ideone.com/SA4FYT
4. http://ideone.com/Of9mKI
5. http://ideone.com/u8Knhq
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
PSR-1: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
Обе ссылки ведут на 404. ОП. Обнови пожалуйста!
расскажи нахуя программисту искать вакансии только в родном городе/стране?
тебя забанили на upwork?
не умеешь в английский? пиздуй вон из профессии
даже это не беда!
hh.ru яндекс.работа | grep поргомист | grep удаленка
...
PROFIT
Работать в Facebook конечно же! И коммитить в ядро HHVM за деньги, но это уже не пхп.
Можешь пойти и автоматизировать производство разовых сайтов-визиток, и хуяк - у тебя компания с оборотом 203.52 млн долларов, например: https://en.wikipedia.org/w/index.php?oldid=729054498
Composer де-факто стандарт. Либо качать архив с исходниками.
>sompfony
Symfony
>>796470
Там автотестов (когда твоё решение проверяется на сайте) нет что ли? Или решения на PHP не поддерживаются сайтом?
Попробуй leetcode ещё. Там PHP нет, я на JS решаю, но разница в задачках на алгоритмы небольшая.
>>796357
Да никак, если это твой проект и ты пишешь всё с нуля, а не за кем-то говно чистишь, то лучше перепроектируй с нуля так, чтобы глобальные переменные вообще не использовались. И возьмись за PDO.
Если интересно, то про глобальные состояния ОП писал в пасте про DI.
>>795984
У ОПа в задании: https://github.com/codedokode/pasta/blob/master/student-list.md
всё расписано. Перед тем, как задавать вопрос по студентам, убедись, что в пасте нет ответа. Я так когда-то тоже с багом PDO::FETCH_CLASS сглупил, хотя в пасте всё было написано.
>>796473
Ну предоставь сразу ссылки на рабочие версии (пусть и на англ, раз других нет), внесёшь вклад в общее дело.
Такое даже стыдно наверное показывать должно быть, но ничего, придется через этот стыд пройти.
http://ideone.com/GF79ti
Вангую что это нифига не правильное ООП. Хз что пытался изобразить. Разгромите, кому не лень читать этот говнокод, меня в пух и прах.
В общем я пытался сделать так, что бы животные друг с другом воздействовали через "мир", ведь они что бы видеть друг друга, должны как бы смотреть вокруг себя, ну вы поняли. А делать так что бы животные смотрели на всех других животных перебирая массивы - как-то НЕРЕАЛИСТИЧНО ЧТО ЛИ Поэтому попытался вот такое вот реализовать. Ну а дальше весь этот бред оттуда и вытекает.
научись в vagrant, или хотя бы nginx конфигурять, выброси денвер.
все зависимости ставь через composer
Чтоб было.
Я по этой причине никак за бутсрап не возмусь - разгребать кучи говн ради двух кнопочек и трех талбиц.
В голос, какое ты там говно разгребать собрался? Подключить бутстрап: прописать две ссылки - на стиль бутстрапа и жквери.
Такой же вопрос опу теперь по видео. С превьюшки я думаю еще допустимо хранить в корне сервера, но куда видео то ложить, если папка с загрузками выше корня сервера.
>Некоторые пытаются возложить на объект Pager лишние функции, например чтение параметров поиска из $_GET или подсчет числа записей в базе.
Значит этим должен заниматься контроллер?
$records = $studentGataway->getAllStudents();
$pager = new Pager($records, $currentPage = $this->getQuery('page'), $recordsPerPage = 10);
...
У меня getQuery($query) вбросит исключение если запроса не будет существовать, но ведь этого запроса может и не быть. Например, если мы только открываем страницу, то запроса о номере страницы быть не должно, и по стандарту должны выводиться записи с первой страницы. Я не правильно написал метод getQuery и не понимаю когда должны вбрасываться исключения?
К примеру, я пишу файлообменник. Там 3 страницы, проще будет сделать один контроллер, но с другой стороны было бы логичней под одну страничку один контроллер, вообще не понятно
Не люблю, когда куча говна, которое не используется никак.
Вот часть файла, которая идет с бутстрапом.
Вся эта лапша вида .style-1, .style-2, style-3{} - какое же говно говняное и говнистое.
Ради пары колонок, нескольких таблиц и кнопок держать всю эту парашу ебааааную? Чтобы просто былО?
Приходится, потому что потом можно взять и что-то ещё использовать, но бесит такое.
>>797241 | Задача про номера телефонов (+7 меня смущает), А не проще вкаорячить в htaccess Deny from All, задачи по регуляркам >>783071 ,
>>797242| регулярка для номеров >>785910 , Как правильно проводить валидацию, лиличка
--------------
>>797127
Каждой странице соответствует одно действие (экшен). Иногда на каждое действие делается свой контроллер, но обычно действия из одного раздела сайта группируются вместе в один контроллер. Ну например список новостей и просмотр новости можно сгруппировать в один контроллер новостей.
Если ты используешь микрофреймворк слим то все контроллеры - это функции в index.php
>>797129
В теории бутстрап состоит из модулей на LESS или SASS. Ты можешь скомпилировать только нужные тебе модули.
Более того, там есть веб-конфигуратор: http://getbootstrap.com/customize/
Ты можешь сделать свою сборку только с нужными тебе вещами (всем советую делать именно так).
Ты в принципе не обязан использовать бустрап. Можно верстку делать самому. Но бутстрап экономит время + позволяет тебе его изучить. Его довольно части используют для всяких внутренних страниц (админка) чтобы не возиться с стилизацией таблиц и форм.
>>797150
Ты пишешь как будто это что-то плохое. Я наоборот считаю что плохо не уметь верстать. Ленивые и некомпетентные разработчики любят придумывать предлгоги чтобы что-нибудь не изучать.
>>797241 | Задача про номера телефонов (+7 меня смущает), А не проще вкаорячить в htaccess Deny from All, задачи по регуляркам >>783071 ,
>>797242| регулярка для номеров >>785910 , Как правильно проводить валидацию, лиличка
--------------
>>797127
Каждой странице соответствует одно действие (экшен). Иногда на каждое действие делается свой контроллер, но обычно действия из одного раздела сайта группируются вместе в один контроллер. Ну например список новостей и просмотр новости можно сгруппировать в один контроллер новостей.
Если ты используешь микрофреймворк слим то все контроллеры - это функции в index.php
>>797129
В теории бутстрап состоит из модулей на LESS или SASS. Ты можешь скомпилировать только нужные тебе модули.
Более того, там есть веб-конфигуратор: http://getbootstrap.com/customize/
Ты можешь сделать свою сборку только с нужными тебе вещами (всем советую делать именно так).
Ты в принципе не обязан использовать бустрап. Можно верстку делать самому. Но бутстрап экономит время + позволяет тебе его изучить. Его довольно части используют для всяких внутренних страниц (админка) чтобы не возиться с стилизацией таблиц и форм.
>>797150
Ты пишешь как будто это что-то плохое. Я наоборот считаю что плохо не уметь верстать. Ленивые и некомпетентные разработчики любят придумывать предлгоги чтобы что-нибудь не изучать.
>>Некоторые пытаются возложить на объект Pager лишние функции, например чтение параметров поиска из $_GET или подсчет числа записей в базе.
> Значит этим должен заниматься контроллер?
Да. Надо уметь писать более универсальнй код. Не надо писать функции которые берут данные из GET - лучше писать функцию которая получает на вход аргументы.
> $pager = new Pager($records, $currentPage = $this->getQuery('page'), $recordsPerPage = 10);
Не надо так писать. $currentPage = $this->getQuery('page') это отдельная команда которая должна быть на отдельной строке.
> У меня getQuery($query) вбросит исключение если запроса не будет существовать
Тебе нужна другая функция которая не выбросит исключение, а вернет 1.
> Я не правильно написал метод getQuery и не понимаю когда должны вбрасываться исключения?
Скорее всего неправильно. Все GET параметры приходят от пользователя и могут отсутствовать.
>>796963
Либо держать файлы в публичной папке либо настроить сервер на отдачу их из непубличной папки. Например есть расширение Апач x-sendfile которое позволяет php-скрипту выдать заголовок, апач его перехватит и начнет отдавать пользователю файл. Также можно сделать переназначение УРЛ через mod_rewrite
>>796942
"лень разбираться" не приветствуется в нашем треде и не считается уважительной причиной. Есть мануал, прочитай, в идеале - английскую официальную версию.
>>796940
У тебя должна быть система публикации скриптов. В простейшем случае - просто скрипт копирующий файлы в публичную папку, в сложном случае - система, склеивающая и минифицирующая файлы. Просто композера недостаточно.
Запускать эту систему можно автоматически - композер позволяет задать скрипт который вызывается после установки или обновления зависимостей.
Ну либо есть еще вариант не использовать композер и руками загрузить нужные файлы.
>>Некоторые пытаются возложить на объект Pager лишние функции, например чтение параметров поиска из $_GET или подсчет числа записей в базе.
> Значит этим должен заниматься контроллер?
Да. Надо уметь писать более универсальнй код. Не надо писать функции которые берут данные из GET - лучше писать функцию которая получает на вход аргументы.
> $pager = new Pager($records, $currentPage = $this->getQuery('page'), $recordsPerPage = 10);
Не надо так писать. $currentPage = $this->getQuery('page') это отдельная команда которая должна быть на отдельной строке.
> У меня getQuery($query) вбросит исключение если запроса не будет существовать
Тебе нужна другая функция которая не выбросит исключение, а вернет 1.
> Я не правильно написал метод getQuery и не понимаю когда должны вбрасываться исключения?
Скорее всего неправильно. Все GET параметры приходят от пользователя и могут отсутствовать.
>>796963
Либо держать файлы в публичной папке либо настроить сервер на отдачу их из непубличной папки. Например есть расширение Апач x-sendfile которое позволяет php-скрипту выдать заголовок, апач его перехватит и начнет отдавать пользователю файл. Также можно сделать переназначение УРЛ через mod_rewrite
>>796942
"лень разбираться" не приветствуется в нашем треде и не считается уважительной причиной. Есть мануал, прочитай, в идеале - английскую официальную версию.
>>796940
У тебя должна быть система публикации скриптов. В простейшем случае - просто скрипт копирующий файлы в публичную папку, в сложном случае - система, склеивающая и минифицирующая файлы. Просто композера недостаточно.
Запускать эту систему можно автоматически - композер позволяет задать скрипт который вызывается после установки или обновления зависимостей.
Ну либо есть еще вариант не использовать композер и руками загрузить нужные файлы.
>Если ты используешь микрофреймворк слим то все контроллеры
нет, я решил сразу освоить нужный мне фреймворк самый популярный Laravel, хотя понимаю, что для такой задачи подойдет и простенький, но хочется убить два зайца сразу
> public function move (World $world) {
Вместо того чтобы передавать сюда World, удобнее передавать его в животное при создании либо при размещении на карте и сохранять в свойстве.
> if ($this->dead == false && $world->field[$this->x][$this->y] != $this->icon) {
Вот тут мышь занимается не своим делом. Она лезет во внутренности мира: $world->field[$this->x][$this->y]. Но разве это задача мыши - определять, кто где находится? Очевидно, это задача мира. мышь просто должна вызывать метод вроде "есть ли кто-то на этой клетке?".
Мир спроектирован неудачно. Как в твоей реализации получить объект-животное по координатам? Или список животных в определенном радиусе? Ты хранишь маловажную информацию (иконку) а важную (сам объект со всей информацией) не сохраняешь.
Также, у тебя очень плохо сделано хранение информации о расположении животных. Допустим я поменял у мыши координату x или y. Где гарантия что массив $world->field всегда отразит это изменение? У тебя информация о животных хранится сразу в 2 местах: в самом животном и в $world->field и появляется риск расхождения, в животном будет одна координата, а на карте оно будет в другом месте.
Более того, у тебя иконка животного тоже хранится в 2 местах - в world и underworld и тут точно такая же проблема синхронизации.
От этих проблем проще всего избавиться, храня информацию только в одном месте без дубликатов.
И вообще, у тебя слишком много публичных полей. Надо закрывать к ним доступ и разрешать только делать ограниченный набор действий через методы. Это называется инкапсуляция. Сделай все поля непубличными. Плюс, не выдавай массив field наружу, а сделай методы вроде "получить список животных в радиусе вокруг точки".
То есть для начала придумай какие у тебя классы, за что они отвечают и какие у них будут публичные методы. А потом уже пиши код.
Функцию move надо разбивать на подфункции, а не писать код стеной.
> if (isset($world->field[$this->x][$this->y - 1]) and ($world->field[$this->x][$this->y - 1] == $world->filler)) {
> $directions[] = array($this->x, $this->y - 1);
> }
Это копипаста. не копипасть.
Алгоритм оценки ходов, который я рекомендовал, не рализован.
> public function move (World $world) {
Вместо того чтобы передавать сюда World, удобнее передавать его в животное при создании либо при размещении на карте и сохранять в свойстве.
> if ($this->dead == false && $world->field[$this->x][$this->y] != $this->icon) {
Вот тут мышь занимается не своим делом. Она лезет во внутренности мира: $world->field[$this->x][$this->y]. Но разве это задача мыши - определять, кто где находится? Очевидно, это задача мира. мышь просто должна вызывать метод вроде "есть ли кто-то на этой клетке?".
Мир спроектирован неудачно. Как в твоей реализации получить объект-животное по координатам? Или список животных в определенном радиусе? Ты хранишь маловажную информацию (иконку) а важную (сам объект со всей информацией) не сохраняешь.
Также, у тебя очень плохо сделано хранение информации о расположении животных. Допустим я поменял у мыши координату x или y. Где гарантия что массив $world->field всегда отразит это изменение? У тебя информация о животных хранится сразу в 2 местах: в самом животном и в $world->field и появляется риск расхождения, в животном будет одна координата, а на карте оно будет в другом месте.
Более того, у тебя иконка животного тоже хранится в 2 местах - в world и underworld и тут точно такая же проблема синхронизации.
От этих проблем проще всего избавиться, храня информацию только в одном месте без дубликатов.
И вообще, у тебя слишком много публичных полей. Надо закрывать к ним доступ и разрешать только делать ограниченный набор действий через методы. Это называется инкапсуляция. Сделай все поля непубличными. Плюс, не выдавай массив field наружу, а сделай методы вроде "получить список животных в радиусе вокруг точки".
То есть для начала придумай какие у тебя классы, за что они отвечают и какие у них будут публичные методы. А потом уже пиши код.
Функцию move надо разбивать на подфункции, а не писать код стеной.
> if (isset($world->field[$this->x][$this->y - 1]) and ($world->field[$this->x][$this->y - 1] == $world->filler)) {
> $directions[] = array($this->x, $this->y - 1);
> }
Это копипаста. не копипасть.
Алгоритм оценки ходов, который я рекомендовал, не рализован.
Имей в виду что в ларавели много сомнительных вещей - например злоупотребление статическими методами и глобальными функциями, это первое что бросается в глаза. Как у них сделана работа с базой данных. мне тоже не нравится.
может быть, но согласись, многие так же думают про php, в плане сомнительности, но ничего живет и развивается же как-то, учу из-за того, что самый популярный, а значит больше шансов найти работу
Я не совсем еще не дошел до этого, но вроде как там используется ActiveRecord или Eloquent, мол создаешь модель и это таблица в бд, создаешь обьект и создается строка в той таблице, свойства обьекта - атрибуты таблицы.
Вроде как очень удобно
Спасибо. Кстати у меня есть аж 2 скрипта для контроля моих же паст:
1) проверяльщик ссылок в пастах: https://github.com/codedokode/pasta-link-checker
2) пока не опубликованный проверяльщик грамматики - ищет опечатки. По сути это скрипт-обертка вокруг hunspell
Новые ссылки:
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
Их подход приводит к тому что один класс занимается несколькими вещами - хранит информацию о объекте, работой с базой данных, валидацией. Это известный недостаток active record и он здорово портит код в больших приложениях, так как модели сильно раздуваются.
Но в общем, я думаю, изучить фреймворк будет полезно.
>>796652
> function inclineWord($number, $word1, $word2, $word5) {
Последний if не нужен.
> if ($number == 0)
> return "ноль";
надо ставить фигурные скобки.
> array_push($temp,$spelling[$hundreds]);
Удобнее писать $temp[] = ...
Кстати название $temp не годится, оно ничего не значит.
> $text = preg_replace("/ноль/u", "", $text);
> $text = preg_replace("/ +/u", " ", $text);
Это кривые костыли и они затрудняют понимание и поддержку кода. Если у тебя ноль сотен, не надо просто класть такое слово в массив.
> array_push($temp," (".$number.") ".inclineWord($ones,"рубль","рубля","рублей"));
> } else {
> array_push($temp," (".$number.") рублей");
Эту строчку не надо копировать 2 раза, достаточно написать один раз.
>>796470
Здесь лучше разбивать preg_split с флагом PREG_SPLIT_NO_EMPTY так, что сразу получится массив только из чисел.
Надо ставить фигурные скобки. Вместо копипастоы ифов лучше сделать массив с цифрами и словами и циклом искать совпадения в нем.
Не читал условия, но разбивать лучше preg_split (чтобы поддерживалось любое число пробелов), а для перемножения любого числа элементов есть готовая функция array_prod по моему
Их подход приводит к тому что один класс занимается несколькими вещами - хранит информацию о объекте, работой с базой данных, валидацией. Это известный недостаток active record и он здорово портит код в больших приложениях, так как модели сильно раздуваются.
Но в общем, я думаю, изучить фреймворк будет полезно.
>>796652
> function inclineWord($number, $word1, $word2, $word5) {
Последний if не нужен.
> if ($number == 0)
> return "ноль";
надо ставить фигурные скобки.
> array_push($temp,$spelling[$hundreds]);
Удобнее писать $temp[] = ...
Кстати название $temp не годится, оно ничего не значит.
> $text = preg_replace("/ноль/u", "", $text);
> $text = preg_replace("/ +/u", " ", $text);
Это кривые костыли и они затрудняют понимание и поддержку кода. Если у тебя ноль сотен, не надо просто класть такое слово в массив.
> array_push($temp," (".$number.") ".inclineWord($ones,"рубль","рубля","рублей"));
> } else {
> array_push($temp," (".$number.") рублей");
Эту строчку не надо копировать 2 раза, достаточно написать один раз.
>>796470
Здесь лучше разбивать preg_split с флагом PREG_SPLIT_NO_EMPTY так, что сразу получится массив только из чисел.
Надо ставить фигурные скобки. Вместо копипастоы ифов лучше сделать массив с цифрами и словами и циклом искать совпадения в нем.
Не читал условия, но разбивать лучше preg_split (чтобы поддерживалось любое число пробелов), а для перемножения любого числа элементов есть готовая функция array_prod по моему
Модель это такая вещь в себе, которая управляет данными (списоком студентов) и никак не взаимодействует с внешним миром. И она не знает откуда ей приходят команыд и куда уходят ответы. Потому за редиректы она никак отвечать не может. Она получает все данные через аругменты при вызове функций.
> А обязательно шаблон для ссылки передавать?
Нет. Не передавать даже будет правильнее, так как задача пейджера считать номера страниц, а не генерировать ссылки.
> Ведь можно в самом шаблоне писать <a href="?page=<?= $page ?>">, и ссылка будет перенаправлять на текущую страницу + запрос с гетом.
Можно но лучше вынести генерацию ссылки в отдельную функцию, тем более что там нужно добавлять параметры для сортировки и поиска. И для первой страницы параметр page не требуется.
> https://github.com/TheSidSpears/Students/blob/master/students.sql#L31
> `hash` text NOT NULL,
Тут лучше подойдет varchar
https://github.com/TheSidSpears/Students/blob/master/router.json
Вот тут я не уверен что в роутере должен указываться вью. зачем? Ты планируешь один вью с несколькими контроллерами использовать? Это вряд ли получится, так как вью привязан к своему контроллеру и не совместим с другими. И даже если он совместим, при правке это легко сломать. Ангалогично мне кажется нет смысла в роутере указвать заголовок страницы (если только ты не используешь это еще например для меню - и то, наверно выгоднее как-то в контроллере это хранить).
https://github.com/TheSidSpears/Students/blob/master/public/.htaccess#L5
не очень понятно зачем тут перенаправление всех УРЛ на 503.php. Коментарий бы добавил.
https://github.com/TheSidSpears/Students/blob/master/public/errors.log
Почему лог ошибок в публичной папке? и кстати зачем вообще его было делать, если в php уже есть готовый лог?
https://github.com/TheSidSpears/Students/blob/master/public/index.php
тут странный код: ты создаешь объект и ничего с ним не делаешь:
> $frontController=new FrontController($container);
Задача конструктора - инициализировать объект, а не обрабатывать запрос.
https://github.com/TheSidSpears/Students/blob/master/app/bootstrap.php#L12
Ты используешь относительный путь который зависит например от теущего каталога. надо использовтаь абсолютный путь например с использованием __DIR__ или метода преобразования относительного пути в абсолютный.
https://github.com/TheSidSpears/Students/blob/master/app/bootstrap.php#L19
Автозагрузку можно было бы через композер сделать. И тут та же проблема с относительными путями.
https://github.com/TheSidSpears/Students/blob/master/app/container.php#L7
> return JSONLoader::config();
> return JSONLoader::router();
Статические методы это не ООП-подход. Не вижу причин тут использовать статический вызов. Также не вижу где написан путь к конфигу.
Более того, ты возвращаешь массив непонятной структуры. Не лучше ли возвращать объект с методами для получения данных?
https://github.com/TheSidSpears/Students/blob/master/app/controllers/FrontController.php#L15
> public $isAuthorized=false;
зачем тут это публичное свойство? Контроллер это не сервис чтобы другие могли к нему обращаться. У тебя есть сервис авторизации для этого. Не надо дублировать его функции.
https://github.com/TheSidSpears/Students/blob/master/app/classes/Router.php
Роутер странный. Он называется роутер и при этом он не использует даже файл с конфигом. Что он вообще делает? По моему ты не смог изолировать функционал роутинга в одном классе и он у тебя вытек в front controller.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/FrontController.php#L33
Это функционал роутера.
> https://github.com/TheSidSpears/Students/blob/master/router.json
> "controller": "Main",
Плохая идея писать имя класса не полностью. Если я захочу поискать где используется класс MainController, я не найду это место.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php#L96
> $this->viewData['students']=$this->c['table']->getStudents($this->sortBy,$this->orderBy,$this->limit,$this->offset,$this->find);
Слишком сложное выражение, плохо читается. Вместо $this->c['table'] лучше писать $this->studentTDG или $studentTDG.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php
Контроллер переусложнен. По моему он весь пишется в виде одного местода на 15-20 строк, а ты зачем-то надобавлял тут свойств и методов. У тебя как-то все выглядит переусложненно, попробуй упростить и избавиться от лишнего.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php#L31
> if ($isAuthorized) {
> $user=$this->c['auth']->getUser();
> $this->user=$this->filterUserData($user);
зачем тут filterUserData? Не понимаю.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/EditController.php
https://github.com/TheSidSpears/Students/blob/master/app/controllers/RegisterController.php
Не очень удачное решение. Вместо наследования тут проще сделать один контроллер и поставить пару ифов. такой код читать будет проще, чем постоянно переключаться между 2 классами.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/RegisterController.php#L29
> setcookie('hash',$student->hash,time()+360012365,'/',null,false,true);
Странно, у тебя есть класс отвечающий за авторизацию, но куку почему-то ты ставишь в контроллере.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php#L73
> protected function fillStudent(Student $student){
Непонятно что тут делает цикл ибо он ничего не меняет в массиве.
Опять же, редактирование переусложнено. Надо радикально упрощать код, убрать наследование, убрать код из конструктора. Свойства во многих случаях проще заменить на обычные переменные.
Метод showView тоже назван неудачно. Логчинее назвать его "обработать запрос" и сделать абстрактным в базовом контроллере.
https://github.com/TheSidSpears/Students/blob/master/app/classes/Authorization.php#L12
> function __construct($container){
перечитай урок про DI. Это service locator и это плохая вещь.
Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
https://github.com/TheSidSpears/Students/blob/master/app/classes/JSONLoader.php
Тут зачем-то захардкожены имена файлов.
> $array=file_get_contents($filename,FILE_IGNORE_NEW_LINES);
Имя переменной не соответствует тому что она хранит
> LIMIT :y OFFSET :x");
Неудачные названия плейсхолдеров
> $rows = $this->db->prepare("SELECT FROM `students` ORDER BY $sortBy $orderBy LIMIT :y OFFSET :x");
> if (isset($search)) {
> $rows = $this->db->prepare("SELECT FROM `students` WHERE CONCAT(`name`,' ',`sname`,' ',`group_num`,' ',`points`,' ',`gender`,' ',`email`,' ',`b_year`,' ',`is_resident`) LIKE :search ORDER BY $sortBy $orderBy LIMIT :x,:y");
Получается первый prepare был сделан зря? зачем тогда его делать?
В student->addInfo есть проблема. У тебя нет фильтрации по разрешенными полям и пользователь может менять любые свойства студента в том числе те, которых нет в форме. ну например что если мы добавим колонку is_admin - пользователь сможет передать $POST['is_admin'] = 1 при редактирвоании. И кстати об этом было написано в моем уроке.
> https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L98
> foreach($mask['values'] as $value){
> if($s->$field=$value){
in_array()
> 'regexp'=>"/^([а-яa-z][ ']*)+$/iu",
Где буква ё? Где дефис для фамилий?
https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L66
> function __construct(Student $s, $container, $id=NULL){
Почему ты пишешь код валидации в конструкторе? И почему передаешь контейнер? Почитай про DI.
https://github.com/TheSidSpears/Students/blob/master/app/classes/ViewHelper.php
тут слишком много всего понамешано. Еще и контейнер.
В общем:
1) упрощай код
2) перечитай урок по DI
3) перечитай комментарии к задаче
> https://github.com/TheSidSpears/Students/blob/master/students.sql#L31
> `hash` text NOT NULL,
Тут лучше подойдет varchar
https://github.com/TheSidSpears/Students/blob/master/router.json
Вот тут я не уверен что в роутере должен указываться вью. зачем? Ты планируешь один вью с несколькими контроллерами использовать? Это вряд ли получится, так как вью привязан к своему контроллеру и не совместим с другими. И даже если он совместим, при правке это легко сломать. Ангалогично мне кажется нет смысла в роутере указвать заголовок страницы (если только ты не используешь это еще например для меню - и то, наверно выгоднее как-то в контроллере это хранить).
https://github.com/TheSidSpears/Students/blob/master/public/.htaccess#L5
не очень понятно зачем тут перенаправление всех УРЛ на 503.php. Коментарий бы добавил.
https://github.com/TheSidSpears/Students/blob/master/public/errors.log
Почему лог ошибок в публичной папке? и кстати зачем вообще его было делать, если в php уже есть готовый лог?
https://github.com/TheSidSpears/Students/blob/master/public/index.php
тут странный код: ты создаешь объект и ничего с ним не делаешь:
> $frontController=new FrontController($container);
Задача конструктора - инициализировать объект, а не обрабатывать запрос.
https://github.com/TheSidSpears/Students/blob/master/app/bootstrap.php#L12
Ты используешь относительный путь который зависит например от теущего каталога. надо использовтаь абсолютный путь например с использованием __DIR__ или метода преобразования относительного пути в абсолютный.
https://github.com/TheSidSpears/Students/blob/master/app/bootstrap.php#L19
Автозагрузку можно было бы через композер сделать. И тут та же проблема с относительными путями.
https://github.com/TheSidSpears/Students/blob/master/app/container.php#L7
> return JSONLoader::config();
> return JSONLoader::router();
Статические методы это не ООП-подход. Не вижу причин тут использовать статический вызов. Также не вижу где написан путь к конфигу.
Более того, ты возвращаешь массив непонятной структуры. Не лучше ли возвращать объект с методами для получения данных?
https://github.com/TheSidSpears/Students/blob/master/app/controllers/FrontController.php#L15
> public $isAuthorized=false;
зачем тут это публичное свойство? Контроллер это не сервис чтобы другие могли к нему обращаться. У тебя есть сервис авторизации для этого. Не надо дублировать его функции.
https://github.com/TheSidSpears/Students/blob/master/app/classes/Router.php
Роутер странный. Он называется роутер и при этом он не использует даже файл с конфигом. Что он вообще делает? По моему ты не смог изолировать функционал роутинга в одном классе и он у тебя вытек в front controller.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/FrontController.php#L33
Это функционал роутера.
> https://github.com/TheSidSpears/Students/blob/master/router.json
> "controller": "Main",
Плохая идея писать имя класса не полностью. Если я захочу поискать где используется класс MainController, я не найду это место.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php#L96
> $this->viewData['students']=$this->c['table']->getStudents($this->sortBy,$this->orderBy,$this->limit,$this->offset,$this->find);
Слишком сложное выражение, плохо читается. Вместо $this->c['table'] лучше писать $this->studentTDG или $studentTDG.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php
Контроллер переусложнен. По моему он весь пишется в виде одного местода на 15-20 строк, а ты зачем-то надобавлял тут свойств и методов. У тебя как-то все выглядит переусложненно, попробуй упростить и избавиться от лишнего.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php#L31
> if ($isAuthorized) {
> $user=$this->c['auth']->getUser();
> $this->user=$this->filterUserData($user);
зачем тут filterUserData? Не понимаю.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/EditController.php
https://github.com/TheSidSpears/Students/blob/master/app/controllers/RegisterController.php
Не очень удачное решение. Вместо наследования тут проще сделать один контроллер и поставить пару ифов. такой код читать будет проще, чем постоянно переключаться между 2 классами.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/RegisterController.php#L29
> setcookie('hash',$student->hash,time()+360012365,'/',null,false,true);
Странно, у тебя есть класс отвечающий за авторизацию, но куку почему-то ты ставишь в контроллере.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php#L73
> protected function fillStudent(Student $student){
Непонятно что тут делает цикл ибо он ничего не меняет в массиве.
Опять же, редактирование переусложнено. Надо радикально упрощать код, убрать наследование, убрать код из конструктора. Свойства во многих случаях проще заменить на обычные переменные.
Метод showView тоже назван неудачно. Логчинее назвать его "обработать запрос" и сделать абстрактным в базовом контроллере.
https://github.com/TheSidSpears/Students/blob/master/app/classes/Authorization.php#L12
> function __construct($container){
перечитай урок про DI. Это service locator и это плохая вещь.
Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
https://github.com/TheSidSpears/Students/blob/master/app/classes/JSONLoader.php
Тут зачем-то захардкожены имена файлов.
> $array=file_get_contents($filename,FILE_IGNORE_NEW_LINES);
Имя переменной не соответствует тому что она хранит
> LIMIT :y OFFSET :x");
Неудачные названия плейсхолдеров
> $rows = $this->db->prepare("SELECT FROM `students` ORDER BY $sortBy $orderBy LIMIT :y OFFSET :x");
> if (isset($search)) {
> $rows = $this->db->prepare("SELECT FROM `students` WHERE CONCAT(`name`,' ',`sname`,' ',`group_num`,' ',`points`,' ',`gender`,' ',`email`,' ',`b_year`,' ',`is_resident`) LIKE :search ORDER BY $sortBy $orderBy LIMIT :x,:y");
Получается первый prepare был сделан зря? зачем тогда его делать?
В student->addInfo есть проблема. У тебя нет фильтрации по разрешенными полям и пользователь может менять любые свойства студента в том числе те, которых нет в форме. ну например что если мы добавим колонку is_admin - пользователь сможет передать $POST['is_admin'] = 1 при редактирвоании. И кстати об этом было написано в моем уроке.
> https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L98
> foreach($mask['values'] as $value){
> if($s->$field=$value){
in_array()
> 'regexp'=>"/^([а-яa-z][ ']*)+$/iu",
Где буква ё? Где дефис для фамилий?
https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L66
> function __construct(Student $s, $container, $id=NULL){
Почему ты пишешь код валидации в конструкторе? И почему передаешь контейнер? Почитай про DI.
https://github.com/TheSidSpears/Students/blob/master/app/classes/ViewHelper.php
тут слишком много всего понамешано. Еще и контейнер.
В общем:
1) упрощай код
2) перечитай урок по DI
3) перечитай комментарии к задаче
Значит у тебя неправильно стоит ссылка. Вот урок есть по теме https://github.com/codedokode/pasta/blob/master/network/urls.md
>>795608
Задачи учебника в ОП посте не годятся?
>>795451
Он же для интернет-магазинов.
>>795352
Так да, я это и писал, если мы разрешаем иррациональные числа то мы вынуждены оперировать выражениями произвольной сложности так как упростить их невозможно.
Потому варианты такие:
- запретить брать корень вообще
- запретить брать корень если результат нерациональный
- разрешить брать корень, но округлять результат с потерей точности до десятичной дроби
>>795321
Ну главное чтобы ты второй раз ту же ошибку не повторял. А вообще, интересная статистика.
>>795060
phpquery?
>>795007
Откуда он про него должен был узнать? Это именно проблема с экосистемой приложений что непонятно какое из них лучше и какое содержит трояны.
Кстати сейчас та же ерунда с андроидом, заливают трояны чтобы они в поиске находились по именам популярных приложений вроде призмы.
>>794978
Превьюшки можно перенести в публичную папку, да и загружаемые файлы в общем тоже. Либо настраивать их скачивание: через mod_rewrite либо через x-sendfile.
Проще наверно перенести в публичную папку.
>>794934
Вообще нет, смешной сайт на народе для тех кто ничего не знает.
Про архитектуру языка советую официальный мануал с php.net
По взаимодействию с БД изучай PDO.
Значит у тебя неправильно стоит ссылка. Вот урок есть по теме https://github.com/codedokode/pasta/blob/master/network/urls.md
>>795608
Задачи учебника в ОП посте не годятся?
>>795451
Он же для интернет-магазинов.
>>795352
Так да, я это и писал, если мы разрешаем иррациональные числа то мы вынуждены оперировать выражениями произвольной сложности так как упростить их невозможно.
Потому варианты такие:
- запретить брать корень вообще
- запретить брать корень если результат нерациональный
- разрешить брать корень, но округлять результат с потерей точности до десятичной дроби
>>795321
Ну главное чтобы ты второй раз ту же ошибку не повторял. А вообще, интересная статистика.
>>795060
phpquery?
>>795007
Откуда он про него должен был узнать? Это именно проблема с экосистемой приложений что непонятно какое из них лучше и какое содержит трояны.
Кстати сейчас та же ерунда с андроидом, заливают трояны чтобы они в поиске находились по именам популярных приложений вроде призмы.
>>794978
Превьюшки можно перенести в публичную папку, да и загружаемые файлы в общем тоже. Либо настраивать их скачивание: через mod_rewrite либо через x-sendfile.
Проще наверно перенести в публичную папку.
>>794934
Вообще нет, смешной сайт на народе для тех кто ничего не знает.
Про архитектуру языка советую официальный мануал с php.net
По взаимодействию с БД изучай PDO.
Ответил в старом треде: >>797241
С "а" или "но" ненадежно сделано - перед ним может быть не только запятая, но и например двоеточие или другой знак. Пробел не обязательно будет ровно один.
В остальном верно.
Тут то же самое замечание, в остальном верно.
в общем верно, хотя у тебя он не подсветит вторую опечатку в том же слове вроде тOпOр
>>794822
>>794808
тут выгоднее вытащить данные из базы и обработать на стороне php
>>794789
Именно такому учат в нашем треде кстати, включая тесты.
>>794471
Она плоха тем что при любом изменении в одной из таблиц запрос сломается. При изменении порядка полей будет еще хуже.
Так писать нельзя, это мина замедленного действия.
>>794418
Официальнй мануал, хоть это и не книга.
>>794384
Не знаю, может обратиться в техподдержку? Это ведь не официальный крон а веб-морда к нему. Также, плохая идея рассчитвать что скрипт будет вызван определенное число раз - а что если сервер перезагрузят?
Все, я ушел.
Ответил в старом треде: >>797241
С "а" или "но" ненадежно сделано - перед ним может быть не только запятая, но и например двоеточие или другой знак. Пробел не обязательно будет ровно один.
В остальном верно.
Тут то же самое замечание, в остальном верно.
в общем верно, хотя у тебя он не подсветит вторую опечатку в том же слове вроде тOпOр
>>794822
>>794808
тут выгоднее вытащить данные из базы и обработать на стороне php
>>794789
Именно такому учат в нашем треде кстати, включая тесты.
>>794471
Она плоха тем что при любом изменении в одной из таблиц запрос сломается. При изменении порядка полей будет еще хуже.
Так писать нельзя, это мина замедленного действия.
>>794418
Официальнй мануал, хоть это и не книга.
>>794384
Не знаю, может обратиться в техподдержку? Это ведь не официальный крон а веб-морда к нему. Также, плохая идея рассчитвать что скрипт будет вызван определенное число раз - а что если сервер перезагрузят?
Все, я ушел.
пожалеть себя
>> Я не правильно написал метод getQuery и не понимаю когда должны вбрасываться исключения?
>Скорее всего неправильно. Все GET параметры приходят от пользователя и могут отсутствовать.
Но ведь исключения нужны для программистов, которые могут неправильно написать запрос...
Поменять мышление: вместо "не могу" - "не хватает упорства". Затем распределить свое время на мелкие отрезки чтобы упорства хватало. Рим тоже не один день строился.
https://github.com/applejacky/arithmetic_expression_calculator
Всё по максимуму переведено на bc-функции, можно использовать большие числа. Токены из лексем определяются поточно (если я правильно понял "поточно"), с использованием стека, позволяющего учитывать предыдущий токен (чтобы отличать унарные операторы от бинарных).
За отображение точности/неточности отвечает тильда.
>>795255
> У меня идея такая:
> Затем мы делаем такой трюк: возводим $result в квадрат с помощью bcpow (без потерь точности). Сравниваем результат возведения (строку) с $a (строкой). Если они совпали ...
Не знаю, что бы я делал без этой подсказки, спасибо. Всё упиралось в то, что pow(1.4142135623731, 2) округляет результат до двойки.
>> Там precision у bcdiv 20, то есть он всегда дробную часть добивает нулями. Тогда нули убирать регулярками/фунциями для манипуляций со строками?
> У тебя по идее знаменатель и числитель целые ведь. Зачем что-то добивать?
Мне следовало весь контекст обсуждения запостить. Суть: bc-функции не умеют сами определять, с какой точностью после запятой отображать результат. Если не указывать scale (количество знаков после запятой), то по умолчанию bc-функции отображают только целую часть ответа. Если указать scale, к примеру 50, то в bc покажет именно 50 символов после запятой, не забывая добить результат нулями справа. Я счёл логичным написать мелкую обёртку, которая эти нули с конца будет удалять.
В результате SimpleFraction будет быстрее упрощать себя, так как числа меньше. (0.1 => 1/10, а без удаления нулей было бы 0.100...N => 100...N/100...N+1, где N - кол-во нулей).
>>792629
>Ну а НОК легко считается через НОД. Реализуй алгоритм Евклида
Нашёл функцию gmp_gcd. Взял её, так как моё решение будет медленнее.
>У тебя парсинг оказался разделен на 2 части: проверка синтаксиса и сам парсинг.
Сейчас объединил парсинг и валидацию. Это позволило вообще не использовать регулярки для валидации, но код, как это обычно происходит в моём случае, стал ещё запутанней.
>> str_pad("Выражение в инфиксной нотации", 61)
> Она не умеет считать русские буквы, имей в виду.
Я так понял, это справедливо для всех str_* функций без префикса mb? А как тогда выравнивать? Сделал sprintf'ом.
https://github.com/applejacky/arithmetic_expression_calculator
Всё по максимуму переведено на bc-функции, можно использовать большие числа. Токены из лексем определяются поточно (если я правильно понял "поточно"), с использованием стека, позволяющего учитывать предыдущий токен (чтобы отличать унарные операторы от бинарных).
За отображение точности/неточности отвечает тильда.
>>795255
> У меня идея такая:
> Затем мы делаем такой трюк: возводим $result в квадрат с помощью bcpow (без потерь точности). Сравниваем результат возведения (строку) с $a (строкой). Если они совпали ...
Не знаю, что бы я делал без этой подсказки, спасибо. Всё упиралось в то, что pow(1.4142135623731, 2) округляет результат до двойки.
>> Там precision у bcdiv 20, то есть он всегда дробную часть добивает нулями. Тогда нули убирать регулярками/фунциями для манипуляций со строками?
> У тебя по идее знаменатель и числитель целые ведь. Зачем что-то добивать?
Мне следовало весь контекст обсуждения запостить. Суть: bc-функции не умеют сами определять, с какой точностью после запятой отображать результат. Если не указывать scale (количество знаков после запятой), то по умолчанию bc-функции отображают только целую часть ответа. Если указать scale, к примеру 50, то в bc покажет именно 50 символов после запятой, не забывая добить результат нулями справа. Я счёл логичным написать мелкую обёртку, которая эти нули с конца будет удалять.
В результате SimpleFraction будет быстрее упрощать себя, так как числа меньше. (0.1 => 1/10, а без удаления нулей было бы 0.100...N => 100...N/100...N+1, где N - кол-во нулей).
>>792629
>Ну а НОК легко считается через НОД. Реализуй алгоритм Евклида
Нашёл функцию gmp_gcd. Взял её, так как моё решение будет медленнее.
>У тебя парсинг оказался разделен на 2 части: проверка синтаксиса и сам парсинг.
Сейчас объединил парсинг и валидацию. Это позволило вообще не использовать регулярки для валидации, но код, как это обычно происходит в моём случае, стал ещё запутанней.
>> str_pad("Выражение в инфиксной нотации", 61)
> Она не умеет считать русские буквы, имей в виду.
Я так понял, это справедливо для всех str_* функций без префикса mb? А как тогда выравнивать? Сделал sprintf'ом.
Symfony2
Но сам по себе он тебе ничего не даст. Symfony - просто инструмент, позволяющий реализовывать любые паттерны ООП. Вот они то тебе для большого проекта и нужны
Виндовая консоль не может отображать utf-8. Какие есть варианты?
- писать код в кодировке cp1251. Минус в том что код перестанет работать с utf8. То есть ради винды придется себя ограничивать. Под линуксом который по умолчанию поддерживает utf-8, буквы выводиться не будут.
- попробовать использовать вместо консоли приложение вроде http://conemu.github.io/en/UnicodeSupport.html которое вроде как поддерживает вывод utf8 (я не проверял)
- сохранять вывод скрипта в файл и просматривать файл редактором:
php script.php > result.txt
- не использовать кириллицу
- запускать свой код под линуксом. Линукс можно установить в виртуалку либо зарегистрироваться на c9.io (бесплатно) и запускать там. PHP там уже стоит.
Вот на какой хуй мне нужно заполнять всякие ебанные веб сервет руты, если при написании web path, он продолжает мой сервер рут и выходит говно с слешем на конце, а нахуй мне всрался ебанный слеш на конце? Я хочу без него, а нихуя если сотрешь, то это будет не правильно, а может оставить пустой веб сервер рут и правильно заполнить web path? А вот нихуяшечки.
Обьясните нахуя я должен заполнять два поля если сайт сука у меня один, как вообще блять правильно вписать эти два ебаных поля, да и хуй там на каждом ебаном шаге ошибки хуишибки, делаешь сука, все в точности по инструкции и нихуя не работает, говно ебаное
про зенд ничего не скажу
Yii идеальный фреймворк для скоростного "хуяк-хуяк и впродакшн". Но в долгой перспективе на большом проекте подобный подход до добра не довоидт
Спасибо. У меня есть еще такой "детский" вопрос. Например на кодигнайтере я могу с легкостью построить MVC и за минуту сделать пагинацию или валидацию и остальные муторные задачи, С симфони так же все, просто ты сказал что он сам по себе ничего не даст и я немного запутался.
>>797549
Смена кодировки виндовой консоли на юникод:
chcp 65001
Обратно на DOS:
chcp 866
Гуглится за 2 минуты.
Для начала, ты не пробовал прочесть документацию?
https://www.google.ru/search?q=phpstorm+server+config&btnG=Поиск&newwindow=1&gbv=1
>>797558
А ты путь указал к публичной папке?
>>797583
Просто ты с одним фреймворком работал больше чем с другим.
Ты говоришь "могу настроить валиадцию" - а ты можешь валидировать не данные из POST, а например просто из массива или в объекте-модели?
Кодеигнайтер очень убогий, насколько я помню. Там контроллеры наследуются от ядра фрйеморка или как-то так. КАкие-то странные хаки вместо DI и автозагрузки.
>>797597
Ты тестировал или просто скопировал информацию которую неграмотный выложил в интернет? Это тебя самого делает неграмотным.
Конечно тестировал. На Win10 работает.
Это всё, само собой, есть и в Symfony
Просто там, к примеру, та же валидация сделана так, что ты с помошью симфониевского встроенного валидатора можешь валидировать ВООБЩЕ любой обьект в своём проекте
А в том же Yii - встроенным валидатором ты можешь валидировать только модели, унаследоанные, кажется, от ActiveForm. Но при этом он проще настраивается и проще разобраться, как им пользоваться. В итоге говнокодить получается куда быстрее.
Аналогично со всеми остальными компонентами. В симфони - сложнее, но гибче. В Yii проще, но дубовей.
Спасибо! Ты можешь подсказать по Symfony книгу или сайт. я загуглил несколько но уже запутался в них.
Олсо
Будет много таблиц в БД и мне хочется сделать все хорошо и правильно. Работаю с MySQL и PHP. До этого использовал БД в который максимум 5-7 таблиц и не шибко связанны между собой, а этот проект сулит большой объем. Так вот собственно моя просьба: подскажи, пожалуйста, какие посмотреть материалы для работы (книги, статьи). Особенно хочется понять как правильно построить архитектуру БД и оптимизировать ее.
Никто не ответил в треде про БД так что пишу сюда
>ты с помошью симфониевского встроенного валидатора можешь валидировать ВООБЩЕ любой обьект в своём проекте
И не только объект!
нет, в общем сидел, клацал, что-то менял, что-то возвращал и внезапно все заработало, каким образом, хрен его знает, просто мистика какая-то
https://symfony.com/doc/current/index.html
Официальная дока, она у симфони очень хороша.
Также обязательно прочти cookbook оттуда же
>>797635
Уфф, это целая наука, которую в 3 словах не опишешь.
В симфони используется ORM Doctrine2. Её главна фишка в том, что она любые обьекты со всеми их связями с другими обьектами позволяет нативно сохранить в БД. Поэтому ты должен проектировать не таблицы в БД, а (очень важно!!!) доменную логику своего приложения. Тобишь проектировать классы, которые будут делать то, что хочет от программы заказчик, и их взаимодействие между собой. А потом, особо не парясь про БД с помошью доктрины всё это хозяйство сохранять в БД.
Как проектировать доменную логику приложения?? Ну это уже вопрос всей жизни, вселенной и всего такого. Начни с вот этого:
https://www.youtube.com/watch?v=xOx-si8s3K8
https://www.youtube.com/watch?v=nE2T2ZIaYvs
Потом гугли статьи про DDD. НАпример:
http://blog.byndyu.ru/2010/05/domain-driven-design.html
http://blog.byndyu.ru/2011/12/domain-driven-design.html
Дальше книги. Авось разберешься
>Авось разберешься
Добавлю ещё, что это все - высший пилотаж обьектно-ориентированного программирования. Если честно, я не уверен, что ни разу не варившись в больших проектах, в которых хотя бы частично применялся подобный подход, можно вот так вот легко взять и сходу во всё это врубиться.
Кстати именно по этому говорят, что Symfony - фреймворк для опытных разработчиков.
То, с чего я начинал - гибких фреймворк, позволяющий реализовывать самые продвинутые практики ООП. Но проблема в том, что сначала эти практики надо научиться применять....
PS: Всё ещё уверен, что хочешь взять Symfony?
Спасибо! Я не в чем толком не уверен. времени есть месяца три для получения хоть каких-то результатов, но программистов набирают не ахти- пока я один и совсем не опытный. поэтому думаю что проект может быть лажовым.
А, ну если заказчики неадекваты и набирают на сложный проект нубов - ну чтож, сами себе злобные буратины.
Значит делай любую херню за их счет. Хочешь симфони - бери симфони. Проект несомненно провалится, но ты не парься про это - это будет виной жадных заказчиков, жадничающих на сложный проект взять нормального опытного лида\архитектора.
Проект провалится - ты наберешься опыта - свалишь в место понормальнее. Дерзай.
ОП, в соседнем треде проводят специальную олимпиаду. Предлагают решить задачу, победитель - самая короткая программа. https://2ch.hk/pr/res/784954.html (М)
Пока в треде фаворит RUBY-анон - 89 символ.
У меня получилось 161, после удаления пробелов в одну строку. Вот мое решение - http://ideone.com/KxAijz
Сможешь сделать короче?
а в работе есть какие-то штрафы за такое? мол не умеешь, так чего взялся?
просто вот к примеру если повар не сможет приготовить сложное блюдо и клиент вернется недовольный, то пизды дадут повару.
в программировании такого нет?
Если это французский повар с 20-летним стажем, то да, претензии в кассу, и его за такое надо уволить.
Но если владелец ресторана на должность шеф-повара берёт первого попавшегося мальчика с улицы, без опыта, только потому, что мальчик просит 500$ (вместо 4000$ которые надо платить профессионалу) - то какие могут быть претензии к мальчику?
Мальчика может и выпрут, но я бы на его месте не расстроился бы совсем. Опыта набрался - и ладно.
ну я объяснил свой скудный опыт, но парня это не смутило. не знаю чего так. может никто из серьезных программеров не хочет браться за проект и остался только я. но все же ради опыта я согласен это сделать.
>парня это не смутило.
Он всё прекрасно понимает, но жадность - страшная вешь.
Ну ничего - скупой платит дважды.
АЛСО проваленный проект - тоже отличный опыт в копилку. По крайней мере в следующий раз ты уже будешь знать, как НЕ надо делать, и почему.
Авось сможешь сделать выводы, почитать книжки, как надо делать, ещё раз сделать выводы и в следующий раз всё сделать правильно.
А мне кажется связываться с заранее обреченным проектом это фэил. Ведь у тебя в портфолио будет провальный проект. Что ты будешь отвечать если спросят: "Ты работал над "ххх", почему оно не взлетело?" А ты такой "Ну потому что заказчик был злобный буратино" или "Была слабая команда" или "Проект был слишком сложным, запутанным и не продуманным". И каждый ответ против тебя, во всех случаях ты перекладываешь ответственность на кого-то другого, ведь ты сам вызвался работать над ним. А по поводу опыта, в первую очередь это будет опыт провала. Лучше найти что-то, что тебе по силам, и сделать это максимально хорошо, насколько ты можешь, даже если масштабам будет меньше.
По пододу даже полного фейла я написал выше.
Кроме того между полным фейлом и полным успехом вообще то хуева туча промежуточных состояний. Не пугайте человека, совсем не обязательно всё пойдет по самому плохому пути. Вероятнее всего получится просто весьма хреново, но как-то там оно работать будет.
Просто на определенном этапе станет очень сложно вносить изменения в проект и работать с кодом в стиле "взрыв на макаронной фабрике" неимоверно заебёт. Вот тогда и можно будет вал ить дальше. Предварительно сделав выводы из результатов работы.
Врать ни в коем случае нельзя. IT сфера - большая деревня, все друг друга знают.
Достаточно просто ... скажем так... умолчать о некоторых деталях прошлого проекта.
А как делают так, чтобы один сайт обслуживало несколько серверов? Как это называется?
>Сможешь сделать короче?
Делать нечего ОПу, как письками меряться с нами.
Померялся с тобой, у меня влезло в 102 символа: https://ideone.com/dgEMLQ
не могу понять даже как сделать ёбаный кубик
поможет кто ?
1) Убери знак доллара у функции mt_rand.
Знаком доллара предваряются переменные.
2) Функции mt_rand нужно передавать 2 параметра, ещё раз перечитай задание и объяснения, которые ему предшествовали.
Вот пытаюсь вытащить статистику сообщества методом stats.get
https://vk.com/dev/stats.get
В документации написано что токен нужен если статистика скрыта.
Вот я взял для примера сообщество с открытой для всех статистикой LIVE Express, делаю запрос
http://api.vk.com/method/stats.get?group_id=32295218&date_from=2016-07-16&date_to=2016-07-16
но у меня выдают ошибку и требуют токен. Что я делаю неправильно?
ДАвненько имел дело, но кажется так:
Токен нужен в любом случае
Если данные публичные - то достаточно передать просто токен своего приложения
Положим, что у меня есть матрица размером 2 х n, dв одном столбце у меня даты формата 00:00:00, а в другом какие-то данные, в зависимости от этих данных я меняю текущую дату на день вперёд.
Как это сделать?
я не буду участовать, но дам пару советов по улучшению (точнее, ухудшению) кода:
- минус в регулярке не требуется экранировать
- натыкать плюсов в число можно гораздо проще:
$x=preg_replace("/\d(?!$)/",'$0+',$i);
-123 -> -1+2+3
(анонам домашнее задание: разберите что делает эта регулярка)
- eval("echo\"$e=\",$e;"); -> eval("echo'$e=',$e;");
- Можно заменить <?php на <?= и выиграть еще 2 символа. <?= это <?php echo и может это получится как-то использовать
- можно писать все одним выражением вроде <?= ($i=readline()) . ...
Как видите во всяких идиотских конкурсах PHP точно будет не последним.
Оп тян, если что. Мимо олдфаг тредов
Почему в тред олимпиады не запостил, мы должны победить! Отстоять честь синего слона!
index.html - это html страница содержащая форму с тремя полями ввода и отправкой данных в "action.php" методом POST;
action.php - это php скрипт, который рассчитывает кредит и загружает шаблон template.html с помощью функции include;
template.html - это html страница в которой содержится логика отображения сообщений.
Получается, после отправки данных с помощью формы, пользователь попадет на страницу template.html, изменится ли адрес в адресной строке в браузере?
Для того чтобы изменить данные и рассчитать кредит еще раз, пользователю нужно нажать назад, или кликнуть на ссылку ведущую на страницу index.html (для этого, мне нужно сделать эту ссылку на странице template.html)?
Можно ли выводить сообщения на странице index.html, не переходя на template.html средствами PHP?
Спасибо за терпение)
https://github.com/TheSidSpears/Students/blob/master/router.json
> Вот тут я не уверен что в роутере должен указываться вью. зачем? Ты планируешь один вью с несколькими контроллерами использовать? Это вряд ли получится, так как вью привязан к своему контроллеру и не совместим с другими. И даже если он совместим, при правке это легко сломать.
Мне на самом деле эта строка нужна была, чтобы указать в какой папке вью. Если заменю "view": "status/register_ok" на "folder": "status" - будет норм?
> https://github.com/TheSidSpears/Students/blob/master/app/container.php#L7
> Более того, ты возвращаешь массив непонятной структуры. Не лучше ли возвращать объект с методами для получения данных?
- В чём заключается непонятность структуры? Ты предлагаешь делать методы типа getDBLogin(), getDBPass() и т.д. или как?
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php
Контроллер переусложнен. По моему он весь пишется в виде одного местода на 15-20 строк, а ты зачем-то надобавлял тут свойств и методов. У тебя как-то все выглядит переусложненно, попробуй упростить и избавиться от лишнего.
Cократил, но не уверен что верно. Закоммитил, проверь.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php#L73
> protected function fillStudent(Student $student){
Непонятно что тут делает цикл ибо он ничего не меняет в массиве.
foreach ($_POST as $post) {$post=trim(strval($post));}
Он делает trim и strval, разве нет?
Почему? Файл template.html содержит и php код и html и наверное правильнее было бы дать ему расширение .tpl, но первый файл index.html полностью состоит из html'а?
И еще, как правильно писать в шаблонах конструкции с открывающимися и закрывающимися фигурными скобками ({}) или двоеточие (:) и endif (endfor)
Например
<?php for ($i = 0; $i < 5; ++$i): ?>
Hello, there!
<?php endfor; ?>
или
<?php for ($i = 0; $i < 5; ++$i){ ?>
Hello, there!
<?php } ?>
>писать в шаблонах конструкции с открывающимися и закрывающимися фигурными скобками
а погуглить, не?
Там же полно хтмл параши, разве нет? Каждый .пхп файл воспринимать как класс?
ну как представление подключать я не ебу, я в джаве шарю на уровне написание консольной программки, ну по сути если без гуи создавать прогу, то аналогично как в джаве выходит.
А как присобачивать ко всему этому еще html уже хз
Как я сам не догадался? Спасибо, ты мне очень помог, что бы я без тебя делал.
>Не аналогично. В джаве ВСЕ с чем ты работаешь - классы, здесь же дохуя скриптов которые как каша и это меня раздражает. Я бы просто хотел управлять хтмл файлами из классов
Сука почему нет то блять??? Ты думаешь зачем в пхп ООП сделали, по приколу?!
Пишешь класс для взятия данных из базы.
Пишешь класс для манипуляций данными.
Пишешь класс для отображения данных( в html/xml/yml/xaml/json/rss/nebo/allah e.t.c.)
Так если ты догадался, так чего же не погуглил?
При альтернативном синтаксисе тело управляющей структуры заключается не в фигурные скобки а помещается между двоеточием и ключевым словом.
Управляющие структуры, имеющие альтернативный синтаксис с закрывающими ключевыми словами:
if - endif;
while - endwhile;
for - endfor;
foreach - endforeach;
switch - endswitch;
ВАЖНО: Смешивание синтаксиса в одной и той же управляющей структуре не поддерживается.
Использовать альтернативный синтаксис удобно при использовании PHP в роли шаблонизатора - когда небольшой код PHP необходимо интегрировать в html шаблон.
Например:
<select>
<? foreach($options as $value => $label):?>
<option value="<?=$value?>"><?=$label?></option>
<? endforeach;?>
</select>
А я Леха Пирамидка
Мне кажется, шаблон лучше сделать один. Он должен отображать и форму, и результат, если тот есть. Тогда можно подправить какие-то параметры и снова отправить форму.
>>798266
Не сбивай людей с току.
>>798294
Не только можно, но и нужно.
>>798296
Через двоеточие
>>798300
Да, как класс.
>>798302
Через шаблонизатор. Можно через встроенный в пхп.
>>798303
Не сбивай людей с толку.
>>798308
Непраивльно писать без фигурных скобок или двоеточия.
Мне кажется, шаблон лучше сделать один. Он должен отображать и форму, и результат, если тот есть. Тогда можно подправить какие-то параметры и снова отправить форму.
>>798266
Не сбивай людей с току.
>>798294
Не только можно, но и нужно.
>>798296
Через двоеточие
>>798300
Да, как класс.
>>798302
Через шаблонизатор. Можно через встроенный в пхп.
>>798303
Не сбивай людей с толку.
>>798308
Непраивльно писать без фигурных скобок или двоеточия.
Спасибо
>Мне кажется, шаблон лучше сделать один. Он должен отображать и форму, и результат, если тот есть. Тогда можно подправить какие-то параметры и снова отправить форму.
Один шаблон для формы, другой для вывода результатов.
А возвращать шаблон, в котором подключен шаблон для формы и шаблон для вывода информации.
>Через шаблонизатор. Можно через встроенный в пхп.
Php -это и есть шаблонизатор.
>Непраивльно писать без фигурных скобок или двоеточия.
Ты ахуеешь, но можно.
Смотри, условно говоря всё так. У тебя есть логика, которая как раз ООП там классы и вот это вот всё. В ней ты как раз управляешь всем, в том числе и аштээмэлем.
Потом в одном классе, который отвечает за вывод будет написано что-то в духе:
$viewData['name'] = $user->name;
$viewData['friends'] = $user->friends;
ну и дальнейший сбор инфы, которая тебе нужна для вывода на сайте.
далее ты пишешь например:
$main->loadView("userPage.php", $viewData);
Это допустим метод подгрузки шаблона, с перешачей туда аштээмэль-параши.
А внутри шаблона у тебя примерно такое
<html>
<body>
<p>Привет <?=$user?> </p>
<p>Друзья онлайн:<ul>
<? foreach ($friends as $friend) {
echo "<li> $friend </li>
}
?>
</ul></p>
</body>
</html>
Ну это очень грубо так примерно всё, и вообще я сам не шарю.
Смотри, условно говоря всё так. У тебя есть логика, которая как раз ООП там классы и вот это вот всё. В ней ты как раз управляешь всем, в том числе и аштээмэлем.
Потом в одном классе, который отвечает за вывод будет написано что-то в духе:
$viewData['name'] = $user->name;
$viewData['friends'] = $user->friends;
ну и дальнейший сбор инфы, которая тебе нужна для вывода на сайте.
далее ты пишешь например:
$main->loadView("userPage.php", $viewData);
Это допустим метод подгрузки шаблона, с перешачей туда аштээмэль-параши.
А внутри шаблона у тебя примерно такое
<html>
<body>
<p>Привет <?=$user?> </p>
<p>Друзья онлайн:<ul>
<? foreach ($friends as $friend) {
echo "<li> $friend </li>
}
?>
</ul></p>
</body>
</html>
Ну это очень грубо так примерно всё, и вообще я сам не шарю.
не слушай эту маню.
Скрипт - это такая абстракция. От нее отталкиваться нельзя. Скрипт я могу на калякать на Bash и на C.
Ты написал класс.
У тебя есть роутер класс. Он принимает Имя класса как строку и вызвает класс с таким именем.
Представляю, сколько глистов у этих кошатниц
>В азии много таких кафе
То-то они все унтерменши. Из поколения в поколение глистов переносят.
В каких еще скриптах? При нормальной архитектуре в php у тебя нет никаких скриптов, только классы, вызывающие другие классы, наследование, абстрактные классы, интерфейсы, полиморфизм. Скрипты только говнокодеры пишут.
><p>Друзья онлайн:<ul>
><? foreach ($friends as $friend) {
>echo "<li> $friend </li>
>}
>?>
В шаблонах используют специальный синтаксис для них:
<? foreach ($friends as $friend): ?>
<li> <?=$friend ?> </li>
<? endforeach; ?>
Классное творческое применение хаков, помог мне уменьшить код: https://ideone.com/dgEMLQ
>(анонам домашнее задание: разберите что делает эта регулярка)
>preg_replace("/\d(?!$)/",'$0+','-123')
Почитал немного, понячья магия какая-то. Как я её понял:
Первый символ дефис, пропускаем его (но кладем в whole match).
Следующий символ 1, подходит под \d. За ним не конец строки, значит negative lookahead заматчил единицу, в $0 добавляется 1+, -1+ в результате. $0 сбросился, так как lookahead отработал (именно из-за этой особенности, насколько я понял, для lookahead нельзя указывать квантификаторы, например вот так /\d(?!${1,2}), ведь проверяется только следующий символ.
Дальше двойка, за ней не конец строки - матчим двойку, заменяем $0 (там сейчас только 2) на whole match с плюсом, конкатенируем с результатом, сбрасываем whole match. Следующий символ 3, за ним конец строки, тройку не матчим, но она добавляется в whole match.
Я писал на с++, потом на с#, очень привык с темам vs, но на саблайм текс и пхпшторм они очень кривые какие-то. Нет тут дрочильщиков на темы vs? Перекидываться на другие как-то очень нет желания, у меня уже цвета в подсознании сидят.
Погугли темы vs для шторма и саблайма, наверняка есть.
Ты как-то странно объяснил работу preg_replace. Она ничего не накапливает. Она идет от начала строки к концу посимвольно и проверяет ее на совпадение с регуляркой. Если совпало - заменяет и идет дальше, если нет - переходит к следующему символу. Между проверками ничего не накапливается.
> Первый символ дефис, пропускаем его (но кладем в whole match).
Мы никуда не кладем дефис, а просто оставляем как есть, не заменяя, так как он не совпал с регуляркой. Заменяется только то, что совпало.
?! нужен только чтобы сказать "за цифрой не конец строки". Как альтернатива можно писать (?=\d) но это длиннее.
> ${1,2}
Тут ошибка, я не знаю, можно ли применять квантификатор к утверждению, но даже если и можно то это было бы бессмысленно. Ты можешь хоть 10 раз проверить условие конца строки, это ничего не меняет.
>>798632
Дефолтную светлую тему из саблайма.
> Она идет от начала строки к концу посимвольно и проверяет ее на совпадение с регуляркой.
Вот теперь, думаю, всё стало ясно. Спасибо.
>> ${1,2}
> Тут ошибка, я не знаю, можно ли применять квантификатор к утверждению
Да, глупость какую-то написал, даже не протестировав.
У меня было что-то вроде этого, я напутал: https://stackoverflow.com/questions/9030305/regular-expression-lookbehind-doesnt-work-with-quantifiers-or
Darcula в PHPStorm.
Упомянутые там ограничения относятся к lookbehind и связаны с особенностями реализации, чтобы проверять строки неизвестной длины, движок регулярных выражений должен уметь двигаться в обратную сторону по строке, и видимо не все реализации это умеют.
А при фиксированной длине строки можно просто отодвинуться на N символов назад и сравнивать их слева направо.
То есть это лишь особенность конкретного движка, возможно что есть и такие, в которых ограничения нет. Принцпиального ограничения тут нет.
Пиши в студии, хули ты. https://visualstudiogallery.msdn.microsoft.com/6eb51f05-ef01-4513-ac83-4c5f50c95fb5
>>798322
Получается структура будет такой:
index.php - я не знаю что это, но оно грузит (include) либо template.html в которой и форма и вывод результата, либо по отдельности form.html и result.html.
template.html (или form.html и result.html) - это шаблон.
action.php - это скрипт с логикой.
Схема алгоритма выглядит так: сindex.html -include-> template.html -action/post-> action.php -include-> index.html -include-> template.html ?
Или сделать просто 2 файла index.html - шаблон с формой и выводом
и action.php - это скрипт с логикой.
Тогда схема: index.html -action/post-> action.php -include-> index.html
Зачем делать 2 скрипта и усложнять все? делай один скрипт для вывода и для обработки данных формы. И один шаблон для вывода формы и результатов.
Алсо, урок по работе с формами: https://github.com/codedokode/pasta/blob/master/forms.md
Единственное, редирект тут делать не надо, и метод стоит использовать GET.
> Надо ставить фигурные скобки. Вместо копипастоы ифов лучше сделать массив с цифрами и словами и циклом искать совпадения в нем.
Я ничегошеньки не понял как это делать, кто-нибудь может подсказать?
6 задача: http://ideone.com/ZockRi
Use elseif or switch, Luke!
Я этот урок не видел в ОП посте, наверное стоит его пройти, прежде чем приступать к "еще одному кредиту"
>Опыт не менее 3-х лет в роли веб-разработчика (желательно ecommerce).
>Наличие в портфолио хотя бы одного проекта, реализованного на Framework,
>Плюсом будет, если знаешь:
>Javascript, HTML/CSS;
3 года опыта, знание html/css будет плюсом, окей.
Ну не всегда PHP-программист пишет что-то на фронте. Знаю студию, где проекты делятся между бекендщиками и фронтендщиками.
Алсо, вот что я как-то нашёл на бирже фриланса. Меня хватило на минут 30 скроллить такое, больше я там не появлялся.
Переодически, где-то раз в неделю процесс mysql занимает триста процентов в топе. Я не знаю, как искать то, что пораждает такую нагрузку.
От рута можно сделать такие запросы для начала:
SHOW FULL PROCESSLIST
SHOW ENGINE InnoDB STATUS
Про них написано в офиц. мануале (англ). Если не понимаешь, можешь попробовать запостить, может кто-то из анонимных экспертов нашего треда глянет.
Ребята, поясните в двух словах, что такое Cron ? Из того, что прочитал, понял что если я поставлю себе Cron задачу на сервере, то она будет выполнятся с определённым интервалом.
Вопрос, могу ли я залить php документ с запросом в базу данных, в крон задачу, чтобы автоматически удалялись устаревшие данные из базы , м ?
>Ребята, поясните в двух словах, что такое Cron
Ты настолько обленился, что википедию не осилил?
На сервере что стоит, debian\ubuntu наверно? Тогда лучше погляди на таймеры systemd для этого.
Можешь, но то же самое ты можешь сделать и используя процедуры в базе.
Если файл обязателен, то просто ставишь время и путь к файлу. (Помни, что документ рут проекта может мешать работе с кроном (а может и не мешать))
Подумайте 10 раз прежде чем отказаться от php.
>Положим, что у меня есть матрица размером 2 х n, dв одном столбце у меня даты формата 00:00:00, а в другом какие-то данные, в зависимости от этих данных я меняю текущую дату на день вперёд.
>Как это сделать?
>матрица
Фуф, еле вспомнил как это работает. Я такого со времен первого курса вуза не слышал. Где такое нужно сделать?
Тебе помогут такие функции - array_map, array_walk
<html>
<head>
...
</head>
<body>
<header></header>
<footer></footer>
</body>
</html>
Что из этого "шапка"? <head> или <header>?
Как правильно выводить шаблоны через php? Иметь в каждом шаблоне <!DOCTYPE ...> и <head> или иметь отдельные шаблоны для этого? Если второе, то должны ли они содержать тэги <body> или их можно выводить в рабочем шаблоне?
Можно ли назвать это выполненным заданием?
>321.5+3/2-5=157.25
>'7+2/2='; //4.5
Это неправильные ответы. Операции деления и умножения должны выполняться раньше, чем операции сложения и вычитания. Погугли алгоритм сортировочной станции. Для каждого оператора выставляй приоритет в виде цифры.
>>799912
В других тредах тоже норм, только там вряд ли кто-то будет много твоего кода проверять. Да и у нас это только ОП делает.
В общем, если нормально спросить, то нормально ответят. Можешь погуглить "how to ask questions smart way".
>>799911
Смотря что валидировать. Если только email или тип данных (список констант есть в мануале по filter_var), то подойдёт. Если нужно, чтобы поле содержало только определённые символы, то бери регулярки.
>>799824
Из комментов:
>С другой стороны js\node могут привлекать существенно лучшим дизайном языка в мелочах, чем у того же php
Вот тут просто стул прожёг. Вспомнилось видео: https://www.youtube.com/watch?v=D5xh0ZIEUOE
Всё никак не могу себя заставить сесть за задачи ОПа по JS.
>Это неправильные ответы. Операции деления и умножения должны выполняться раньше, чем операции сложения и вычитания.
Порядок действий не соблюдается (как и в обычном калькуляторе). Калькулятор отсюда http://archive-ipq-co.narod.ru/l1/finals.html
Ну делай с приоритетами теперь.
Если у тебя 1 шаблон на весь сайт, то просто делаешь 1 шаблон без разделения и всё.
Если у тебя шаблонов несколько, но есть общая для всех шапка и подвал, то просто выносишь шапку и подвал в отдельные шаблончики.
ну и в завимимости от того какую ты страничу собрался отдавать, то инклудишь в своем коде подходящее наполнение между шапкой и телом
require ('head.php');
include ('page1.php');
require ('footer.php);
>Если второе, то должны ли они содержать тэги <body> или их можно выводить в рабочем шаблоне?
Я бы сделал так на твоем месте, что бы в случае "проебанной страницы", у тебя ничего не сломалось, и вывелся хотя бы пустой хедер с футером, поэтому все главные теги разместил бы в них.
>Что из этого "шапка"? <head> или <header>?
<head> - содержит в себе служебную инфу, которая на странице не отображается.
<header> - новый тег в хтмл насколько я понимаю введенный для семантической простоты, что бы в него именно и писали все шапку. а не воротили
<div class="header"> </div>
><head> - содержит в себе служебную инфу, которая на странице не отображается.
>
><header> - новый тег в хтмл насколько я понимаю введенный для семантической простоты, что бы в него именно и писали все шапку. а не воротили
><div class="header"> </div>
Я знал об этом. Но что из этого "шапка"
>Алсо, урок по работе с формами: https://github.com/codedokode/pasta/blob/master/forms.md
Запилил процедурную реализацию алгоритма валидации формы как в уроке, теперь пытаюсь сделать тоже самое, но с ООП подходом. Пикрил - диаграмма классов.
Есть пара вопросов по уроку:
В разделе урока ООП-подход, второй абзац. Не совсем понятно, что имелось ввиду. Класс ошибок FormErrors - подразумевается, что этот класс хранит все ошибки, допущенные при заполнении всех полей формы, и соответственно, тогда каждую ошибку нужно как-то ассоциировать с полем, значением и сообщением, и хранить в виде массива, или в виде объекта Error в этом классе (композиция)? А в классе User хранить ссылку на него? Или можно хранить только одну ошибку, для каждого поля формы в классе Error, а все объекты Error хранить в массиве класса User (у меня на диаграмме Values)? Или вообще не стоит хранить ссылку на ошибки в классе User? Тогда, т.к. они возвращаются в методе класса Validator, то вызывать этот метод должен не User, а главный скрипт (MainScript), он же будет принимать решение, печатать сообщение об ошибках или создавать класс User. А класс User будет обладать только одним методом - конструктором, которому в качестве аргументов нужно передать корректные значения всех полей? А в самом конструкторе будет достаточно только указать тайп-хинт для значений, т.к. получается, что они уже прошли проверку до того, как были переданы в конструктор?
И второй вопрос, я сделал валидацию с помощью функции filter_var, тип фильтра я храню в константе, которая обозначает формат значения, который нужно ввести в поле формы. Но нужно где-то хранить отношения "поле_ввода=>формат_значения" и где-то объявлять константы. Мне кажется логично хранить константы в классе User, т.к. для каждой формы весь скрипт валидации отличается только этим классом? Но тогда, этот же класс и должен передавать значения на проверку в класс Validator? Но можно добавить класс Форма, в котором указать допустимый формат для каждого поля, и он же будет вызывать метод проверки, а потом создавать класс User. Но в этом случае, для каждой формы придется изменять уже два класса: Форму и User.
>Алсо, урок по работе с формами: https://github.com/codedokode/pasta/blob/master/forms.md
Запилил процедурную реализацию алгоритма валидации формы как в уроке, теперь пытаюсь сделать тоже самое, но с ООП подходом. Пикрил - диаграмма классов.
Есть пара вопросов по уроку:
В разделе урока ООП-подход, второй абзац. Не совсем понятно, что имелось ввиду. Класс ошибок FormErrors - подразумевается, что этот класс хранит все ошибки, допущенные при заполнении всех полей формы, и соответственно, тогда каждую ошибку нужно как-то ассоциировать с полем, значением и сообщением, и хранить в виде массива, или в виде объекта Error в этом классе (композиция)? А в классе User хранить ссылку на него? Или можно хранить только одну ошибку, для каждого поля формы в классе Error, а все объекты Error хранить в массиве класса User (у меня на диаграмме Values)? Или вообще не стоит хранить ссылку на ошибки в классе User? Тогда, т.к. они возвращаются в методе класса Validator, то вызывать этот метод должен не User, а главный скрипт (MainScript), он же будет принимать решение, печатать сообщение об ошибках или создавать класс User. А класс User будет обладать только одним методом - конструктором, которому в качестве аргументов нужно передать корректные значения всех полей? А в самом конструкторе будет достаточно только указать тайп-хинт для значений, т.к. получается, что они уже прошли проверку до того, как были переданы в конструктор?
И второй вопрос, я сделал валидацию с помощью функции filter_var, тип фильтра я храню в константе, которая обозначает формат значения, который нужно ввести в поле формы. Но нужно где-то хранить отношения "поле_ввода=>формат_значения" и где-то объявлять константы. Мне кажется логично хранить константы в классе User, т.к. для каждой формы весь скрипт валидации отличается только этим классом? Но тогда, этот же класс и должен передавать значения на проверку в класс Validator? Но можно добавить класс Форма, в котором указать допустимый формат для каждого поля, и он же будет вызывать метод проверки, а потом создавать класс User. Но в этом случае, для каждой формы придется изменять уже два класса: Форму и User.
Я это понимаю так:
<head> используется один раз, например в шаблоне head.* Он содержит служебную информацию.
<header> может быть использован неограниченное кол-во раз на странице. Он содержит информацию для пользователя. Обозначает заголовок смыслового блока. В заголовок обычно помещается название и иногда короткая информация о содержимом блока. Вся страница сайта, это некий блок, и у него есть заголовок, который обычно содержит название или логотип. Содержимое страницы то же можно разделить на блоки по смыслу, например, статья, последние записи, форма обратного звонка. Каждый такой блок будет содержать как минимум название. Даже подвал страницы может иметь <header>. Точно также обстоят дела с тегом <footer>.
"Шапка сайта" - обычно имеется ввиду верхняя часть, где логотип названия, контакты, иногда меню. В WordPress эта часть шаблона называется header.php. По новым правилам ее нужно заключать между тегами <header></header>. Но эти теги можно использовать не только в шапке сайта, но и в шапке статьи, в шапке подвала и т.д.
Пытаюсь вкатиться, скажите ЧЯДНТ? Почему возвращает false?
$a = Yii::$app->getSecurity()->generatePasswordHash('хуй');
$b = Yii::$app->getSecurity()->generatePasswordHash('хуй');
if (Yii::$app->getSecurity()->validatePassword($a, $b)) {
echo 'Совпало';
} else {
echo 'Нихуя';
}
Я не писал на Yii, но мне кажется, что ты сгенерировал 2 разных пароля и хочешь, чтобы они были одинаковые.
Ну сойди с неба на землю и поясни смертному, в чем дело то? И там и там же "Хуй", проверяю я их сходство вроде правильной функцией с методички. Почему они не одинаковые?
Погуглил за тебя: http://www.yiiframework.com/doc-2.0/guide-security-passwords.html
Ты сгенерировал 2 хеша. И их же проверяешь методом для проверки пароля.
Ты разницу между паролем и солью понимаешь?
Ок, сделал так:
$a = Yii::$app->getSecurity()->generatePasswordHash('хуй');
$b = '$2y$13$5KzuGLhwGGIl9gXlZhLroOqkwTLAgKvyMONYq6MSqUFaIItGHlOGW'; //хэш хуя
if (Yii::$app->getSecurity()->validatePassword($a, $b)) {
echo 'Совпало';
} else {
echo 'Нихуя';
}
Всеравно false
Теперь ты одинаковые хеши передаёшь в метод валидации пароля. Ты не понимаешь разницу между хешем и паролем, рано тебе во фреймворки лезть. Решай студентов из ОП-поста, задача содержит множество полезной информации, с которой ты не знаком.
сам решай свои задачи.
Однако ты прав, написал в $a 'хуй', не хешируя его - вернуло тру. Однако в методичке четко написано:
>Когда пользователь попытается войти, отправленный пароль должен быть хеширован и сравнён с ранее сохранённым хешем
Этот метод автоматом хешириует второй (или первый аргумент). Получается, что один из хешей отхеширован второй раз. Запихивай один пасс плейнтекстом
Первый аргумент. (фикс)
Вот пример с туториала (как тут кода вставлять):
$hash = Yii::$app->getSecurity()->generatePasswordHash($password);
if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {
// all good, logging user in
} else {
// wrong password
}
> >С другой стороны js\node могут привлекать существенно лучшим дизайном языка в мелочах, чем у того же php
- нет тайп хинтов
- нет нормального ООП
- обращение к несуществующему полю не взывает ошибки
- деление на ноль не вызывает ошибки
>>800030
Класс Value с одним полем - не очень понятно, зачем он. Мне кажется, он не нужен и это переусложнение. Ни разу такого не видел.
Не уверен что в классе Values должны храниться ошибки. Мне кажется, их можно хранить отдельно. Более того, тут появляется проблема что при изменении значений ошибки становятся неактуальными.
Также, обычно вместо него используют модель, то есть класс примерно такого вида:
class Student
{
public $name;
public $surname;
}
Там правда есть подвох что поля в форме не всегда соответствуют модели один-к-одному. Ну например в форме регистрации будет 2 поля ввода пароля, а в модели студента - поле с хешем пароля. Где хранить эти пароли...
Ты пишешь универсальные классы для любой формы или для какой-то конкретной? Как минимум валидация в каждой форме будет своя.
У валидатора по моему должен быть один публичный метод - validate(Values) -> errors. Или, что лучше, валидировать конкретную модель без привязки к форме: StudentValidator->validateStudent(Student) -> errors
Также надо помнить что не все поля можно проверить отдельно от других. ну например при вводе пароля при регистрации надо проверить что пароль совпадает с подтверждением пароля.
Не понимаю, что делает метод Values#createValues() ? createValue()? Так как мне кажется что класс Value не нужен то и эти методы тоже получаются ненужными.
Также, мне кажется что в Values не должно быть метода validate. Зачем? Валидация это задача другого класса.
В FormError вместо value лучше хранить к какому полю относится ошибка.
MainScript я думаю не надо разбивать на методы. Алгоритм будет лучше читаться если он написан в одном методе и небольшой. Название стоит поменять на ....Controller.
В общем:
- посмотри, какие классы универсальные, а какие пишутся индивидуально для каждой формы
- определи задачу каждого класса
- убери из него то, что к ней не относится
> >С другой стороны js\node могут привлекать существенно лучшим дизайном языка в мелочах, чем у того же php
- нет тайп хинтов
- нет нормального ООП
- обращение к несуществующему полю не взывает ошибки
- деление на ноль не вызывает ошибки
>>800030
Класс Value с одним полем - не очень понятно, зачем он. Мне кажется, он не нужен и это переусложнение. Ни разу такого не видел.
Не уверен что в классе Values должны храниться ошибки. Мне кажется, их можно хранить отдельно. Более того, тут появляется проблема что при изменении значений ошибки становятся неактуальными.
Также, обычно вместо него используют модель, то есть класс примерно такого вида:
class Student
{
public $name;
public $surname;
}
Там правда есть подвох что поля в форме не всегда соответствуют модели один-к-одному. Ну например в форме регистрации будет 2 поля ввода пароля, а в модели студента - поле с хешем пароля. Где хранить эти пароли...
Ты пишешь универсальные классы для любой формы или для какой-то конкретной? Как минимум валидация в каждой форме будет своя.
У валидатора по моему должен быть один публичный метод - validate(Values) -> errors. Или, что лучше, валидировать конкретную модель без привязки к форме: StudentValidator->validateStudent(Student) -> errors
Также надо помнить что не все поля можно проверить отдельно от других. ну например при вводе пароля при регистрации надо проверить что пароль совпадает с подтверждением пароля.
Не понимаю, что делает метод Values#createValues() ? createValue()? Так как мне кажется что класс Value не нужен то и эти методы тоже получаются ненужными.
Также, мне кажется что в Values не должно быть метода validate. Зачем? Валидация это задача другого класса.
В FormError вместо value лучше хранить к какому полю относится ошибка.
MainScript я думаю не надо разбивать на методы. Алгоритм будет лучше читаться если он написан в одном методе и небольшой. Название стоит поменять на ....Controller.
В общем:
- посмотри, какие классы универсальные, а какие пишутся индивидуально для каждой формы
- определи задачу каждого класса
- убери из него то, что к ней не относится
Уже разобрался, спасип. Есть еще вопрос:
В Yii2 валидация формы на стороне клиента осуществляется по событию - onblur. Как можно это изменить?
> Класс ошибок FormErrors - подразумевается, что этот класс хранит все ошибки, допущенные при заполнении всех полей формы, и соответственно, тогда каждую ошибку нужно как-то ассоциировать с полем, значением и сообщением, и хранить в виде массива, или в виде объекта Error в этом классе (композиция)?
Можно в виде массива, можно в виде объекта Error. Если ты хочешь максимум ООП то конечно в виде объекта.
> А в классе User хранить ссылку на него?
Это на мой взгляд неправильно. Ошибки это не часть информации о пользователе. Это лишь результат валидации пользователя внешним классом. Он устаревает со временем и потому хранить его в юзере неправильно.
> класс User будет обладать только одним методом - конструктором, которому в качестве аргументов нужно передать корректные значения всех полей?
Полей может быть много, конструктор будет нечитаемым. обычно делают пустой конструктор и мето принимающий массив полей для установки (setAttributes(array $values)) либо ставят свойства в цикле.
> А в самом конструкторе будет достаточно только указать тайп-хинт для значений, т.к. получается, что они уже прошли проверку до того, как были переданы в конструктор?
Тайп-хинты не имеют отношения к валидации. Тайп хинты это проверяемые подсказки для программистов, какие данные надо подавать на вход. Они не способны проверить, правильно ли пользователь заполнил форму. Или я не понял твой вопрос?
> И второй вопрос, я сделал валидацию с помощью функции filter_var, тип фильтра я храню в константе, которая обозначает формат значения, который нужно ввести в поле формы.
Не, ты слишком ограничиваешь себя. Валидация может быть произвольной. Ну например проверить что год рождения указан от A до B или что данного значения нет в базе данных. Валидация может связывать несколько полей, например проверить что поля совпадают или что значеие одного поля не противоречит другому.
filter_var тут не хватит. Должна быть возможность писать произвольный код.
Более того, правила могут еще меняться в зависимости от ситуации. Ну например может быть правило "заголовок статьи можно менять только в течение 1 часа после публикации". Или "заголовок может менять только модератор".
> . Но нужно где-то хранить отношения "поле_ввода=>формат_значения" и где-то объявлять константы.
Информацию о типах значений можно хранить в 2 местах:
- в модели User если эти правила актуальны в любой ситуации. Например, правило "длина имени никогда не может быть более 50 символов".
- в форме если эти правила относятся только к форме, а в принципе в модели могут быть и другие значения. Не могу сейчас придумать пример.
> Но можно добавить класс Форма, в котором указать допустимый формат для каждого поля, и он же будет вызывать метод проверки, а потом создавать класс User. Но в этом случае, для каждой формы придется изменять уже два класса: Форму и User.
Возможно, что придется. Если подумать, часть информации относится к модели пользователя. а часть только к форме.
> Класс ошибок FormErrors - подразумевается, что этот класс хранит все ошибки, допущенные при заполнении всех полей формы, и соответственно, тогда каждую ошибку нужно как-то ассоциировать с полем, значением и сообщением, и хранить в виде массива, или в виде объекта Error в этом классе (композиция)?
Можно в виде массива, можно в виде объекта Error. Если ты хочешь максимум ООП то конечно в виде объекта.
> А в классе User хранить ссылку на него?
Это на мой взгляд неправильно. Ошибки это не часть информации о пользователе. Это лишь результат валидации пользователя внешним классом. Он устаревает со временем и потому хранить его в юзере неправильно.
> класс User будет обладать только одним методом - конструктором, которому в качестве аргументов нужно передать корректные значения всех полей?
Полей может быть много, конструктор будет нечитаемым. обычно делают пустой конструктор и мето принимающий массив полей для установки (setAttributes(array $values)) либо ставят свойства в цикле.
> А в самом конструкторе будет достаточно только указать тайп-хинт для значений, т.к. получается, что они уже прошли проверку до того, как были переданы в конструктор?
Тайп-хинты не имеют отношения к валидации. Тайп хинты это проверяемые подсказки для программистов, какие данные надо подавать на вход. Они не способны проверить, правильно ли пользователь заполнил форму. Или я не понял твой вопрос?
> И второй вопрос, я сделал валидацию с помощью функции filter_var, тип фильтра я храню в константе, которая обозначает формат значения, который нужно ввести в поле формы.
Не, ты слишком ограничиваешь себя. Валидация может быть произвольной. Ну например проверить что год рождения указан от A до B или что данного значения нет в базе данных. Валидация может связывать несколько полей, например проверить что поля совпадают или что значеие одного поля не противоречит другому.
filter_var тут не хватит. Должна быть возможность писать произвольный код.
Более того, правила могут еще меняться в зависимости от ситуации. Ну например может быть правило "заголовок статьи можно менять только в течение 1 часа после публикации". Или "заголовок может менять только модератор".
> . Но нужно где-то хранить отношения "поле_ввода=>формат_значения" и где-то объявлять константы.
Информацию о типах значений можно хранить в 2 местах:
- в модели User если эти правила актуальны в любой ситуации. Например, правило "длина имени никогда не может быть более 50 символов".
- в форме если эти правила относятся только к форме, а в принципе в модели могут быть и другие значения. Не могу сейчас придумать пример.
> Но можно добавить класс Форма, в котором указать допустимый формат для каждого поля, и он же будет вызывать метод проверки, а потом создавать класс User. Но в этом случае, для каждой формы придется изменять уже два класса: Форму и User.
Возможно, что придется. Если подумать, часть информации относится к модели пользователя. а часть только к форме.
Нельзя проверять пароль генерацией хеша. Должна быть функция проверитьПароль(пароль, хеш из базы)
Так как хеш может содержать не только пароль, но и случайную соль.
>>799911
По моему только в ограниченных случаях. Я не помню почему, но вроде она не очень удобная.
>>799891
Зависит от контекста. Как правило общую часть разных страниц выносят в отдельный шаблон. Копипаста это зло.
>>799860
И цикл foreach
>>799931
Для первых 2 строк стоит использовать цикл чтобы не повторяться. Также погугли функцию array_rand.
>>800002
Почему для разных шаблонов используются разные функции require/include?
>>800090
Почитай про соленые хеши
>>800161
Не знаю. Там нет опции? Если нет, то только заменой кода на свой или добавлением своего кастомного кода.
Нельзя проверять пароль генерацией хеша. Должна быть функция проверитьПароль(пароль, хеш из базы)
Так как хеш может содержать не только пароль, но и случайную соль.
>>799911
По моему только в ограниченных случаях. Я не помню почему, но вроде она не очень удобная.
>>799891
Зависит от контекста. Как правило общую часть разных страниц выносят в отдельный шаблон. Копипаста это зло.
>>799860
И цикл foreach
>>799931
Для первых 2 строк стоит использовать цикл чтобы не повторяться. Также погугли функцию array_rand.
>>800002
Почему для разных шаблонов используются разные функции require/include?
>>800090
Почитай про соленые хеши
>>800161
Не знаю. Там нет опции? Если нет, то только заменой кода на свой или добавлением своего кастомного кода.
>>800014
Ну смотри, давай разберем, что тебе нужно. У тебя должна после всех твоих инклудов и сборов по частям, просто получиться правильная по структуре и содержанию ХТМЛ страница, верно?
Вот такого в общем вида как ты сам принес:
<!DOCTYPE html> //начало шаблона head.php - назвать можно как угодно на самом деле, лишь бы тебе было понятно
<html>
<head>
... //обязательная служебная инфа
</head>
<body> //тут уже пошел "видимый юзеру хтмл
<header>
... // сюда ты запихнешь шапку, которая повторяется у тебя на каждой странице, с меню, контактами, логотипом и прочим
</header> //конец шаблона header.php
<div class="content"> //начало шаблона page1.php например
... а вот тут у тебя уже контент который зависит на странице от того какой пользователь пришел к нам, или чего он хочет
</div> //конец шаблона page1.php
<footer> // начало шаблона footer.php
... // здесь будет подвал, который тоже одинаков для каждой страницы,
</footer>
</body>
</html> //конец шаблона footer.php
>>800174
>Почему для разных шаблонов используются разные функции require/include?
Ну допустим за тело самой страницы может отвечать юзер, создавая какие-нибудь товары и прочее. Поэтому написал инклуд, что бы если страница вдруг проебется, то не было бы фатал ерора. Поясни если не прав
>>800014
Ну смотри, давай разберем, что тебе нужно. У тебя должна после всех твоих инклудов и сборов по частям, просто получиться правильная по структуре и содержанию ХТМЛ страница, верно?
Вот такого в общем вида как ты сам принес:
<!DOCTYPE html> //начало шаблона head.php - назвать можно как угодно на самом деле, лишь бы тебе было понятно
<html>
<head>
... //обязательная служебная инфа
</head>
<body> //тут уже пошел "видимый юзеру хтмл
<header>
... // сюда ты запихнешь шапку, которая повторяется у тебя на каждой странице, с меню, контактами, логотипом и прочим
</header> //конец шаблона header.php
<div class="content"> //начало шаблона page1.php например
... а вот тут у тебя уже контент который зависит на странице от того какой пользователь пришел к нам, или чего он хочет
</div> //конец шаблона page1.php
<footer> // начало шаблона footer.php
... // здесь будет подвал, который тоже одинаков для каждой страницы,
</footer>
</body>
</html> //конец шаблона footer.php
>>800174
>Почему для разных шаблонов используются разные функции require/include?
Ну допустим за тело самой страницы может отвечать юзер, создавая какие-нибудь товары и прочее. Поэтому написал инклуд, что бы если страница вдруг проебется, то не было бы фатал ерора. Поясни если не прав
А я то думал у вас здесь филиал быдла. Ладно, больше не буду
По сути, обычный MVC, только немного переименованный, видимо с целью запутать людей:
- они зачем-то называют контроллер "роутом"
- они называют набор данных для view "моделью"
- они делают типичную ошибку начинающего, думая что 1 контроллер = 1 модель
- нагородили свою систему объектов с Ember.Object. Напомню, что когда у вас появляется желание наследовать все свои объекты от одного базового класса - с вашей ООП моделью что-то не так.
- лезут в стандартные прототипы
- интеграционный тест из примера https://guides.emberjs.com/v2.6.0/tutorial/simple-component/ ужасный, содержит много знаний о внутреннем устройстве страницы и скорее всего очень легко ломается
Хотя конечно в сравнении с каким-нибудь ангуларом или реактом он еще относительно прилично смотрится.
>>800245
нет, оно же ничего не делает.
Не ОП, но по своему скудному опыту скажу, что в небольших приложениях одна страница - один контроллер. Много страниц (много контроллеров) могут работать с одной и той же моделью.
На сайте статей модель Article может использовать как ArticleController (для показа статьи обычному пользователю), так и AdminController (для управления статьями).
> модель Article может использовать как ArticleController
*модель Article может использоваться как ArticleController'ом ...
Так понятней.
file_get_contents получаю html код себе на localhost ,
рву относительные ссылки изображений "../" на "https://2ch.hk/... (М)" но картинок не получаю
в чем я не прав помогите!
Функции file_get_contents ты должен скормить url вида https://2ch.hk/pr/src/793705/14689382342860.jpg. (М)
Из того, что пике 1 нужно получить то, что на пике 2. Убери 2 точки и склей это с https://2ch.hk/pr/res (М)
ОП! Я хочу сделать сайт с независимой навигацией двух или трех типов (отдельные меню, возможность нахождения в двух или трех категориях одновременно и т. д.)? Как это правильно делать и как быть с поисковой оптимизацией (ссылки на одни и те же материалы сайта будут встречаться в разных категориях), как быть с содержимым адресной строки, которую хочется сделать логичной? Было бы здорово, если бы ты показал простейший пример. Очевидные теги использовать не хочется, потому что в моем случае это будет выглядеть как сайтнейм.ру/тэгс/статья+стратегия+андроид+айос+винфон+платные+популярное, лол. Кроме того, теги я итак хочу, но в них будет совсем другое (компания-дистрибьютор например, авторы и прочее)
Конкретно: хочу сделать сайт про игрушки (не пинай за это, вопрос ведь не об этом), эти игрушки с одной стороны подразделяются по жанрам на стратегии, шутеры, гонки и ммо, с другой стороны по платформе (мобильники, десктоп, консоли), с третьей - на платные и бесплатные и так далее. А материалы про них - на статьи, обзоры, сравнения, новости и другие. Вот хотя бы жанр и тип материала хотелось бы вынести в два независимых меню, остальное оставив на теги. Возникают описанные выше проблемы с содержимым юрл-бара, индексацией, способом хранения.
Ты читал мой урок https://gist.github.com/codedokode/772a4ccc03e41d6b7cba ?
Есть разные подходы.
> сайтнейм.ру/тэгс/статья+стратегия+андроид+айос+винфон+платные+популярное,
Это ерунда какая-то.
Для начала можно попробовать сделать минималистичную схему, убирая все лишнее:
- страница игры /game/final-fantazy или /game/123
- информация о платформе и играх для нее /platform/android
- список игр в жанре /genre/strategy
Но если ты делаешь страницу /genre/strategy то хорошо бы чтобы это была именно страница про стратегии, например статья с кратким обзором популярных стратегий, а не тупо список ссылок на игры. Я не разбираюсь в СЕО, но сомневаюсь что поисковик будет высоко ценить страницу на которой 0 уникального контента. Да и нужна ли она посетителям твоего сайта?
Для страниц которые включают в себя поиск по нескольким критериям вообще не надо делать отдельные УРЛ. Пусть это будет поиск вроде /games?genre=strategy&platform=android. Все равно эти автосгенерированные страницы имеют нулевую ценность для поисковиков. Это просто модификация страницы /games со списком ссылок на игры.
В общем, я тебе советую придерживаться такого принципа: уникальный УРЛ = уникальная страница. Список, отфильтрованный по какому-то критерию, новой страницы не создает.
Что касается статей и обзоров, подумай, как пользователю будет удобнее их читать. Может быть стоит вывести ленту последних статей, как на хабре, может стоит на главной сделать топ обзоров, может как-то еще. Может люди в основном захоядт из поиска в гугле по названию игры.
Я гуглил array_rand, но у меня с ним не получается, выдаёт непонятно что. Если тебя не затруднит, то не мог бы ты пару строчек с array_rand мне показать?
А ты мануал читал? Ты знаешь что возвращает array_rand? Она возвращает случайный ключ из массива. Ты должен после этого по ключу взять значение элемнета. Ты знаешь, как это сделать? для этого используются квадратные скобки.
Спасибо за подробный ответ!
>Также, обычно вместо него используют модель, то есть класс примерно такого вида
То есть в моем случае, т.к. это форма для ввода значений для расчета кредита, модель будет выглядеть так:
class Credit
{
public $amount;
public $percent;
public $payment;
}
> Ты пишешь универсальные классы для любой формы или для какой-то конкретной?
> Как минимум валидация в каждой форме будет своя.
Я делаю ее для задачи расчета кредита, но хочу чтобы ее можно было использовать для последующих задач.
>Как минимум валидация в каждой форме будет своя.
>Или, что лучше, валидировать конкретную модель без привязки к форме: StudentValidator->validateStudent(Student) -> errors
А как связать поля формы и модели? И нужно валидировать и форму и модель, т.е. два валидатора?
Controller будет отправлять форму (модель) на валидацию?
Пытался использовать квадратные скобки, не получилось что-то, я необучаемый
Спасибо за ответ, это один из лучших тредов )
>Тайп-хинты не имеют отношения к валидации.
Имел в виду, какой класс должен отправить значения полей формы на валидацию, Controller (MainScript) правильно? Класс User (Модель) - этим не занимается?
>Валидация может быть произвольной. Ну например проверить что год рождения указан от A до B или что данного значения нет в базе данных. Валидация может связывать несколько полей, например проверить что поля совпадают или что значеие одного поля не противоречит другому.
Получается Валидатор должен иметь несколько методов на все случаи жизни, или делать под каждый случай новый Валидатор? Тогда и контроллер должен знать в какой Валидатор отправить значения, или какой метод запустить? Ила Валидатор может получить эту информацию из Модели (User\Value) и решить как правильно проверять значение?
>Информацию о типах значений можно хранить в 2 местах:
То есть нужно проверять и модель и форму на соответствие формату введенные значения?
Вот хорошее объяснение: http://stackoverflow.com/a/19609171
Если коротко - просто поправь в bootstrap.min.css пути к иконкам (пик).
Спасибо.
Для формы расчета кредита использовать столько классов - переусложнение. Ну пусть там будет класс CreditParams (чтобы не возиться с массивами), пусть там будет класс Errors, наверно этого хватит. Валидацию можно сделать просто функцией, расчет кредита - другой функцией. При желании валидацию и расчет кредита можно даже объединить.
Не переусложняй систему бед надобности. В коде на 50 строчек не надо делать много классов. Дойдешь до задачи про студентов и там развернешься.
> А как связать поля формы и модели? И нужно валидировать и форму и модель, т.е. два валидатора?
Зависит от ситуации. Если у тебя форма не совпадает с моделью, то да, 2 валидатора, один для модели, другой для формы (вызывает валидатор модели для тех полей которые есть и там и там). Но это не очень часто бывает.
> Controller будет отправлять форму (модель) на валидацию?
Контроллер принимает данные из GET, вызывает валидацию и получение результата, вызывает шаблон для вывода данных.
В догонку...
https://github.com/TheSidSpears/Students/blob/master/app/classes/Authorization.php#L12
> function __construct($container){
> перечитай урок про DI. Это service locator и это плохая вещь.
Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
Добавил setHash(). Еще что-то нужно? У меня нет идей
> В student->addInfo есть проблема. У тебя нет фильтрации по разрешенными полям и пользователь может менять любые свойства студента в том числе те, которых нет в форме. ну например что если мы добавим колонку is_admin - пользователь сможет передать $POST['is_admin'] = 1 при редактирвоании. И кстати об этом было написано в моем уроке.
Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L66
> function __construct(Student $s, $container, $id=NULL){
> Почему ты пишешь код валидации в конструкторе? И почему передаешь контейнер? Почитай про DI.
- Я переписал __construct так
$this->table=$table;
$this->validate();
return $this->errors;
потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
https://github.com/TheSidSpears/Students/blob/master/app/classes/ViewHelper.php
> тут слишком много всего понамешано.
Понамешано? Я тебя не понял
В догонку...
https://github.com/TheSidSpears/Students/blob/master/app/classes/Authorization.php#L12
> function __construct($container){
> перечитай урок про DI. Это service locator и это плохая вещь.
Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
Добавил setHash(). Еще что-то нужно? У меня нет идей
> В student->addInfo есть проблема. У тебя нет фильтрации по разрешенными полям и пользователь может менять любые свойства студента в том числе те, которых нет в форме. ну например что если мы добавим колонку is_admin - пользователь сможет передать $POST['is_admin'] = 1 при редактирвоании. И кстати об этом было написано в моем уроке.
Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L66
> function __construct(Student $s, $container, $id=NULL){
> Почему ты пишешь код валидации в конструкторе? И почему передаешь контейнер? Почитай про DI.
- Я переписал __construct так
$this->table=$table;
$this->validate();
return $this->errors;
потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
https://github.com/TheSidSpears/Students/blob/master/app/classes/ViewHelper.php
> тут слишком много всего понамешано.
Понамешано? Я тебя не понял
> Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
Да, это обычно удобнее. В Симфони тоже так сделано.
>> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
> Добавил setHash(). Еще что-то нужно? У меня нет идей
Принцип единой ответственности подразумевает, что каждый класс решает свою задачу, соответственно класс авторизации должен содержать в себе функционал, позволяющий:
- авторизовать пользователя
- убрать авторизацию (разлогиниться)
- проверить наличие авторизации, может быть определить авторизованного пользователя
Метод setHash на мой взгляд, это не "залогинить пользоваетля". Как минимум его надо переименовать.
Тут опечатка: if (empty($isAuthorized)) { - пропущено this. Если бы ты не использовал empty, ты бы сразу увидел ошибку. Потому - не применяй empty к отдельной переменной.
> Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
Откуда я могу об этом догадаться? И нет, не элегантно, так как могут добавиться новые поля и неизвестно, можно ли их редактировать. Что если там будет публичное поле isAdmin? Нужна фильтрация, может быть в контроллере, может в модуле отвечающем за формы.
> потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
Во-первых, конструктор не может вернуть значение. Во-вторых, ООП не подразумевает такого использования объектов. В-третьих, если получать валидатор из контейнера, то будет опять же одна строка.
Конструктор лишь подготавливает объект к работе. Он не должен заниматься валидацией.
>> тут слишком много всего понамешано.
> Понамешано? Я тебя не понял
Посмотри на список полей. Их так много что класс напоминае God Object ( https://ru.wikipedia.org/wiki/Божественный_объект )
Контейнер надо убрать. Также, я вижу как минимум что тут смешан класс для генерации УРЛ и класс с статическими функциями-утилитами. Для функций надо расставить private/public. название тоже неправильное. Можно подумать что это универсальный класс но на самом деле он умеет генерировать УРЛ только для таблицы студентов с разными видами сортировок - это надо отразить в названии.
> Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
Да, это обычно удобнее. В Симфони тоже так сделано.
>> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
> Добавил setHash(). Еще что-то нужно? У меня нет идей
Принцип единой ответственности подразумевает, что каждый класс решает свою задачу, соответственно класс авторизации должен содержать в себе функционал, позволяющий:
- авторизовать пользователя
- убрать авторизацию (разлогиниться)
- проверить наличие авторизации, может быть определить авторизованного пользователя
Метод setHash на мой взгляд, это не "залогинить пользоваетля". Как минимум его надо переименовать.
Тут опечатка: if (empty($isAuthorized)) { - пропущено this. Если бы ты не использовал empty, ты бы сразу увидел ошибку. Потому - не применяй empty к отдельной переменной.
> Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
Откуда я могу об этом догадаться? И нет, не элегантно, так как могут добавиться новые поля и неизвестно, можно ли их редактировать. Что если там будет публичное поле isAdmin? Нужна фильтрация, может быть в контроллере, может в модуле отвечающем за формы.
> потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
Во-первых, конструктор не может вернуть значение. Во-вторых, ООП не подразумевает такого использования объектов. В-третьих, если получать валидатор из контейнера, то будет опять же одна строка.
Конструктор лишь подготавливает объект к работе. Он не должен заниматься валидацией.
>> тут слишком много всего понамешано.
> Понамешано? Я тебя не понял
Посмотри на список полей. Их так много что класс напоминае God Object ( https://ru.wikipedia.org/wiki/Божественный_объект )
Контейнер надо убрать. Также, я вижу как минимум что тут смешан класс для генерации УРЛ и класс с статическими функциями-утилитами. Для функций надо расставить private/public. название тоже неправильное. Можно подумать что это универсальный класс но на самом деле он умеет генерировать УРЛ только для таблицы студентов с разными видами сортировок - это надо отразить в названии.
> Имел в виду, какой класс должен отправить значения полей формы на валидацию, Controller (MainScript) правильно? Класс User (Модель) - этим не занимается?
Не занимается. Задача модели - хранить информацию о пользователе.
> Получается Валидатор должен иметь несколько методов на все случаи жизни, или делать под каждый случай новый Валидатор? Тогда и контроллер должен знать в какой Валидатор отправить значения, или какой метод запустить? Ила Валидатор может получить эту информацию из Модели (User\Value) и решить как правильно проверять значение?
Для каждой модели нужен свой класс-валидатор. Однако, для многих полей испоьзуются стандартные виды проверок (проверить что поле заполнено, проверить длину, проверить по регулярке) и можно наследовать валидаторы от базового класса, предоставляющего стандартные методы для наиболее частых случаев.
Раз уж ты интересуешься всем этим, советую почитать комментарии к этой задаче - https://github.com/codedokode/pasta/blob/master/student-list.md
> Ила Валидатор может получить эту информацию из Модели (User\Value) и решить как правильно проверять значение?
Это годится только для типовых случаев, например проверка на длину. А если у тебя нестандартная проверка, как ты эту информацию закодируешь?
Я тебе советую глянуть (если ты понимаешь английский) компонент симфони для валидации. Он позволяет с помощью аннотаций помечать правила валидации модели: https://symfony.com/doc/current/book/validation.html
Это именно независимый компонент, он не требует наличия полной версии симфони и может использоваться отдельно (это большой плюс компонентов симфони).
>>Информацию о типах значений можно хранить в 2 местах:
> То есть нужно проверять и модель и форму на соответствие формату введенные значения?
Если у формы есть каике-то поля, которых нет у модели то для их проверки нужен отдельный валидатор. Если поля совпадают то проверять данные формы можно валидатором модели.
Стандарта нет, но есть библиотеки. Давай я научу тебя как их искать:
http://phptrends.com/dig_in/authorization
https://packagist.org/search/?search_query[query]=authorization
http://pronskiy.com/php-digest/ - ввести "авторизация" в поиск
Будет неплохо если ты посмотришь самые популярные библиотеки и тут напишешь свое мнение про их плюсы и минусы.
Также, если тебе нужна авторизация через соцсети, для этого тоже есть библиотеки.
>>800270
Один контроллер может использовать несколько моделей.И наоброт. Я правда перепутал, в эмбере функция model() возвращает не модель, а набор данных для шаблона (ViewModel?).
>>800265
Я перепутал, в эмбере функция model() возвращает не модель из MVC, а набор данных для шаблона (ViewModel?).
>>800219
> Ну допустим за тело самой страницы может отвечать юзер, создавая какие-нибудь товары и прочее. Поэтому написал инклуд, что бы если страница вдруг проебется, то не было бы фатал ерора. Поясни если не прав
Нужно делать фатал еррор - это называется fail fast: https://habrahabr.ru/post/218325/
Не надо скрывать ошибки - надо их исправлять. если нельзя отобразить страницу, надо показывать страницу 503.
Стандарта нет, но есть библиотеки. Давай я научу тебя как их искать:
http://phptrends.com/dig_in/authorization
https://packagist.org/search/?search_query[query]=authorization
http://pronskiy.com/php-digest/ - ввести "авторизация" в поиск
Будет неплохо если ты посмотришь самые популярные библиотеки и тут напишешь свое мнение про их плюсы и минусы.
Также, если тебе нужна авторизация через соцсети, для этого тоже есть библиотеки.
>>800270
Один контроллер может использовать несколько моделей.И наоброт. Я правда перепутал, в эмбере функция model() возвращает не модель, а набор данных для шаблона (ViewModel?).
>>800265
Я перепутал, в эмбере функция model() возвращает не модель из MVC, а набор данных для шаблона (ViewModel?).
>>800219
> Ну допустим за тело самой страницы может отвечать юзер, создавая какие-нибудь товары и прочее. Поэтому написал инклуд, что бы если страница вдруг проебется, то не было бы фатал ерора. Поясни если не прав
Нужно делать фатал еррор - это называется fail fast: https://habrahabr.ru/post/218325/
Не надо скрывать ошибки - надо их исправлять. если нельзя отобразить страницу, надо показывать страницу 503.
> "/(^ )/u", //пробелы в начале строки
Их наверно проще через trim удалять
> $regExp[1]
Это не очень хорошо читается так как надо искать нужный элемент глазами. Лучше класть регулярки в переменные или сразу вписывать в preg_replace напрямую.
> $letters = preg_split("//u", $text,-1,PREG_SPLIT_NO_EMPTY);
>$letters[0] = mb_strtoupper($letters[0]);
тут излишне разбивать на символы - проще взять первый символ через mb_substr
Чтобы не было проблем с троеточием, надо модифицировать регулярку "/ ([.,?!:]) */u", а то, что у тебя больше напоминает "костыль".
>>794246
> $words = preg_split("/\b/ui",
на слова лучше разбивать пробелом
В остальном верно.
>>794248
http://ideone.com/tcJqI0
> $regexp = '/\n/';
Тут незачем регулярки использовать, хватит простого explode
> $maxlength = mb_strlen($lines[0]);
лучше бы найти максимальную дину всех строк, например с помощю max и array_map, это короче чем писать цикл.
> for ($column = 0; $column < $numberOfColumn; $column++) {
Тут наверно foreach лучше подойдет
> $lines[$column] = mb_substr($lines[$column], 1);
Это что-то странное, зачем ты обрезаешь исходную строку? Это как минимум усложняет понимание кода.
http://ideone.com/yWwikd
> for ($participant = 0; $participant < $total; $participant++) {
>$seats[$participant] = $participant + 1;
Тут нельзя использовать функцию range()? Или array_fill?
> for ($participant = 0; $total >= $skip; $total--) {
Немного сбивает с толку то, что используются разные переменные.
> if ($participant <= $total - $skip) {
> $participant = $participant + $skip - 1;
Запретить значению выходить за определенный предел удобнее с помощью операции "деление с остатком", %.
> unset($seats[$participant]);
> sort($seats);
Для перенумерации выгоднее использовать array_values. Однако для удаления элемента из массива с перенумерацией есть готовая функция array_splice.
> for ($PlacesToEnd = $skip; $PlacesToEnd > 0; $PlacesToEnd--) {
> $placeInNewCircle++;
По моему весь этот цикл можно заменить на сложение и остаток от деления.
В общем, код стоит упростить. Пока он переусложнен.
> "/(^ )/u", //пробелы в начале строки
Их наверно проще через trim удалять
> $regExp[1]
Это не очень хорошо читается так как надо искать нужный элемент глазами. Лучше класть регулярки в переменные или сразу вписывать в preg_replace напрямую.
> $letters = preg_split("//u", $text,-1,PREG_SPLIT_NO_EMPTY);
>$letters[0] = mb_strtoupper($letters[0]);
тут излишне разбивать на символы - проще взять первый символ через mb_substr
Чтобы не было проблем с троеточием, надо модифицировать регулярку "/ ([.,?!:]) */u", а то, что у тебя больше напоминает "костыль".
>>794246
> $words = preg_split("/\b/ui",
на слова лучше разбивать пробелом
В остальном верно.
>>794248
http://ideone.com/tcJqI0
> $regexp = '/\n/';
Тут незачем регулярки использовать, хватит простого explode
> $maxlength = mb_strlen($lines[0]);
лучше бы найти максимальную дину всех строк, например с помощю max и array_map, это короче чем писать цикл.
> for ($column = 0; $column < $numberOfColumn; $column++) {
Тут наверно foreach лучше подойдет
> $lines[$column] = mb_substr($lines[$column], 1);
Это что-то странное, зачем ты обрезаешь исходную строку? Это как минимум усложняет понимание кода.
http://ideone.com/yWwikd
> for ($participant = 0; $participant < $total; $participant++) {
>$seats[$participant] = $participant + 1;
Тут нельзя использовать функцию range()? Или array_fill?
> for ($participant = 0; $total >= $skip; $total--) {
Немного сбивает с толку то, что используются разные переменные.
> if ($participant <= $total - $skip) {
> $participant = $participant + $skip - 1;
Запретить значению выходить за определенный предел удобнее с помощью операции "деление с остатком", %.
> unset($seats[$participant]);
> sort($seats);
Для перенумерации выгоднее использовать array_values. Однако для удаления элемента из массива с перенумерацией есть готовая функция array_splice.
> for ($PlacesToEnd = $skip; $PlacesToEnd > 0; $PlacesToEnd--) {
> $placeInNewCircle++;
По моему весь этот цикл можно заменить на сложение и остаток от деления.
В общем, код стоит упростить. Пока он переусложнен.
> Задача про телефонные номера: http://ideone.com/k4Man9
Верно
> "усложненная" задача про номера: http://ideone.com/5qNwL9
Верно.
> Автозамена: http://ideone.com/uxO9zY
Все правильно.
Шифровка: Сл131 Тр6ть6му Р6#ху!
Дешифровка: Слава Третьему Рейху!
Пацаны, я Энигму создал.
Суровых лет замены нету
Я умираю смысл жизни
Жиза, пиздец...
Спасибо, попробую Sentinel
Не лучше ли хешировать файлы?
олсо. прочитал в одной вакансии про самостоятельное поднятие сервера и начал гуглить. Понял что ничего об этом не знаю, кроме того что описано в обычных учебниках по php. Прочитал про сервера, нашел туториалы как их настраивать, но мне ни как не дойдет как это сделать. Как мне тестово настроить сервер? мне нужно его покупать или можно это сделать на своем компе? сейчас ничего не пойму, прошу помощи объяснить
>>801191
> Погуглите за меня сайт с вакансиями
> Объясните как подымать сервер
Почему ты такой несамостоятельный? Какой сервер, ты хочешь, чтобы сайт из твоей локальной сети был виден всему миру? Вот: http://varkon.biz/2010/08/kak-sdelat-dostup-k-apache-iz-interneta/
Если вообще нулячий, то можешь попробовать следующее:
1. Поставить на виртуалку Ubuntu, засетапить там LAMP, залить туда сайт.
2. Научится заходить на этот сайт из хостовой ОС (той, на которой ты запустил виртуальную машину). Если разберёшься, то многое прояснится.
Но это если хочешь что-то понять. Если понимать не обязательно, то бери heroku. Ну и обязательно нужно знать про домены-хостинги, всё разжёвано донельзя: http://www.postroika.ru/hosting/
Погуглил за тебя.
>>801219
Видимо, пользовался денвером-большой-красной-кнопкой.
я нашел много сайтов с вакансиями на каждом нужно регаться, хочу узнать про один толковый, а не сотню хуйпойми чего.
Про сервер тоже прогуглил но ничего не понял вот и пытаюсь узнать. Это же блядь имиджборда.
слышал. вопрос в том что сервер я так понял это машина. я могу поднять его и на своем компе?
Apache посмотри..
Ты где учился языку-то, как ты смотрел, что код исполняется вообще? Троллишь так, что ли, чертяка?
Это же как устраиваться работать в такси, но не иметь водительских прав.
Анон выше тебе всё расписал.
вообще нулячий в серверах.
с первым я разберусь, а что дальше? что на нее ставить где почитать? нихуя не пойму пока и не прошу все по полочкам раскладывать, просто ссылки на инфу покидайте
> У тебя должна быть система публикации скриптов
Не подскажешь как она называется? Что-то я не могу подобное найти, ищу по запросам в стиле "как скачивать js библиотеки composer".
http://ideone.com/wBq4H7 — доллары и рубли
http://ideone.com/hkA81Q — имитация броска кубика
http://ideone.com/ug2qIV — игра в кубики
http://ideone.com/whLSCq — таблица умножения
http://ideone.com/qODyPA — миллион в банке
вот я умею настроить только локальный сервак по туториалам и виртуальные хосты.
а сложно ли сделать сервак, чтобы он был доступен для других в интернете?
Ну почитай те ссылки, что я тебе нагуглил. Не траллируй, я сейчас материться начну.
Всё хорошо, продолжай.
1) https://ideone.com/4gty5H
2) https://ideone.com/tZI7Fp
3) https://ideone.com/L7JdaE
не понял, почему есть 12 строка, и можно ли от неё избавиться?
>$difference = $paymentTotal - 40000;
Если хочешь потом посчитать разницу, то лучше изначально $creditBalance сохранить дополнительно в соответствующей переменной:
>$parentCreditBalance = $creditBalance;
А затем уже в самом конце отнять от $paymentTotal этот $parentCreditBalance.
В этом случае легче обслуживать код - не надо менять цифру в самом конце, когда, допустим, меняешь сумму кредита изначально.
А так всё хорошо выглядит, задача правильно решена.
Есть бд, на сайт должны выводиться выборки с этой бд.
Мне эту хуйню надо разработать и протестить на своём компутере (что называете локальным сервером, так?)
Т.е. для разработки мне нужно установить:
1. сервер (какой?)
2. среду разработки (как я понял в тредне пхпшторм, пойдёт?)
3. настроить эту среду (тяжело ли настраивать пхпшторм? компиляторы, хуяторы, проверку синтаксиса, дебаг, есть там это всё из коробки или надо поставить 200 плагинов?)
4. браузер, в котором можно видеть результат (а можно без браузера? консоль там или ещё что)
Где про это можно подробно почитать? Вообще про взаимодействие сайта с сервером. Что пишется на js, что на php, как запросы формировать, вот это всё, как данные выдавать, асинхронность, вот это всё, рожь, зелень.
Я к вам из c++ пришёл и голова с вашей хуйни забубённой просто пухнет, думал за вечер установлю всё необходимое, в итоге не установил нихуя.
>1. сервер (какой?)
Обычный веб-сервер, который слушает определенный порт и отдает веб-страницы пользователям которые к нему обращаются. Их существует много, но для новичков тут часто советуют апач (Apache HTTP Server - https://httpd.apache.org/ ). Но одного веб-сервера мало, он умеет только отдавать только обычную статику (т.е. файлы html которые лежат в его корневой директории), для динамики к серверу нужно будет поставить интерпретатор PHP. Как это сделать и как оно работает можешь почитать тут https://github.com/codedokode/pasta/blob/master/soft/apache-install.md там есть секция Q&A которая поможет тебе разобраться во всем получше.
>2. среду разработки (как я понял в тредне пхпшторм, пойдёт?)
Необязательно среду, тут уже вкусовые предпочтения. Некоторые используют редакторы типа Sublime Text или Atom. Они легче чем пхпшторм, не так нагружают компьютер, и для старых ноутбуков самое то. Конечно функционала там меньше, но все самое необходимое (линтер, дебаггер) можно настроить с помощью плагинов. Конкретно за пхпшторм рассказать не смогу, я им не пользуюсь. Может кто из анонов подскажет.
>а можно без браузера? консоль там или ещё что
Если к своему приложению сможешь написать клиент для работы с командной строкой - тогда можно. Я не думаю что тебе будет приятно читать в консоли html разметку файлов которые отдал сервер.
Так же, у ОПа есть еще несколько уроков, которые рекомендуется почитать
https://github.com/codedokode/pasta/blob/master/soft/php-install.md - про установку PHP
https://github.com/codedokode/pasta/blob/master/soft/web-server.md - про настройку веб-сервера с PHP, там же есть несколько задачек для закрепления\убеждения в том что ты все сделал правильно.
Окей смотри, меня ща обоссут местные устанавливатели ВРУЧНУЮ ПОДНЯТИЕ ЛИНУКСА + ПХП + МУСКУЛЭЛ + АПАЧ на локальном компе что бы лампово пердолится вечерами на локалхосте, но уверен что тебе я помогу.
Идешь на http://open-server.ru/download/
Скачиваешь бэйсик версию.
Устанавливаешь её, придложит еще доп компоненты мб установить тип библиотеки для винды и прочее, тоже ага.
1. В той папке куда ты установил всё, у тебя будет папка domains
2. Заходишь значит в domains, создаешь в ней папку с именем например loh.pidr
3. В этой папочке создаешь файл index.php
4. В этом файлике пишешь например: <?php echo "hello world" ?> сохраняешь
5. Запускаешь в значит open server x64.exe
6. В трее повяится красный флажок, правой кнопочкой по нему и жамкаешь запустить
7. После того как всё запустилось и флажок стал зелененьким заходишь в браузер и в адресной строке вбиваешь адрес http://loh.pidr
(опционально можно http://loh.pidr/index.php, но к этому файлу и так будет автоматом цепляться при заходе на просто loh.pidr)
8. Вот собственно ты и поднял у себя связку APACHE + PHP + MYSQL на винде
9. Редактируешь свои скрипт_нейм.php в папке loh.pidr, смотришь результат в браузере loh.pidr/скрипт_нейм.php
10. Удачи, если что спрашивай
11. Если вдруг лень качать open server, а без пожертвования он будет качаться часа 2, (могу залить куда-нибудь что бы быстрее скачать если не ссышь от левого анона брать файло) то можешь скачать http://www.denwer.ru/ и по их мануалу всё настроить, там немного отличается подход создания локального домена, но суть та же. Просто денвер устарел и не обновляется.
Окей смотри, меня ща обоссут местные устанавливатели ВРУЧНУЮ ПОДНЯТИЕ ЛИНУКСА + ПХП + МУСКУЛЭЛ + АПАЧ на локальном компе что бы лампово пердолится вечерами на локалхосте, но уверен что тебе я помогу.
Идешь на http://open-server.ru/download/
Скачиваешь бэйсик версию.
Устанавливаешь её, придложит еще доп компоненты мб установить тип библиотеки для винды и прочее, тоже ага.
1. В той папке куда ты установил всё, у тебя будет папка domains
2. Заходишь значит в domains, создаешь в ней папку с именем например loh.pidr
3. В этой папочке создаешь файл index.php
4. В этом файлике пишешь например: <?php echo "hello world" ?> сохраняешь
5. Запускаешь в значит open server x64.exe
6. В трее повяится красный флажок, правой кнопочкой по нему и жамкаешь запустить
7. После того как всё запустилось и флажок стал зелененьким заходишь в браузер и в адресной строке вбиваешь адрес http://loh.pidr
(опционально можно http://loh.pidr/index.php, но к этому файлу и так будет автоматом цепляться при заходе на просто loh.pidr)
8. Вот собственно ты и поднял у себя связку APACHE + PHP + MYSQL на винде
9. Редактируешь свои скрипт_нейм.php в папке loh.pidr, смотришь результат в браузере loh.pidr/скрипт_нейм.php
10. Удачи, если что спрашивай
11. Если вдруг лень качать open server, а без пожертвования он будет качаться часа 2, (могу залить куда-нибудь что бы быстрее скачать если не ссышь от левого анона брать файло) то можешь скачать http://www.denwer.ru/ и по их мануалу всё настроить, там немного отличается подход создания локального домена, но суть та же. Просто денвер устарел и не обновляется.
Да, а среда разработки можешь скачать https://www.sublimetext.com/
ассоциировать .php файлы с ним и в нем лампово работать
Весь этот "манулал" что бы тебе просто и безболезненно начать работать у себя на компе и делать полностью свои сайты на локальном серве, а не сидеть пердолиться несколько суток с установкой софта, в который нубу сложно въехать будет
Как подкачаешься в этом, то перейдешь на полностью настроенные самостоянельно серваки и прочие убунты.
>Есть бд, на сайт должны выводиться выборки с этой бд.
Тогда тебе надо разобраться как работать с базой данных с помощью php и вывести в читабельном (html) виде всё это на сайт. Просто напишешь свой скрипт для начла, который коннектится к бд, шлет запрос, получает ответ, и выводит его в браузер.
Подобное в люой книге по php есть обычно, но если совсем ленивый, то можешь на примере этого примера с офф сайта сделать для начала
http://php.net/manual/ru/mysql.examples-basic.php
Ща опять все навалятся, что mysql_ функции в php это деприкейтед и зашквар, но ты сделай для тренировки как тут, а потом на pdo или mysqli_* перейдешь.
Не вижу смысла устанавливать какую-то кривую сборку, когда установка компонентов по отдельности займет не намного больше времени.
Плюс в сборках часто устаревшие версии программ.
Плюс ты потеряешь время, когда захочешь например что-то настроить или поменять, так как все советы в интернете расчитаны на чистый апач, и на твоей сборке просто могут не заработать.
В догонку...
https://github.com/TheSidSpears/Students/blob/master/app/classes/Authorization.php#L12
> function __construct($container){
> перечитай урок про DI. Это service locator и это плохая вещь.
Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
Добавил setHash(). Еще что-то нужно? У меня нет идей
> В student->addInfo есть проблема. У тебя нет фильтрации по разрешенными полям и пользователь может менять любые свойства студента в том числе те, которых нет в форме. ну например что если мы добавим колонку is_admin - пользователь сможет передать $POST['is_admin'] = 1 при редактирвоании. И кстати об этом было написано в моем уроке.
Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L66
> function __construct(Student $s, $container, $id=NULL){
> Почему ты пишешь код валидации в конструкторе? И почему передаешь контейнер? Почитай про DI.
- Я переписал __construct так
$this->table=$table;
$this->validate();
return $this->errors;
потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
https://github.com/TheSidSpears/Students/blob/master/app/classes/ViewHelper.php
> тут слишком много всего понамешано.
Понамешано? Я тебя не понял
В догонку...
https://github.com/TheSidSpears/Students/blob/master/app/classes/Authorization.php#L12
> function __construct($container){
> перечитай урок про DI. Это service locator и это плохая вещь.
Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
Добавил setHash(). Еще что-то нужно? У меня нет идей
> В student->addInfo есть проблема. У тебя нет фильтрации по разрешенными полям и пользователь может менять любые свойства студента в том числе те, которых нет в форме. ну например что если мы добавим колонку is_admin - пользователь сможет передать $POST['is_admin'] = 1 при редактирвоании. И кстати об этом было написано в моем уроке.
Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
https://github.com/TheSidSpears/Students/blob/master/app/classes/StudentValidator.php#L66
> function __construct(Student $s, $container, $id=NULL){
> Почему ты пишешь код валидации в конструкторе? И почему передаешь контейнер? Почитай про DI.
- Я переписал __construct так
$this->table=$table;
$this->validate();
return $this->errors;
потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
https://github.com/TheSidSpears/Students/blob/master/app/classes/ViewHelper.php
> тут слишком много всего понамешано.
Понамешано? Я тебя не понял
Прошу прощения. Что-то у меня проглючило
Кстати, т.к. этот пост был написан раньше, посмею предположить, что ОП его не заметил.
прошу прощение за много сообщений подряд
Посоны. Учил JS полгода, решил вкатиться заодно в PHP.
Смотрю в основном видосы 2011 года с thenewboston.com, попутно пилю чатик используя php для логина-куков и для ajax-запросов.
Появилось два вопроса:
Не слишком ли я устаревший материал изучаю?
Нормально ли использовать пхп только как веб апи?
Не старое, пхп, как и жс - мёртворождённое говно, но даже несмотря на это человечество его использует столько лет, что натворило на этом дерьме почти все интернеты, и будет использовать его ещё больше.
>Не слишком ли я устаревший материал изучаю?
php и js маловато будет, нужны фреймворки.
>Нормально ли использовать пхп только как веб апи?
Что это значит?
Спасибо анонас, именно то что нужно, в этом опен сервере и отладчик есть, всё по уму. Желаю твоей матери крепкого здоровья и долгих лет жизни.
Ясно.
>>802335
>php и js маловато будет, нужны фреймворки.
Оно понятно, на жс я react уже поковырял, но без серверной части ограничен в пилении своих задумок был, а ноду я с первого захода как-то не осилил + из веб-хостингов её не все поддерживают.
>Что это значит?
Что я, возможно, выдумываю терминологию на ходу.
Я имею в виду, что пхп у меня почти только принимает ажакс запросы и отдает жсон, или же принимает жсон и записывает в .тхт файлик, я до баз данных еще не дошел ололо.
А чего не мертворожденное, я только начал просто. Поясните?
affiliate:
class: sfDoctrineRouteCollection
options:
model: JobeetAffiliate
actions: [new, create]
object_actions: { wait: get }
symfony app:routes frontend показывает нужные маршруты
affiliate_new GET /affiliate/new.:sf_format
affiliate_create POST /affiliate.:sf_format
affiliate_wait GET /affiliate/:id/wait.:sf_format
но при обращении в браузере на http://jobeet/frontend_dev.php/affiliate/new ошибка 500 Unable to find a matching route to generate url for params "array ( 'action' => 'index', 'module' => 'affiliate',)".
как решить проблему.
кровь из носа за оставшиеся 5 дней я должен его освоить, помогите пожалуйста.
>Аноны помогите пожалуйста учу symfony1.4
>symfony1.4
>1.4
Это что должно случиться в жизни человека, чтоб он себя так не любил?
начал гуглить, так как ошибка была явно не в моем коде, нагуглил вот это http://trac.symfony-project.org/ticket/9985 поправил как там изложено и все заработало, и че то меня дернула опять попробовать роуты из примера, и оно блять заработало, как блять так?! суки!
пошел устраиваться на работу джуном, сказали мол у них все пишут на symfony1.4, дали 2 недели на обучение. дали этот учебник, я блять думаю что не спроста они мне дали этот учебник, там у меня уже были приколы где приходилось править файлы фреймворка что бы он коректно работал
Помоги нубу, скажи ЧЯДНТ!
Скинули мне backup сайта и cms и бэкапы баз для них.
Как это запустить на локальной машине?
ОС MacOS X 10.11
вроде настроил apache(на локал хост заходи, папки видит)
Mysql тож вроде настроил
phpmyadmin
я положил в папку которая настроена для localhost этот бэкап, он мне выдает когда захожу туда
Error database: Acces denied for user...
Я пока могу только в верстку. Мне нужно этот бэкап запустить у себя, и понять как натянуть новую верстку на "самописную" CMS на codeIgniter.
Аноны спасайте!
Такие проблемы решаются не так. Надо посмотреть (поиском по тексту ошибки или по стектрейсу, что намного удобнее), где выбрасывается исключение. Там отладчиком или временным var_dump посмотреть значения переменных. Если они приходят из какой-то функции - залезть туда и тоже посмотреть. И так постепенно ты скорее всего дойдешь до причины ошибки.
Алсо, у тебя ошибка не при роутинге. У тебя ошибка при попытке сгенерировать УРЛ, например при выводе шаблона или еще чего-то.
Надо делать как я написал выше. Ты вместо того, чтобы найти причину и чему-то научиться пытаешься просто убежать от ошибки. Так не пойдет. На работе ты тоже так же поступать будешь?
Сочувствую.
У тебя в бекапе сайта, среди файлов кодигнайтера должен быть какой-нибудь конфиг файл. Причем не далеко в ядре, а где-то почти на поверхности.
Попробуй в
application/config/config.php
Судя по ошибке, у тебя твои скрипты просто не могут подцепиться к базе, если ты конечно её сложил к себе на локальный mysql сервер, если он у тебя конечно поднят 100%, а не ВРОДЕ БЫ
В общем берешь и настраиваешь в этом конфиге что бы скрипт ломился на локалхост и под юзером которого туда пустят.
Мануал вот есть вроде, думаю разверешься.
https://www.codeigniter.com/userguide3/database/configuration.html
1.Юзер заходит на сайт - проверить есть ли у юзера кука csrf_token, если нету - сгенерировать и установить
2. Когда юзер отправляет любую форму - взять эту куку и навесить на скрытый инпут либо в гет запрос добавить
3. Обработчик сравнивает полученный токен с тем который установлен у юзера в куках, если == обработать форму
И вопрос следом, нужно ли закреплять токен за юзером в базе? По другому я не вижу как это может защитить
Или striptags. Что-то не понятно.
нет, мухастранск
если бы я хотел просто убежать, я бы послал все нахер
Вчера ебался с шаблонизаторами, чтобы здоровенные функции PGSQL с похожим кодом в файлы миграций БД в несколько строчек генерировались.
И это пиздец. Шаблонизаторы (которые себя таковыми позиционируют) - нефункциональное говнище. Причём я не говорю о функциях работы с данными, а именно о работе с выводимым текстом - тем во, что шабонизатор должен мочь больше всего. Остановился на Nunjucks и чуть не сгорел от баттхёрта, когда там фильтр функции отступа (просто, блядь, 4 пробела!) сжирал весь текст внутри себя и переменные не присваивались. Причём репорты на ГитХабе висят.
А потом попробовал писать шаблоны прямо таки в php, компиля gulp-ом через 'php -f %файл%'. И это охуенно, аноны! PHP - охуенный шаблонизатор! Минималистичный синтаксис, куча встроенных функций и сторонних библиотек, быстрая скорость компиляции, большое комьюнити.
Не повторяйте моих ошибок, пацаны. Нужно сгенерировать статические файлы с шаблонизатором - берите PHP. 10/10, базарю!
>мой хуев начальник уже второй месяц заебывает меня чтобы я поднял интернет магазин А я не в зуб ногой в веб программинг, я блядь админ!, посоветуйте движок на котором это говно проще всего поставить?
Лучше посоветую тебе нахуй послать своего начальника.
Тогда меня вероятно уволят, а работу в моих ебенях не так уж и просто найти
Проще всего - OpenCart. Он устаревший и плагины ставятся ректальным путём (вообще всё, что не из коробки, ставится ректальным путём), однако своё дело делает. Ставится и настраивается просто.
У клиента на нём уже второй год запиленный мной сайт вертится. Ни одной жалобы, торговля идёт, сайт жив.
Трипл так-то не врёт.
Но можно и тупо Wordpress + плагин WooCommerce, там всё проще, а задачу решает точно так же.
> Далее простая, но полезная задача сделать список студентов...
> простая
> Время: 3-10 дней
Пишу чуть больше двух месяцев(((
Есть одна игрушка. Для каждого раунда она записывает этакий лог с очками и временем.
Табличка с раундами, games:
id level
1465 2
1464 1
Табличками с логами раунда, logs:
game_id score time
1465 21 30
1465 13 20
1465 10 10
1464 10 20
1464 5 10
Мне нужно получить среднее значение максимальных значений каждого раунда сгруппированных по уровням.
На пике мои натуги. Получилось вытащить максимальное значение раунда для каждого уровня и дальше я чет совсем загрустил. Записей в бд много, несколько миллионов, и с каждой неделей увеличивается еще на миллион.
WITH t AS (
SELECT
games.level AS level,
MAX(logs.score) AS score
FROM games
LEFT JOIN logs
ON games.id = logs.game_id
GROUP BY games.level
)
SELECT
t.level,
AVG(score)
...
FROM t
Стоп, я нихуя не понял, но этого тебе должно хватить.
Понял, спасибо.
Сделал, тестировать на проде в ночь на субботу зассал.
Анон, может можно его как-то оптимизировать? Может какие-нибудь индексы создать стоит?
http://paste.ofcode.org/7BMEj8r45QpjB3cFj7X8PP
На больших объёмах join всё равно индексы не использует, а других критериев у тебя и нет. Возможно завести индекс по времени логов, или партисипировать таблицу логов по времени, и в запросе указывать границы времени, за которое считать статистику.
При партисипировании можно актуальные логи при держать на быстром хранилище, а старые перемещать в архивное.
Какие есть ошибки в правильности так сказать подхода?
http://ideone.com/99vqwE
Хотели с знакомым заняться веб-проектом. Чтобы он учил js, css, html, а я серверную часть. Если я правильно называю это. Серверная чать - это ведь например RoR, Python + django, PHP? Наверняка эта тема уже обсасывалась много раз, но я не понимаю. Как использовать PHP в сайтах? То есть надо как-то сервер запускать? А как тогда это всё на полноценный хостинг/сайт перенести? Не понимаю. И как сейчас вообще PHP живёт? Не помер надеюсь?
Даже если ничего не получится, то плевать, главное, что тема эта интересна.
С сервером разобрался. Опять же он только локальный, чтобы протестировать работу например php. А как это всё дело на хостинг рандомный занести?
Я погуглил-погуглил и нехрена не понял что делать. Какой есть вариант кроме - удалить нахуй проект с гитхаба и создать заного?
Что я сделал не так, что гитхаб меня так наказывает?
>Какой есть вариант кроме - удалить нахуй проект с гитхаба и создать заного?
Закоммитить свои изменения перед пушем.
>git add .
Да, если из корня проекта, после этого изменения добавляются в индекс. Потом
git commit -m "Я сотворил неведомую херню"
Твои изменения закоммичены, их можно пушить.
Пушатся только коммиты. При выполнении git add изменения заносятся в индекс. Индекс - кандидат на коммит, закоммичены будут изменения, внесенные в индекс. Изменения не внесенные в индекс(не добавлены через git add) закоммичены не будут, их нельзя будет пушнуть.
Я вот второй день как вкатился, заебался на таблице умножения уже, хочется дропнуть нахуй.
Откуда информация о неиспользовании индексов при джойне таблиц с большим числом строк?
Спасибо
А как вызвать класс, если остались только файлы с классами, а мне запрещают писать в них голый пхп код?
Ламповая kоHфepенцNя вордпресс-джиквери-интеграторов нуждается в вашем высоком интеллекте. Сосёмся в дёсны, поясняем за хаскель и функциональщину на самом деле нет, реакты с редуксами, пайтон, джанго, правильный UX и другие никому не нужные вещи. Треш и угар гарантируем. С собой иметь плавки и бальзам Звёздочка.
http://url-cut.ru/539233
К делу:
Купил на собственные деньги недорогой хостинг, и собираюсь переносить свой проект туда. Тем более плюсы есть (доступность 24/7 из любого девайса с интернетом). Проблема в том, что данные, которые будут там храниться, никак не должны попасть случайным лицам. И если раньше все было легко, то как обеспечить безопасность на сервере я никогда даже не задумывался.
Прошу советов мудрых, хинтов, лайфхаков, может быть литературу или статьи в интернете (к сожалению, из-за работы не получается уделять много времени этому хобби, учился по php.net).
ты на свои деньги оплачиваешь хостинг для твоей шараги? И ещё за сохранность данных печёшься?
ты понимаешь, до какой степени ты не прав?
Проект - моя инициатива, упорядочивает данные и экономит кучу времени на бумажной волоките. Руководство не волнует как я делаю свою работу, с помощью программ или без, за 8 часов или остаюсь сверхурочно, нужно чтобы все было сделано и в срок. Так что это мне выгодно в первую очередь, остальные все равно ничего не понимают в интернетах дальше одноклассников. Без нее вернусь в дремучие времена, которые даже вспоминать страшно и уволюсь.
>>803567
БД удалили уже (после того как я ее сохранил на флешку), да и я не вижу проблемы использовать БД моего хостинг-провайдера, про безопасность PHP в работе с mysqli уже начал читать.
Буду задавать конкретные вопросы itt, начну вот с чего:
структура папок на хосте выглядит так:
корневой каталог(1)/мой_юзернейм(2)/public_html(3)
папка (3) доступна из интернета, в ней открываются все файлы. Есть ли смысл держать в ней html, css, js и одинфайл php, содержащий строку "<?php include_once '../index.php' ", а всю php-составляющую положить на уровень (2), куда доступа извне нет? Соответственно, просмотреть содержимое файлов (пароли к бд, конфиги) будет нельзя даже если что-то на сервере пойдет не так с php-компилятором.
Ламповая kоHфepенцNя вордпресс-джиквери-интеграторов нуждается в вашем высоком интеллекте. Сосёмся в дёсны, поясняем за хаскель и функциональщину на самом деле нет, реакты с редуксами, пайтон, джанго, правильный UX и другие никому не нужные вещи. Треш и угар гарантируем. С собой иметь плавки и бальзам Звёздочка.
http://url-cut.ru/539233
Админ у нас...это просто космос. В прошлый раз он переустановил виндуус не спросив никого и потер ВСЕ данные на компе, получил пизды, но он сын начальника и продолжает работать без образования, рашка такая рашка, да. Он сто процентов заниматься этим не будет.
>секретную базу данных
В том-то и дело, что хранятся там транзакции закупок, договора и другая документация. Конечно, организация у нас не секретная, но я не уверен что имею право размещать эту информацию где-либо, государственная же! Сидеть потом еще. В общем, ты советуешь наладить все внутри и не париться? Эх. Я сам понимаю, что должен такими вещами заниматься профессионал, но блжад их нет у нас.
.htaccess - первое, про что я подумал. Но меня остановило наличие аж двух папок вверх по каталогу, и предположил я что они для этого и созданы. (Хотя конечно нет, там хранятся логи, и вообще их использование не моего ума дело, но почему бы не урвать кусочек безопасного места?).
Есть права администратора на ПК? Тогда just do it.
> Есть ли смысл держать в ней html, css, js и одинфайл php, содержащий строку "<?php include_once '../index.php' ", а всю php-составляющую положить на уровень (2), куда доступа извне нет
Именно так и нужно делать. В публичную папку кладется только то, что предназначено для раздачи.
>>803589
Зачем искать какие-то костыли когда можно просто не выкладывать код наружу? Это костыли для CMS которые будут разворачивать неквалифицированные пользователи, не понимающие что такое публичная папка.
>>803590
Не стоит выгружать это на хостинг. Думаю, правильнее переставить mysql на другой порт и держать все внутри. В крайнем случае ты можешь ведь на свой компьютер все поставить.
Еще можно попробовать внутри виртуальной машины приложение развернуть если ресурсы позволяют.
>>803580
Вообще, конечно если ты делаешь программу для себя, а не веб-сайт, то ты выбрал не те технологии. Я бы писал на каком-нибудь С# десктопную программу с базой на sqlite. Или, если меня не очень беспокоит производительность, то писал бы программу на яваскрипте и запускал в electron (это штука, пакующая твое яваскрипт-приложение вместе с браузером в виндоуз-приложение).
>>803584
Хватит спамить. Написал один раз и хватит.
>>803491
Сделать файл index.php в котором написать просто скрипт, подключающий и вызывающий нужные классы.
>>803442
Слабак. ты еще даже до кредита не дошел.
> Есть ли смысл держать в ней html, css, js и одинфайл php, содержащий строку "<?php include_once '../index.php' ", а всю php-составляющую положить на уровень (2), куда доступа извне нет
Именно так и нужно делать. В публичную папку кладется только то, что предназначено для раздачи.
>>803589
Зачем искать какие-то костыли когда можно просто не выкладывать код наружу? Это костыли для CMS которые будут разворачивать неквалифицированные пользователи, не понимающие что такое публичная папка.
>>803590
Не стоит выгружать это на хостинг. Думаю, правильнее переставить mysql на другой порт и держать все внутри. В крайнем случае ты можешь ведь на свой компьютер все поставить.
Еще можно попробовать внутри виртуальной машины приложение развернуть если ресурсы позволяют.
>>803580
Вообще, конечно если ты делаешь программу для себя, а не веб-сайт, то ты выбрал не те технологии. Я бы писал на каком-нибудь С# десктопную программу с базой на sqlite. Или, если меня не очень беспокоит производительность, то писал бы программу на яваскрипте и запускал в electron (это штука, пакующая твое яваскрипт-приложение вместе с браузером в виндоуз-приложение).
>>803584
Хватит спамить. Написал один раз и хватит.
>>803491
Сделать файл index.php в котором написать просто скрипт, подключающий и вызывающий нужные классы.
>>803442
Слабак. ты еще даже до кредита не дошел.
> Если я правильно называю это. Серверная часть - это ведь например RoR, Python + django, PHP?
Да. И базы данных.
> То есть надо как-то сервер запускать?
Настраиваешь веб-сервер Апач и интерпретатор php и они будут принимать запросы от браузера и запускать твой код.
> А как тогда это всё на полноценный хостинг/сайт перенести?
Копируешь по SFTP. Лучше бы не руками, а написать bash-скрипт, который ты запускаешь и который обновляет сайт.
Некоторые деплоят через гит. Выгружаешь изменения в гит, а на сервере запускаешь скрипт, который вытягивает эти изменения.
В этом тебе помогут баш-скрипты, но если ты в них не силен, то придется освоить, на пхп это писать не очень удобно (хотя и возможно).
тут конечно есть недостатки что нет атомарности деплоя, то есть замена файлов происходит постепенно и в какой-то момент времени часть файлов старая, часть новая, а один файл наполовину записан. Ну думаю у тебя не такой посещаемый сайт чтобы об этом беспокоиться.
Для атомарности деплоя надо скриптом создавать новую папку, выгружать туда код, прогревать кеши (если они есть), собирать статику (если есть) , переключать путь к корню сайта в конфиге веб-сервера и затем дть ему сигнал перечитать конфиг. Тогда обновление происходит атомарно и без багов.
php companion
>>803289
неправда про большие объемы.
>>803187
перебор большого числа строк нельзя оптимизировать. тебе надро выполнять этот запрос в офлайне, то есть не при генерации страницы, а например раз в час по крону и класть результаты в кеш или в отдельную таблицу.
Ну вообще, представь что у тебя задача считать среднее из миллиона строк. Никакие индексы не оптимизируют перебор миллиона строк. даже если все данные в памяти, это все равно минимум пару секунд займет.
Как тут запрос оптимизировать? Считать раз в час по крону. А если нужно мгновенно обновлять среднее, а не раз в час? Тогда заводим 2 ячейки, в одной храним сумму значений, в другой их количество. Обновляем эти ячейки при каждой вставке в исходную таблицу.
>не те технологии
А я догадывался. Однажды спросил: что легче всего выучить и применить? Мне ответили PHP. ИЧСХ, все так и оказалось, работает же! Но теперь вот такая засада. Спасибо за electron, рассмотрю подробнее, ибо javascript уже использую, а всякие C пугают сложностью тестирования. Конечно десктопное приложение в моем случае идеально подойдет, нужно просто взять себя за яйца и посидеть разобраться. Жаль по образованию далеко от программирования.
Алсо запрос неправильный. У тебя внутренний подзапрос группирует по level, и внешний группирует по level, и среднее там посчитать не получится так как ты его считаешь из одного значения. в запросе явно ошибка.
Наверно во внутреннем запросе надо группировать по раундам.
>>803089
Ну вот, а чтобы считаться джуниором, надо уметь сделать это за 3-10 дней. так что больше пиши код.
>>802981
Зачем генерировать SQL скрипты? Почему на том же пхп не написать код который в цикле будет вызывать нужные запросы? По моему ты чем-то странным занимаешься.
> шаблоны прямо таки в php, компиля gulp-ом
Наркоман? зачем тут гульп если можно просто напрямую запустить php или сделать bash скрипт из 1 строки?
>>802923
Логика отображения. Сделай статический метод ViewUtil::formatBytes и вызывай.
>>802909
Вот ты странные вещи пишешь. Токен можно держать в куках. Сессия - это хранилище на сервере, которое идентифицируется куками. То есть те же куки, просто более сложный способ хранения. Зачем?
>>802895
Если ему не мешать.
>>802821
А мои статьи не годятся? Отсюда https://github.com/codedokode/pasta/tree/master/security
>>802810
В твиге по умолчанию включено автоэкранирование. Изучи, как оно работает.
>>802697
Нет. В этом случае твоя защита будет работать только для зарегистрированных пользователей, а не для всех.
>>802690
Да, верно, только одно дополнение:
> 1.Юзер заходит на сайт - проверить есть ли у юзера кука csrf_token, если нету - сгенерировать и установить
А если есть - то продлить ее жизнь, переустановив
Алсо запрос неправильный. У тебя внутренний подзапрос группирует по level, и внешний группирует по level, и среднее там посчитать не получится так как ты его считаешь из одного значения. в запросе явно ошибка.
Наверно во внутреннем запросе надо группировать по раундам.
>>803089
Ну вот, а чтобы считаться джуниором, надо уметь сделать это за 3-10 дней. так что больше пиши код.
>>802981
Зачем генерировать SQL скрипты? Почему на том же пхп не написать код который в цикле будет вызывать нужные запросы? По моему ты чем-то странным занимаешься.
> шаблоны прямо таки в php, компиля gulp-ом
Наркоман? зачем тут гульп если можно просто напрямую запустить php или сделать bash скрипт из 1 строки?
>>802923
Логика отображения. Сделай статический метод ViewUtil::formatBytes и вызывай.
>>802909
Вот ты странные вещи пишешь. Токен можно держать в куках. Сессия - это хранилище на сервере, которое идентифицируется куками. То есть те же куки, просто более сложный способ хранения. Зачем?
>>802895
Если ему не мешать.
>>802821
А мои статьи не годятся? Отсюда https://github.com/codedokode/pasta/tree/master/security
>>802810
В твиге по умолчанию включено автоэкранирование. Изучи, как оно работает.
>>802697
Нет. В этом случае твоя защита будет работать только для зарегистрированных пользователей, а не для всех.
>>802690
Да, верно, только одно дополнение:
> 1.Юзер заходит на сайт - проверить есть ли у юзера кука csrf_token, если нету - сгенерировать и установить
А если есть - то продлить ее жизнь, переустановив
если у тебя уже есть пхп приложение то наверно нет смысла его переписывать, если это не несет какой-то выгоды. Что касается запуска - при желании ты можешь даже сам себе сборку сделать, собрав вместе mysql, php, апач с конфигами и запуская их bat-скриптом когда тебе нужно.
$newNews = new News();
$newNews->title = 'Сенсация!';
$newNews->text = 'Текст новости';
// вставка в БД
$mapper->save($newNews);
VS
// создание новой
$newNews = News::create('Сенсация!', 'Текст новости');
// вставка в БД
$mapper->save($newNews);
?
...VS
// создание новой
$newNewsData = [
....'title' => 'Сенсация!',
....'body' => 'Текст новости'
];
$newNews = News::createFromArray($newNewsData);
// вставка в БД
$mapper->save($newNews);
Тут нет выгоды заменять хороший объект на плохой массив. Хотя в некотогрых языках есть синтаксис для создания объекта и простановки свойств, например
https://msdn.microsoft.com/ru-ru/library/bb397680.aspx
StudentName student4 = new StudentName
{
FirstName = "Craig",
LastName = "Playstead",
ID = 116
};
У нас в пхп такого нет, так что приходится использовать массивы. Но в твоем примере массив никакой выгоды не дает.
В моем приложении разделенная логика: интерфейс через html+js асинхронно посылает команды на php, который генерирует только json, из которого js рисует таблицы, списки, графику и тп. В общем, путь полной генерации страниц в php я прошел. С ajax-ом намного быстрее, плюс не засоряю мозги и код. Так что скомпилировать гуй в отдельное exe-приложение а не вкладку в браузере будет норм (бывает хромог без плагинов зависает на некрокомпах с антивирусами при открытых 5 вкладках со всякой ерундой)
>Но в твоем примере массив никакой выгоды не дает.
Как не дает?
А если у модели со временем появятся новые поля, значение которых надо будет устанавливать в зависимости от значений 'title' и 'body'? С таким массивом нам не потребуется менять код, вызывающий метод News::createFromArray(). А логику установки этих новых полей придется разрулить только в одном месте -- методе News::createFromArray(). Всё.
Причем не обязательно использовать массив:
// создание новой
$newNewsData = new NewsData();
$newNewsData->title = 'Сенсация!';
$newNewsData->body = 'Текст новости';
$newNews = News::createFromArray($newNewsData);
// вставка в БД
$mapper->save($newNews);
Разумеется, в NewsData мы опишем свойства title и body.
>а через конструктор почему бы не делать?
Чтобы можно было без лишних телодвижений сделать так:
class BreakingNews extends News {}
$newBreakingNews = BreakingNews::create(...);
BUMP
Ребят, кому не сложно - проверьте задачки.
"Grammar Nazi" сразу на исправление сделал, а Опечаточников на поиск.
https://ideone.com/qKlxkQ
https://ideone.com/LoFKwm
А вообще я наркоманю, и разницы тут нет.
Бамп вопросу, может оп не увидел.
Любители ноды пишут такие вещи на gulp, любители php пишут самописные скрипты на пхп, любители bash - на баше. Еще в линуксе есть make, который можно задействовать для этой цели (причем, что хорошо, он умеет обновлять только изменившиеся зависимости).
В общем, вариантов много. Самый известный это наверно gulp, но он завязан на ноду (яваскрипт), и на мой взгляд, там довольно уродливый синтаксис. Вообще, мне он не нравится, это выглядит как убогий велосипед в сравнении с make которому уже лет 40.
>>803733
Либо делать не статическими, либо прокинуть методы как глобальные функции твига.
Я подозреваю, там по каким-то причинам не хотят такое разрешать. Чтобы например не вызывали все подряд, а пользовались только предоставленными переменными и функциями.
Плюс костылики: http://stackoverflow.com/questions/6844266/twig-template-engine-using-a-static-function-or-variable
>>803707
6-10 месяцев. Учить придется не только php, но и html css js mysql.
>>803699
Никому не нужен твой стрим, и никто его не будет смотреть хотя бы потому что это пхп тред.
>>803651
Если при установке полей должна быть какая-то логика, то надо вместо полей использовать сеттеры:
$news->setTitle('....');
В других языках кстати есть синтаксис для того, чтобы сделать свойство, при обращении к которому вызывается метод:
https://msdn.microsoft.com/ru-ru/library/w86s7x04.aspx
Это по сути синтаксический сахар, который позволяет записывать вызов сеттера короче.
Твой подход с массивом проблему никак не решит.
> А логику установки этих новых полей придется разрулить только в одном месте -- методе News::createFromArray(). Всё.
Нет. Он не решает проблему изменения поля позже.
> Причем не обязательно использовать массив:
Это уже переусложнение - ты создал 2 класса, решающих одну и ту же задачу - хранение информации о новости.
>>803649
С аяксом вряд ли быстрее, отобразить готовую страницу гораздо быстрее (и браузер умеет делать это по мере загрузки), чем ждать пока загрузится страница, куча скриптов, пока все отрендерится.
Конечно есть случаи когда это необходимо: например, интерактивные приложения со сложным интерфейсом. Но если делать какой-то простой сайт, например учебник или блог - это только ухудшает удобство использования.
То есть надо смотреть по ситуации. А чтобы другие неопытные аноны сделали правильные выводы, я чуть-чуть прокомментирую твои высказывания.
> С ajax-ом намного быстрее,
Это надо постраться чтобы на пхп код работал медленнее чем код на пхп + передача данных + рендеринг страницы в яваскрипте.
> плюс не засоряю мозги и код.
Вообще, ты его усложняешь. Теперь в генерации страницы принимает участие не только пхп, но и яваскрипт.
> бывает хромог без плагинов зависает на некрокомпах с антивирусами при открытых 5 вкладках со всякой ерундой)
Это зависит от того, каике сайты открывать. реклама и следящие скрипты могут сильно нагружать браузер. Я как-то смотрел - простая хтмл страница без яваскрипта потребляет довольно мало ресурсов. Хотя Хром да, он потребляет много памяти, я подозреваю они просто кешируют все, что можно в надежде ускорить приложение.
Любители ноды пишут такие вещи на gulp, любители php пишут самописные скрипты на пхп, любители bash - на баше. Еще в линуксе есть make, который можно задействовать для этой цели (причем, что хорошо, он умеет обновлять только изменившиеся зависимости).
В общем, вариантов много. Самый известный это наверно gulp, но он завязан на ноду (яваскрипт), и на мой взгляд, там довольно уродливый синтаксис. Вообще, мне он не нравится, это выглядит как убогий велосипед в сравнении с make которому уже лет 40.
>>803733
Либо делать не статическими, либо прокинуть методы как глобальные функции твига.
Я подозреваю, там по каким-то причинам не хотят такое разрешать. Чтобы например не вызывали все подряд, а пользовались только предоставленными переменными и функциями.
Плюс костылики: http://stackoverflow.com/questions/6844266/twig-template-engine-using-a-static-function-or-variable
>>803707
6-10 месяцев. Учить придется не только php, но и html css js mysql.
>>803699
Никому не нужен твой стрим, и никто его не будет смотреть хотя бы потому что это пхп тред.
>>803651
Если при установке полей должна быть какая-то логика, то надо вместо полей использовать сеттеры:
$news->setTitle('....');
В других языках кстати есть синтаксис для того, чтобы сделать свойство, при обращении к которому вызывается метод:
https://msdn.microsoft.com/ru-ru/library/w86s7x04.aspx
Это по сути синтаксический сахар, который позволяет записывать вызов сеттера короче.
Твой подход с массивом проблему никак не решит.
> А логику установки этих новых полей придется разрулить только в одном месте -- методе News::createFromArray(). Всё.
Нет. Он не решает проблему изменения поля позже.
> Причем не обязательно использовать массив:
Это уже переусложнение - ты создал 2 класса, решающих одну и ту же задачу - хранение информации о новости.
>>803649
С аяксом вряд ли быстрее, отобразить готовую страницу гораздо быстрее (и браузер умеет делать это по мере загрузки), чем ждать пока загрузится страница, куча скриптов, пока все отрендерится.
Конечно есть случаи когда это необходимо: например, интерактивные приложения со сложным интерфейсом. Но если делать какой-то простой сайт, например учебник или блог - это только ухудшает удобство использования.
То есть надо смотреть по ситуации. А чтобы другие неопытные аноны сделали правильные выводы, я чуть-чуть прокомментирую твои высказывания.
> С ajax-ом намного быстрее,
Это надо постраться чтобы на пхп код работал медленнее чем код на пхп + передача данных + рендеринг страницы в яваскрипте.
> плюс не засоряю мозги и код.
Вообще, ты его усложняешь. Теперь в генерации страницы принимает участие не только пхп, но и яваскрипт.
> бывает хромог без плагинов зависает на некрокомпах с антивирусами при открытых 5 вкладках со всякой ерундой)
Это зависит от того, каике сайты открывать. реклама и следящие скрипты могут сильно нагружать браузер. Я как-то смотрел - простая хтмл страница без яваскрипта потребляет довольно мало ресурсов. Хотя Хром да, он потребляет много памяти, я подозреваю они просто кешируют все, что можно в надежде ускорить приложение.
Так, в общем, хорошо сделано. надеюсь, в следующий раз ты будешь использовать для вещей вроде Request готовые библиотеки.
https://github.com/applejacky/students/blob/master/dump.sql
> `cookie_token` varchar(100) NOT NULL,
Я бы тут добавил уникальный ключ для защиты от глупых ошибок, например когда туда вставляется пустая строка или что-то такое. И комментарий стоит добавлять, так как назначение поля не очевидно.
https://github.com/applejacky/students/blob/master/util/curl_login_edit_profile.sh
Эта штука мне напоминает тест. Это не тест? Тебе определенно стоит почитать урок про тесты ( https://gist.github.com/codedokode/a455bde7d0748c0a351a ) и открыть для себя codeception - там такие вещи автоматизируются гораздо удобнее.
https://github.com/applejacky/students/tree/master/app/Lib
Здесь не очень удачно положен StudentValidator рядом с фундаментальными классами, лучше бы его в отдельную папку.
https://github.com/applejacky/students/blob/master/app/Lib/StudentValidator.php#L18
StudentMapper было бы удобнее передать как зависимость в конструктор.
https://github.com/applejacky/students/blob/master/app/Lib/StudentValidator.php#L36
Здесь странно что проверки email и пароля делаются только для новых студентов. А что, редактировать email или пароль нельзя? Уж email-то наверно можно? Нет ли тут ошибки, что пользователь может при обновлении передать емайл или пароль и они принимаются без валидации? Хотя конечно метод save() и не сохраняет измененный email, но догадаться об этом не просто.
> "Баллы должны быть в диапазоне между {$this->minRating}-{$this->maxRating} включительно";
> включительно";
А судя по коду - не включительно.
https://github.com/applejacky/students/blob/master/app/Routing/Route.php#L25
> private function routeIsValid
Такой метод лучше сделать статическим так как он вызвается из конструктора когда объект еще не инициализирован и есть риск что кто-то обратится к $this->...
https://github.com/applejacky/students/blob/master/app/Routing/Route.php#L15
> if ($this->routeIsValid($method, $path, $controllerAndAction, $placeholderRegexArray)) {
Зачем тут if если тут нету else и если метод всегда возвращает true?
https://github.com/applejacky/students/blob/master/app/Routing/RouteRequestMatcher.php#L20
Вот здесь вместо замен плейсхолдеров в регулярке конечно было бы правильнее разбиват роут на массив: /a/:b/c/:d -> ['/a/', ':b', '/c/', ':d'] и затем уже из массива собирать регулярку. Это более безопасно.
https://github.com/applejacky/students/blob/master/app/Controller/Controller.php#L22
Вот это плохая штука, ставить так реквайры посередине кода. Лучше делать это где-то в скрипте инициализации.
https://github.com/applejacky/students/blob/master/app/Controller/Controller.php#L45
> public function __get($property)
Вот это вот использование магических методов в контроллере тоже не очень хорошая штука, трудно будет понять откуда там берется свойство. Явное лучше неявного.
В реализации роутов у тебя есть подвох. Параметры роута определяются по порядковым номерам, а не по названиям. То есть можно легко написать в роуте плейсхолдеры /:a/:b/:c, а в контроллере function doSomething($c, $b, $a) и не заметить ошибки. Лучше либо передавать массив именованных плейсхолдеров либо через рефлекшен проверять имена аргументов метода, как это делает Симфони.
https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php
тут мне не нравится, что отдельные функции для GET и POST. зачем? Это лишь приводит к дублированию кода.
Также, не надо возвращать пользователю введенный пароль из соображений безопасности.
https://github.com/applejacky/students/blob/master/app/Helper/Auth.php#L72
> private function generateHash($password, $login)
переменная назвается login, но передается в нее почему-то соль.
https://github.com/applejacky/students/blob/master/app/Helper/FlashMessage.php
Такая реализация плохо работает при отправке форм параллельно в нескольких вкладках - имей в виду.
https://github.com/applejacky/students/blob/master/app/Helper/TableHeadBuilder.php#L36
> return sprintf('Указан несуществующий столбец %s', $column);
Тут наверно исключение надо бросать.
https://github.com/applejacky/students/blob/master/app/Database/AbstractMapper.php#L8
> protected static $table;
Лучше делать это через абстрактный метод. А то где гарантия что переопределят имя таблицы?
https://github.com/applejacky/students/blob/master/app/Database/StudentMapper.php#L9
> public static $table = 'students';
Непонятно почему тут public. Это по моему способствует нарушению инкапсуляции работы с таблицей в одном классе.
https://github.com/applejacky/students/blob/master/app/View/errors/500.phtml
Мелочь, но тут может быть XSS при выводе сообщения об ошибке.
https://github.com/applejacky/students/blob/master/app/View/student/index.phtml#L6
> isset($search)
Плохо когда переменная может быть, а может не быть.
Так, в общем, хорошо сделано. надеюсь, в следующий раз ты будешь использовать для вещей вроде Request готовые библиотеки.
https://github.com/applejacky/students/blob/master/dump.sql
> `cookie_token` varchar(100) NOT NULL,
Я бы тут добавил уникальный ключ для защиты от глупых ошибок, например когда туда вставляется пустая строка или что-то такое. И комментарий стоит добавлять, так как назначение поля не очевидно.
https://github.com/applejacky/students/blob/master/util/curl_login_edit_profile.sh
Эта штука мне напоминает тест. Это не тест? Тебе определенно стоит почитать урок про тесты ( https://gist.github.com/codedokode/a455bde7d0748c0a351a ) и открыть для себя codeception - там такие вещи автоматизируются гораздо удобнее.
https://github.com/applejacky/students/tree/master/app/Lib
Здесь не очень удачно положен StudentValidator рядом с фундаментальными классами, лучше бы его в отдельную папку.
https://github.com/applejacky/students/blob/master/app/Lib/StudentValidator.php#L18
StudentMapper было бы удобнее передать как зависимость в конструктор.
https://github.com/applejacky/students/blob/master/app/Lib/StudentValidator.php#L36
Здесь странно что проверки email и пароля делаются только для новых студентов. А что, редактировать email или пароль нельзя? Уж email-то наверно можно? Нет ли тут ошибки, что пользователь может при обновлении передать емайл или пароль и они принимаются без валидации? Хотя конечно метод save() и не сохраняет измененный email, но догадаться об этом не просто.
> "Баллы должны быть в диапазоне между {$this->minRating}-{$this->maxRating} включительно";
> включительно";
А судя по коду - не включительно.
https://github.com/applejacky/students/blob/master/app/Routing/Route.php#L25
> private function routeIsValid
Такой метод лучше сделать статическим так как он вызвается из конструктора когда объект еще не инициализирован и есть риск что кто-то обратится к $this->...
https://github.com/applejacky/students/blob/master/app/Routing/Route.php#L15
> if ($this->routeIsValid($method, $path, $controllerAndAction, $placeholderRegexArray)) {
Зачем тут if если тут нету else и если метод всегда возвращает true?
https://github.com/applejacky/students/blob/master/app/Routing/RouteRequestMatcher.php#L20
Вот здесь вместо замен плейсхолдеров в регулярке конечно было бы правильнее разбиват роут на массив: /a/:b/c/:d -> ['/a/', ':b', '/c/', ':d'] и затем уже из массива собирать регулярку. Это более безопасно.
https://github.com/applejacky/students/blob/master/app/Controller/Controller.php#L22
Вот это плохая штука, ставить так реквайры посередине кода. Лучше делать это где-то в скрипте инициализации.
https://github.com/applejacky/students/blob/master/app/Controller/Controller.php#L45
> public function __get($property)
Вот это вот использование магических методов в контроллере тоже не очень хорошая штука, трудно будет понять откуда там берется свойство. Явное лучше неявного.
В реализации роутов у тебя есть подвох. Параметры роута определяются по порядковым номерам, а не по названиям. То есть можно легко написать в роуте плейсхолдеры /:a/:b/:c, а в контроллере function doSomething($c, $b, $a) и не заметить ошибки. Лучше либо передавать массив именованных плейсхолдеров либо через рефлекшен проверять имена аргументов метода, как это делает Симфони.
https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php
тут мне не нравится, что отдельные функции для GET и POST. зачем? Это лишь приводит к дублированию кода.
Также, не надо возвращать пользователю введенный пароль из соображений безопасности.
https://github.com/applejacky/students/blob/master/app/Helper/Auth.php#L72
> private function generateHash($password, $login)
переменная назвается login, но передается в нее почему-то соль.
https://github.com/applejacky/students/blob/master/app/Helper/FlashMessage.php
Такая реализация плохо работает при отправке форм параллельно в нескольких вкладках - имей в виду.
https://github.com/applejacky/students/blob/master/app/Helper/TableHeadBuilder.php#L36
> return sprintf('Указан несуществующий столбец %s', $column);
Тут наверно исключение надо бросать.
https://github.com/applejacky/students/blob/master/app/Database/AbstractMapper.php#L8
> protected static $table;
Лучше делать это через абстрактный метод. А то где гарантия что переопределят имя таблицы?
https://github.com/applejacky/students/blob/master/app/Database/StudentMapper.php#L9
> public static $table = 'students';
Непонятно почему тут public. Это по моему способствует нарушению инкапсуляции работы с таблицей в одном классе.
https://github.com/applejacky/students/blob/master/app/View/errors/500.phtml
Мелочь, но тут может быть XSS при выводе сообщения об ошибке.
https://github.com/applejacky/students/blob/master/app/View/student/index.phtml#L6
> isset($search)
Плохо когда переменная может быть, а может не быть.
Теперь разобрался. Спасибо, анон!
Ибо хочется попробовать не просто ковырять всякие PHPNuke или Joomla, а прописать что-то под себя лично.
Вопрос заключается в чём - какой костяк у любого мало-мальски годного движка?
Спасибо тебе, видно что разбираешься хорошо во многом. "Это надо постраться чтобы на пхп код работал медленнее чем код на пхп + передача данных + рендеринг страницы в яваскрипте" - самая первая версия включала функцию, которая в цикле делала запросы и вызывала еще функцию, которая тоже делала запросы, в БД. К концу года цикл был в 1000 витков на каждую отправку формы из одного поля. Так что можно. Далее вопросы только по php.
олсо, хочу поставить yii2. уже прочитал документацию, но плохо разрулился с установкой так как composer не установил. Собираюсь поставить себе фремворк на бесплатный хостинг и оттуда уже и работать, прочитал, что это можно сделать по ssh, но мне еще не дал доступ провайдер.
>Далее, нет логики в наследовании хелперов. Вот у тебя есть Helper и есть LoginHelper, который его наследует. Непонятно, а зачем? Там все равно почти все методы статические. Точнее, часть статическая, а часть нет, и почему, непонятно.
>Там все равно почти все методы статические. Точнее, часть статическая, а часть нет, и почему, непонятно.
>>А разве в одном классе все методы должны быть либо статические либо не статические? Почему?
>Такого ограничения нет. Но должна быть какая-то логика по которой ты делаешь метод статическим или нет. Например, одинаково ли его поведение всегда или разное для разных объектов. Можно ли его вызывать не имея объекта или наоборот, он имеет смысл только если есть объект. У тебя там такой логики нету, слово static поставлено произвольно.
>Пример. Допустим мы делаем класс для работы с файлом, имя файла передается в конструктор. Метод "удалить файл" очевидно должен быть нестатическим, так как он работает с объектом, представляющим файл. А вот метод "перевести размер из байтов в мегабайты" логично сделать статическим так как ему в принципе объект не нужен, он всегда одинаково работает, и может вообще использоваться не для файла, а для чего-то еще.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php#L13
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L55
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L62
За исключением этих методов у меня был еще один статический метод https://github.com/someApprentice/Students/blob/f35699489413c5b948046ce07f66316d91a2a8b2/app/Model/Helper/Helper.php#L6 (актуальная версия файла на момент замечания) - его я исправил, вынесев его в класс контроллера и обращаясь через $this. Остальные же методы, они, как из примера метода "перевести размер из байтов в мегабайты", всегда будут работать одинакового и им не нужен объект. К тому же, их удобно вызывать в других местах не создавая класс, например здесь https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L37 и здесь https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Student.php#L101-L102
В этом ведь есть логика иметь эти методы статическими?
>>797257
>> Я не правильно написал метод getQuery и не понимаю когда должны вбрасываться исключения?
>Скорее всего неправильно. Все GET параметры приходят от пользователя и могут отсутствовать.
Действительно, я неправильно понимаю зачем нужны исключения, когда они должны вбрасываться и как с ними работать. Я перечитал заново мануал по исключениям, и у меня возникли вопросы, которые почему-то не возникли с самого начала:
>Исключение выбрасывается в случае возникновения нештатной ситуации, когда функция обнаруживает что не способна выполнить свою задачу.
Чтобы вбросить исключение мы должны сначала проверить на эту нештатную ситуацию, т.е. мы должны знать заранее какая нештатная ситуация может быть.
В моем случае (в случае с методом getQuery https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L6) нештатная ситуация это то что такой запрос может отсутствовать или не быть скалярным, и соответственно не способна выполнить свою задачу: https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L8
В чем я не правильно смотрю на эту ситуацию?
>Все GET параметры приходят от пользователя и могут отсутствовать.
Разве программы не созданы для того чтобы работать с данными пришедшими от пользователя? Всегда будут ситуации в которых от пользователя приходят неверные данные и нужно с этим что-то сделать. Разве исключения не для этого созданы?
Обработать ошибку значит сделать что-то при вбрасывании исключения? Допустим какой-то метод someMethod вбрасывает исключение SomeMethodException, значит где-то в начале программы я должен написать
set_exception_handler(function (SomeMethodException $exception) {
$exception->вывестиОшибкуВЛог();
$exception->вывестиЗаглушку();
...
});
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L56
Мне не хотелось писать функцию получающую из БД определённое количество отсортированных студентов, т.к. чтобы вызвать её сначала нужно рассчитать значение OFFSET, а не просто создать Pager и передать его в шаблон, и я подумал что можно передать в Pager все записи и получить нужное количество\отсортировать уже внутри него.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L72
Чтобы отсортировать студентов с помощью usort мне пришлось spl переводить в массив, а затем снова в spl.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L76
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L100
Сначала я хотел написать аналогичную usort функцию для spl, но потом подумал что ведь можно использовать массив вместо него.
Какие преимущества у spl перед массивом? Я вижу только недостатки в том что его нельзя отсортировать, отфильтровать, пройтись по каждому элементу применив к нему функцию (аналогично array_walk). Придётся писать эти методы с нуля мы уже такое делали.
В мануале написано:
Класс SplObjectStorage предоставляет соответствие объекты-данные или набор объектов, игнорируя данные. Эта двойная цель может быть полезна во многих случаях, включая необходимость уникальной идентификации объектов.
>соответствие объекты-данные или набор объектов
Что это значит? У меня не получилось загуглить.
Уникальная идентификация мне не особо нужна, верно?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L81-L87
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L89-L95
Это же копипаста верно? Я подумал что от неё можно избавиться поменяв результаты возвращаемые анонимной функцией местами:
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L86
if ($this->queries['by'] == 'asc') {
$n = -1;
} elseif ($this->queries['by'] == 'desc') {
$n = 1;
}
usort($array, function($a, $b) use ($sort, $n) {
if ($a->getProperty($sort) == $b->getProperty($sort)) {
return 0;
}
return ($a->getProperty($sort) < $b->getProperty($sort)) ? $n : $n * (-1);
});
Как можно переименовать переменную $n, чтобы сразу было понятно зачем она нужна?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L119
В какую сторону должна указывать стрелка сортировки в ссылке "SAT Scores ↓"? У меня логика такая: Если ссылка ведет на страницу с сортировкой по убыванию, значит и стрелка должна указывать вниз.
Или же нужно сделать чтобы она указывала в ту сторону в которую стоит сортировка в текущий момент на странице?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L24-L28
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L30-L34
Это тоже копипаста? Я подумал что можно избавиться от неё написав:
if (!$sort = $this->getQuery('sort')) {
$sort = 'satScores';
}
Ведь можно же задавать переменную в условии и тут же её проверять?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L22
Здесь есть баг: если передать $_GET['sort'] = 'hash' или 'salt', то все записи отсортируются по хешу или соли. Но на практике это ничего не даст - всё равно никак не получится взломать пользователя зная только его позицию в сортировке хешу или соли. Стоит ли исправлять такие баги?
Не пишу ли я переусложненный код? Например в функции getSortLinkBy() https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L107 я сначала пишу $queries = $this->queries, что само по себе выглядит как-то странно, затем ниже еще делаю какие-то, наверно непонятные для других, манипуляции с ней. Но чтобы функция работала именно такие действия нужно совершить: Я не могу в этом методе менять $this->queries['sort'] потому что при генерации новой ссылки всегда будет меняться это свойство, а именно по этому свойству делается сортировка записей, и сортировка делается в конструкторе чтобы не делать её вручную, а просто один раз создать Pager и передать его в шаблон.
>Далее, нет логики в наследовании хелперов. Вот у тебя есть Helper и есть LoginHelper, который его наследует. Непонятно, а зачем? Там все равно почти все методы статические. Точнее, часть статическая, а часть нет, и почему, непонятно.
>Там все равно почти все методы статические. Точнее, часть статическая, а часть нет, и почему, непонятно.
>>А разве в одном классе все методы должны быть либо статические либо не статические? Почему?
>Такого ограничения нет. Но должна быть какая-то логика по которой ты делаешь метод статическим или нет. Например, одинаково ли его поведение всегда или разное для разных объектов. Можно ли его вызывать не имея объекта или наоборот, он имеет смысл только если есть объект. У тебя там такой логики нету, слово static поставлено произвольно.
>Пример. Допустим мы делаем класс для работы с файлом, имя файла передается в конструктор. Метод "удалить файл" очевидно должен быть нестатическим, так как он работает с объектом, представляющим файл. А вот метод "перевести размер из байтов в мегабайты" логично сделать статическим так как ему в принципе объект не нужен, он всегда одинаково работает, и может вообще использоваться не для файла, а для чего-то еще.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php#L13
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L55
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L62
За исключением этих методов у меня был еще один статический метод https://github.com/someApprentice/Students/blob/f35699489413c5b948046ce07f66316d91a2a8b2/app/Model/Helper/Helper.php#L6 (актуальная версия файла на момент замечания) - его я исправил, вынесев его в класс контроллера и обращаясь через $this. Остальные же методы, они, как из примера метода "перевести размер из байтов в мегабайты", всегда будут работать одинакового и им не нужен объект. К тому же, их удобно вызывать в других местах не создавая класс, например здесь https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L37 и здесь https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Student.php#L101-L102
В этом ведь есть логика иметь эти методы статическими?
>>797257
>> Я не правильно написал метод getQuery и не понимаю когда должны вбрасываться исключения?
>Скорее всего неправильно. Все GET параметры приходят от пользователя и могут отсутствовать.
Действительно, я неправильно понимаю зачем нужны исключения, когда они должны вбрасываться и как с ними работать. Я перечитал заново мануал по исключениям, и у меня возникли вопросы, которые почему-то не возникли с самого начала:
>Исключение выбрасывается в случае возникновения нештатной ситуации, когда функция обнаруживает что не способна выполнить свою задачу.
Чтобы вбросить исключение мы должны сначала проверить на эту нештатную ситуацию, т.е. мы должны знать заранее какая нештатная ситуация может быть.
В моем случае (в случае с методом getQuery https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L6) нештатная ситуация это то что такой запрос может отсутствовать или не быть скалярным, и соответственно не способна выполнить свою задачу: https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L8
В чем я не правильно смотрю на эту ситуацию?
>Все GET параметры приходят от пользователя и могут отсутствовать.
Разве программы не созданы для того чтобы работать с данными пришедшими от пользователя? Всегда будут ситуации в которых от пользователя приходят неверные данные и нужно с этим что-то сделать. Разве исключения не для этого созданы?
Обработать ошибку значит сделать что-то при вбрасывании исключения? Допустим какой-то метод someMethod вбрасывает исключение SomeMethodException, значит где-то в начале программы я должен написать
set_exception_handler(function (SomeMethodException $exception) {
$exception->вывестиОшибкуВЛог();
$exception->вывестиЗаглушку();
...
});
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L56
Мне не хотелось писать функцию получающую из БД определённое количество отсортированных студентов, т.к. чтобы вызвать её сначала нужно рассчитать значение OFFSET, а не просто создать Pager и передать его в шаблон, и я подумал что можно передать в Pager все записи и получить нужное количество\отсортировать уже внутри него.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L72
Чтобы отсортировать студентов с помощью usort мне пришлось spl переводить в массив, а затем снова в spl.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L76
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L100
Сначала я хотел написать аналогичную usort функцию для spl, но потом подумал что ведь можно использовать массив вместо него.
Какие преимущества у spl перед массивом? Я вижу только недостатки в том что его нельзя отсортировать, отфильтровать, пройтись по каждому элементу применив к нему функцию (аналогично array_walk). Придётся писать эти методы с нуля мы уже такое делали.
В мануале написано:
Класс SplObjectStorage предоставляет соответствие объекты-данные или набор объектов, игнорируя данные. Эта двойная цель может быть полезна во многих случаях, включая необходимость уникальной идентификации объектов.
>соответствие объекты-данные или набор объектов
Что это значит? У меня не получилось загуглить.
Уникальная идентификация мне не особо нужна, верно?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L81-L87
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L89-L95
Это же копипаста верно? Я подумал что от неё можно избавиться поменяв результаты возвращаемые анонимной функцией местами:
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L86
if ($this->queries['by'] == 'asc') {
$n = -1;
} elseif ($this->queries['by'] == 'desc') {
$n = 1;
}
usort($array, function($a, $b) use ($sort, $n) {
if ($a->getProperty($sort) == $b->getProperty($sort)) {
return 0;
}
return ($a->getProperty($sort) < $b->getProperty($sort)) ? $n : $n * (-1);
});
Как можно переименовать переменную $n, чтобы сразу было понятно зачем она нужна?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L119
В какую сторону должна указывать стрелка сортировки в ссылке "SAT Scores ↓"? У меня логика такая: Если ссылка ведет на страницу с сортировкой по убыванию, значит и стрелка должна указывать вниз.
Или же нужно сделать чтобы она указывала в ту сторону в которую стоит сортировка в текущий момент на странице?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L24-L28
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L30-L34
Это тоже копипаста? Я подумал что можно избавиться от неё написав:
if (!$sort = $this->getQuery('sort')) {
$sort = 'satScores';
}
Ведь можно же задавать переменную в условии и тут же её проверять?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L22
Здесь есть баг: если передать $_GET['sort'] = 'hash' или 'salt', то все записи отсортируются по хешу или соли. Но на практике это ничего не даст - всё равно никак не получится взломать пользователя зная только его позицию в сортировке хешу или соли. Стоит ли исправлять такие баги?
Не пишу ли я переусложненный код? Например в функции getSortLinkBy() https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Pager.php#L107 я сначала пишу $queries = $this->queries, что само по себе выглядит как-то странно, затем ниже еще делаю какие-то, наверно непонятные для других, манипуляции с ней. Но чтобы функция работала именно такие действия нужно совершить: Я не могу в этом методе менять $this->queries['sort'] потому что при генерации новой ссылки всегда будет меняться это свойство, а именно по этому свойству делается сортировка записей, и сортировка делается в конструкторе чтобы не делать её вручную, а просто один раз создать Pager и передать его в шаблон.
>поставить себе фремворк на бесплатный хостинг и оттуда уже и работать
Дак и ставь сразу туда, не мучайся с виндой своей
>У тебя внутренний подзапрос группирует по level
Неа, по id ака раундам
>>803617
>Как тут запрос оптимизировать? Считать раз в час по крону. А если нужно мгновенно обновлять среднее, а не раз в час? Тогда заводим 2 ячейки, в одной храним сумму значений, в другой их количество. Обновляем эти ячейки при каждой вставке в исходную таблицу.
Спасибо, примерно так и сделал. Тот запрос сутки выполнялся и так и не выполнился, пришлось завести два новых столбика, которые обновляю по крону.
К слову, авг двух полей по около 15ккк записей занимает около 5 секунд, я этим очень доволен. Как сильней разрастется, тоже на крон перевешу.
пробовал по ssh, только нет доступа
есть вариант какой-то типа архивом. как вордпресс или кодигнайтер?
не понимаю что за сложности такие с этим yii/
Разворачиваешь на хостинге композер, устанавливаешь через него yii, делаешь инит комит и клонируешь его себе на локалку. Потом настраиваешь свою идешку для работы с удаленным сервером и собственно работаешь.
Есть вопрос.
Существует таблица в базе данных, где есть такие поля:
message_id
message_body
message_recipient
user_id
Primary key = message_id
user_id привязан к другой таблице
Если я делаю запрос по типу mysqli_query($link, $query);, то получаю обьект mysqli_result.
Тут начинаются интересности.
Мой запрос - "SELECT * FROM messages WHERE user_id='".$_COOKIE['id']"'"
Мне нужна информация о каждом сообщении, принадлежащем этому пользователю, чтобы отправить в таблицу.
Я полагаю, что я могу получить ассоциативный массив(где ключ - это айди сообщения) с ассоциативными массивами, содержащими информацию о каждом отдельном сообщении, где я уже буду вставлять это в HTML. Но я не знаю, как получить такой результат. mysqli_fetch_assoc() возвращает единичный массив.
Что делать, анор?
перебери его в цикле где ты создаш новый массив в котором будет ключ и значение какие ты захочешь
Это я понимаю, но я не понимаю, какую функцию для этого использовать. Пытаюсь делать:
if(isset($_COOKIE['id']))
{
$result = mysqli_query(mysqli_connect("localhost", "project", "1q2w3e", "project"), "SELECT * FROM messages WHERE user_id='".$_COOKIE['id']"'");
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
}
} else {
echo "0 results";
}
}
Но это выдает ошибку.
какую ошибку?
Предлагаю такой вариант:
function get_messages_by_userid_as_array(){
$_list = array();
if (!empty($_COOKIE['id'])) {
$_stmt = $mysqli->prepare("SELECT * FROM messages WHERE user_id=?");
$_stmt->bind_param('i', $_COOKIE['id']);
if ( $_stmt->execute() ) {
$_stmt->bind_result($_message_id, $_message_body, $_message_recipient, $_user_id);
while ( $_stmt->fetch() ) { $_list[$_message_id] = ['message_body'=>$_message_body, 'message_recipient'=>$_message_recipient, 'user_id'=>$_user_id];}
$_stmt->close();
}
return $_list}
Исправил, сейчас попробую.
Рофл, не прошли пробелы. В общем, по вопросу:
1) http://php.net/manual/ru/mysqli.quickstart.prepared-statements.php
для лазанья в бд лучше использовать подготавливаемые выражения.
2) WHERE user_id='".$_COOKIE['id']"'
мне кажется, нельзя доверять $_COOKIE в данном случае и напрямую вставлять его в запрос.
3) Массивы это чудесная вещь - можно вкладывать один в другой сколько угодно. Здесь ты создаешь массив пустым, чтобы не было ошибки; далее ты делаешь выборку из БД и перебираешь по одной все строки, записывая как ключ к $_list значение поля message_id (ключи уникальны), а как данные ключа - остальные поля.
в двойные скобки можешь отправлять переменную. тогда и не нужна конкатенация. тем более `` можешь юзать
1) Почитаю
2) Можно, работает. Оно достаёт номер пользователя из кук вполне себе спокойно. Это же глобальный массив.
Можно, конечно. Но $_GET, $_POST, $_COOKIE это небезопасные хранилища, так как приходят от пользователя.
>>804352
Нельзя вставлять переменные, тем более пришедшие от пользователя, в SQL запрос. Это SQL-инъекция. И даже если инъекции нет, все равно читается плохо. Почитай про плейсхолдеры и подготовленные запросы.
>>804321
А еще лучше исользовать PDO. Вот вы тут пишете код с mysqli, а что будет если произойдет какая-то ошибка? В вашем коде она просто игнорируется, никто о ней не узнает. Чтобы ее не пропустить, надо ставить if (и это написано в мануале который вы принципиально не читаете).
PDO в отличие от mysqli умеет выбрасывать исключения при приходе ошибки от базы.
Двачую, лучше. Но если накосячить с перехватом этого исключения, вылезет ошибка с логином и паролем, упс.
Ты можешь установить зависимости композером на своем компьютере, запаковать в архив. Но автоматизируется ли этот способ? Я советую автоматизировать выгрузку кода иначе ты будешь как обезьяна при каждом обновлении вручную делать одни и те же действия. Плюс, можешь забыть что-то выгрузить и потом удивляться почему не работает. Времени своего не жалко?
>>804170
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php
я бы просто тут сделал все методы статическими.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php
Тут со статическими методами все ок, но почему у тебя методы вроде хеширования пароля публичные? Лучше инкапуслировать (скрыть внутри класса) принципы хеширования пароля, а наружу предоставить методы вроде "задать пароль", "проверить пароль". То есть пройдись по своим методами подумай, какие ты выставляешь наружу, а какие являются внутренней логикой класса.
Зачем нужна инкапсуляция? Ну например если у тебя логика хеширования скрыта внутри класса и ты захочешь поменять ее, тебе достаточно будет поменять только этот класс и не искать, не вызываются ли методы где-то еще.
Ну и это гарантирует что работа с хешированием пароле будет заключена в одном классе, а не разбросана по коду.
Вообще, это мелочь, но все же, я хотел бы чтобы ты при написании класса задумывался, какие методы мы выставляем наружу, а какие закрываем.
Вот кстати в твоем коде, смена пароля сделана не в классе авторизации. В принципе твой вариант тоже имеет право на жизнь, но если бы ты перенес смену пароля в класс авторизации, степень инкапсуляции был бы выше. Ну к примеру, если мы поменяем алгоритм генерации пароля, у тебя придется лезть еще в класс Student.
А ты кстати смотришь код других анонов? Вот я вчера видел такой подход к авторизации: https://github.com/applejacky/students/blob/master/app/Helper/Auth.php
Не то чтобы он идеальный (он завязан на использование пароля), но ты можешь просто для сравнения посмотреть на его код.
Насчет авторизации - по моему, у тебя там многовато кук ставится. Целых 3 куки. зачем так много?
Одна кука, допустим (id), идентифицирует пользователя
Другая (hash), допустим, аутентифицирует его (то есть подтверждает что это он, а не хакер, подделавший id)
Ну то есть 2 куки - это что-то вроде формы с логином и паролем. Логин идентифицирует, пароль подтверждает подлинность.
Но третья-то зачем?
Более того, так как у нас хеши (в отличие от паролей) уникальные, мы можем и id не использовать, а ограничиваться только 1 кукой с хешем.
> В этом ведь есть логика иметь эти методы статическими?
Да
Ты можешь установить зависимости композером на своем компьютере, запаковать в архив. Но автоматизируется ли этот способ? Я советую автоматизировать выгрузку кода иначе ты будешь как обезьяна при каждом обновлении вручную делать одни и те же действия. Плюс, можешь забыть что-то выгрузить и потом удивляться почему не работает. Времени своего не жалко?
>>804170
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/Helper.php
я бы просто тут сделал все методы статическими.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php
Тут со статическими методами все ок, но почему у тебя методы вроде хеширования пароля публичные? Лучше инкапуслировать (скрыть внутри класса) принципы хеширования пароля, а наружу предоставить методы вроде "задать пароль", "проверить пароль". То есть пройдись по своим методами подумай, какие ты выставляешь наружу, а какие являются внутренней логикой класса.
Зачем нужна инкапсуляция? Ну например если у тебя логика хеширования скрыта внутри класса и ты захочешь поменять ее, тебе достаточно будет поменять только этот класс и не искать, не вызываются ли методы где-то еще.
Ну и это гарантирует что работа с хешированием пароле будет заключена в одном классе, а не разбросана по коду.
Вообще, это мелочь, но все же, я хотел бы чтобы ты при написании класса задумывался, какие методы мы выставляем наружу, а какие закрываем.
Вот кстати в твоем коде, смена пароля сделана не в классе авторизации. В принципе твой вариант тоже имеет право на жизнь, но если бы ты перенес смену пароля в класс авторизации, степень инкапсуляции был бы выше. Ну к примеру, если мы поменяем алгоритм генерации пароля, у тебя придется лезть еще в класс Student.
А ты кстати смотришь код других анонов? Вот я вчера видел такой подход к авторизации: https://github.com/applejacky/students/blob/master/app/Helper/Auth.php
Не то чтобы он идеальный (он завязан на использование пароля), но ты можешь просто для сравнения посмотреть на его код.
Насчет авторизации - по моему, у тебя там многовато кук ставится. Целых 3 куки. зачем так много?
Одна кука, допустим (id), идентифицирует пользователя
Другая (hash), допустим, аутентифицирует его (то есть подтверждает что это он, а не хакер, подделавший id)
Ну то есть 2 куки - это что-то вроде формы с логином и паролем. Логин идентифицирует, пароль подтверждает подлинность.
Но третья-то зачем?
Более того, так как у нас хеши (в отличие от паролей) уникальные, мы можем и id не использовать, а ограничиваться только 1 кукой с хешем.
> В этом ведь есть логика иметь эти методы статическими?
Да
> Действительно, я неправильно понимаю зачем нужны исключения, когда они должны вбрасываться и как с ними работать.
Исключения - это исключительные ситуации, которые по идее не должны бы происходить. ну например, база сломалась и перестала выполнять запросы. Или в функцию, принимающую положительные числа, кто-то по ошибке передал отрицательное. Исключения обычно идут в логи и программист потом их смотрит, ищет причины и исправляет.
То, что в ГЕТ-параметрах что-то отстуствует - это вполне нормальная и ожидаемая ситуация. Мы понимаем, что пользователь может передавать нам любые параметры. И тут вместо исключения лучше бы например выдавать ошибку из серии 4xx.
У меня такая логика: мы не хотим замусоривать логи сообщением, что пользователь не передал какой-то параметр, так как мы это исправить все равно не можем. Значит, лучше предусмотреть такую ситуацию, и выдавать какой-нибудь подходящий HTTP-код из серии 4xx (ошибка пользователя).
Исключение конечно можно использовать, но в итоге ты получишь записи об ошибке в логах, с которыми ты ничего не можешь сделать.
> Разве программы не созданы для того чтобы работать с данными пришедшими от пользователя? Всегда будут ситуации в которых от пользователя приходят неверные данные и нужно с этим что-то сделать. Разве исключения не для этого созданы?
Ну вообще, не совсем. Их можно тут использовать, если ты ожидаешь что таких запросов быть не может, но ведь пользователь может передать нам все, что угодно. Мы просто получаем исключения с которыми ничего не можем сделать.
> Обработать ошибку значит сделать что-то при вбрасывании исключения? Допустим какой-то метод someMethod вбрасывает исключение SomeMethodException, значит где-то в начале программы я должен написать
Да, сделать что-то. Поймать исключеие можно либо глобально как в твоем коде, либо локально в каком-то месте кода через tyr/catch
> Мне не хотелось писать функцию получающую из БД определённое количество отсортированных студентов, т.к. чтобы вызвать её сначала нужно рассчитать значение OFFSET, а не просто создать Pager и передать его в шаблон, и я подумал что можно передать в Pager все записи и получить нужное количество\отсортировать уже внутри него.
Это неффективно. Неправильно выбирать из базы 1000 студентов чтобы потом отобрать из них только 10, а 990 выкинуть. зачем? Используй LIMIT и отбирай только тех, кого нужно.
Рассчитать оффсет несложно: offset = (page - 1) * countPerPage
> Чтобы отсортировать студентов с помощью usort мне пришлось spl переводить в массив, а затем снова в spl.
Не проще было изначально тогда в массиве хранить?
> Какие преимущества у spl перед массивом?
Главное преимущество такое: в Spl можно в качестве ключей использовать объекты, в массиве - только строки. Допустим что у нас есть массив объектов (например студентов) и надо каждому сопоставить какое-то значение (например процент вероятности поступления). Мы можем создать SplOS в котором ключом будет студент, а значением - нужное нам число.
Также, использование объектов в ключе позволяет делать быстрые проверки вида "есть ли этот объект в списке". Ну допустим у нас есть огромный список объектов list и надо провеирть, есть ли в нем объект X или нет. В случае массивов мы конечно можем использовать in_array($x, $list. true). Но эта функция делает полный обход массива что имеет сложность O(N), то есть не очень быстро. А вот в SplOS мы делаем проверку через contains(), и поиск по ключу имеет сложность O(1), то есть делается быстро.
Если ты забыл, то напомню, что массив и SplOS позволяют очень быстро делать поиск по ключу, а вот для поиска по значению приходится обходить все элементы по очереди, и это медленно на больших списках.
Вот это основные сценарии, для которых нужен SplObjectStorage. Есть еще один плюс, что в отличие от массива с ним можно работать как с объектом, вызывать методы, наследоваться. Но если тебе нужна ООП-замена массиву то есть класс ArrayObject.
> Действительно, я неправильно понимаю зачем нужны исключения, когда они должны вбрасываться и как с ними работать.
Исключения - это исключительные ситуации, которые по идее не должны бы происходить. ну например, база сломалась и перестала выполнять запросы. Или в функцию, принимающую положительные числа, кто-то по ошибке передал отрицательное. Исключения обычно идут в логи и программист потом их смотрит, ищет причины и исправляет.
То, что в ГЕТ-параметрах что-то отстуствует - это вполне нормальная и ожидаемая ситуация. Мы понимаем, что пользователь может передавать нам любые параметры. И тут вместо исключения лучше бы например выдавать ошибку из серии 4xx.
У меня такая логика: мы не хотим замусоривать логи сообщением, что пользователь не передал какой-то параметр, так как мы это исправить все равно не можем. Значит, лучше предусмотреть такую ситуацию, и выдавать какой-нибудь подходящий HTTP-код из серии 4xx (ошибка пользователя).
Исключение конечно можно использовать, но в итоге ты получишь записи об ошибке в логах, с которыми ты ничего не можешь сделать.
> Разве программы не созданы для того чтобы работать с данными пришедшими от пользователя? Всегда будут ситуации в которых от пользователя приходят неверные данные и нужно с этим что-то сделать. Разве исключения не для этого созданы?
Ну вообще, не совсем. Их можно тут использовать, если ты ожидаешь что таких запросов быть не может, но ведь пользователь может передать нам все, что угодно. Мы просто получаем исключения с которыми ничего не можем сделать.
> Обработать ошибку значит сделать что-то при вбрасывании исключения? Допустим какой-то метод someMethod вбрасывает исключение SomeMethodException, значит где-то в начале программы я должен написать
Да, сделать что-то. Поймать исключеие можно либо глобально как в твоем коде, либо локально в каком-то месте кода через tyr/catch
> Мне не хотелось писать функцию получающую из БД определённое количество отсортированных студентов, т.к. чтобы вызвать её сначала нужно рассчитать значение OFFSET, а не просто создать Pager и передать его в шаблон, и я подумал что можно передать в Pager все записи и получить нужное количество\отсортировать уже внутри него.
Это неффективно. Неправильно выбирать из базы 1000 студентов чтобы потом отобрать из них только 10, а 990 выкинуть. зачем? Используй LIMIT и отбирай только тех, кого нужно.
Рассчитать оффсет несложно: offset = (page - 1) * countPerPage
> Чтобы отсортировать студентов с помощью usort мне пришлось spl переводить в массив, а затем снова в spl.
Не проще было изначально тогда в массиве хранить?
> Какие преимущества у spl перед массивом?
Главное преимущество такое: в Spl можно в качестве ключей использовать объекты, в массиве - только строки. Допустим что у нас есть массив объектов (например студентов) и надо каждому сопоставить какое-то значение (например процент вероятности поступления). Мы можем создать SplOS в котором ключом будет студент, а значением - нужное нам число.
Также, использование объектов в ключе позволяет делать быстрые проверки вида "есть ли этот объект в списке". Ну допустим у нас есть огромный список объектов list и надо провеирть, есть ли в нем объект X или нет. В случае массивов мы конечно можем использовать in_array($x, $list. true). Но эта функция делает полный обход массива что имеет сложность O(N), то есть не очень быстро. А вот в SplOS мы делаем проверку через contains(), и поиск по ключу имеет сложность O(1), то есть делается быстро.
Если ты забыл, то напомню, что массив и SplOS позволяют очень быстро делать поиск по ключу, а вот для поиска по значению приходится обходить все элементы по очереди, и это медленно на больших списках.
Вот это основные сценарии, для которых нужен SplObjectStorage. Есть еще один плюс, что в отличие от массива с ним можно работать как с объектом, вызывать методы, наследоваться. Но если тебе нужна ООП-замена массиву то есть класс ArrayObject.
> Я вижу только недостатки в том что его нельзя отсортировать, отфильтровать, пройтись по каждому элементу применив к нему функцию (аналогично array_walk)
Вообще, по SplOS можно пройтись циклом foreach так как он реализует специальный интерфейс Iterable: http://php.net/manual/ru/class.splobjectstorage.php
foreach ($spl as $object) {
....
}
> Класс SplObjectStorage предоставляет соответствие объекты-данные или набор объектов, игнорируя данные. Эта двойная цель может быть полезна во многих случаях, включая необходимость уникальной идентификации объектов.
> Что это значит?
Это немного корявый перевод.
> соответствие объекты-данные
Это значит что мы можем внести в SplOS объект как ключ, и какие-то данные (число, строку, другой объект) как значение. То есть использовать его как массив с ключами-объектами. И каждому объекту-ключу сопоставить и сохранить произвольное значение, и позже достать его из SplOS.
Ну например, поставить в соответствие студенту место, которое он занимает в списке лучших по баллам:
$place = 10;
$spl[$student] = $place;
А позже можно взять это значение:
printf("%s занял %d место\n", $student->name, $spl[$place]);
> включая необходимость уникальной идентификации объектов.
Это просто значит проверить есть ли объект в списке или нет.
> или набор объектов, игнорируя данные.
Это значит, что в SplOS можно заносить объекты, не привязывая к ним данные. То есть использовать его как структуру аднных Set (множество). Ну например, мы можем сделать 2 множества, множество студентов, которые проходят на математический факультет по баллам, и на физико-технический:
$math = new SplObjectStorage();
$math->attach($student1);
$physics = new SplObjectStorage();
$physics->attach($student1);
$physics->attach($student2);
А потом эффективно (без долгого перебора списка) проверить, есть ли объект в множестве или нет:
if ($math->contains($someStudent)) ....
Ну и может делать какие-то другие операции.
Вообще, в пхп у нас особо нет разных структур данных. У нас есть массивы, которые заменяют сразу несколько структур (Map, Set, Deque, Vector), но в других языках часто эти структуры есть по отдельности. То есть можно создать например Set, можно создать map и тд. Это имеет то преимущество, что мы ограничиваем операции которые можно делать со структурой.
Если тебе интересно, и если у тебя есть время, попробуй почитать что-нибудь про "структуры данных", например:
https://habrahabr.ru/post/263765/
http://kvodo.ru/data-structures-introduction.html
https://ru.wikipedia.org/wiki/Структура_данных
http://ru.stackoverflow.com/questions/12183/Структуры-данных
https://www.lektorium.tv/course/22823
http://aliev.me/runestone/
Несколько структур данных есть и в пхп:
http://php.net/manual/ru/spl.datastructures.php
Зачем они нужны? Ну некоторые операции эффективнее выполнять с помощью одной структуры данных, некоторые с помощью другой. Например, хотя пхп массивы позволяют реализовать дек (двунаправленную очередь), но на больших объемах она будет неэффективна. Или например, операция вставки в середину в двусвязном списке очень быстрая, а в пхп массиве - не очень.
Ну и плюс, в программе использование конкретной структуры вместо просто массива помогает дать понять тому. кто читает код, что с ней делать можно, а что - нет.
То есть разные структуры данных заточены под разные сценарии использования.
Если есть вопросы, задавай.
> Это же копипаста верно? Я подумал что от неё можно избавиться поменяв результаты возвращаемые анонимной функцией местами:
Ну это небольшая копипаста. Можно добавить какую-то переменную, задающую порядок сортировки. Можно не добавлять.
Но эффективнее сортировать в базе, а не на стороне приложения.
> Как можно переименовать переменную $n, чтобы сразу было понятно зачем она нужна?
Назвать напримр $direction, или $sortDirection, и добавить комментарий.
> В какую сторону должна указывать стрелка сортировки
По идее стрелка указывает направление, в котором значения возрастают. Если сортировка по убыванию то вверх, если по возрастанию то вниз. Вроде так. Если ты под виндой, открой любую папку и посмотри как там сделано. (я посмотрел - в винде сделано наоборот - при сортировке по возрастанию стрелка указывает вверх).
То есть стрелка показывает текущее направление сортировки. Если сортировка идет не по этой колонке, то стрелки нет.
Нагуглил вопрос на SO (англ): http://ux.stackexchange.com/questions/37564/use-up-or-down-arrow-to-represent-sort-ascending-at-table-header
Везде при сортировке по возрастанию треугольник указывает вверх. Видимо он символизирует что сверху маленькие значения, а снизу большие.
> Я вижу только недостатки в том что его нельзя отсортировать, отфильтровать, пройтись по каждому элементу применив к нему функцию (аналогично array_walk)
Вообще, по SplOS можно пройтись циклом foreach так как он реализует специальный интерфейс Iterable: http://php.net/manual/ru/class.splobjectstorage.php
foreach ($spl as $object) {
....
}
> Класс SplObjectStorage предоставляет соответствие объекты-данные или набор объектов, игнорируя данные. Эта двойная цель может быть полезна во многих случаях, включая необходимость уникальной идентификации объектов.
> Что это значит?
Это немного корявый перевод.
> соответствие объекты-данные
Это значит что мы можем внести в SplOS объект как ключ, и какие-то данные (число, строку, другой объект) как значение. То есть использовать его как массив с ключами-объектами. И каждому объекту-ключу сопоставить и сохранить произвольное значение, и позже достать его из SplOS.
Ну например, поставить в соответствие студенту место, которое он занимает в списке лучших по баллам:
$place = 10;
$spl[$student] = $place;
А позже можно взять это значение:
printf("%s занял %d место\n", $student->name, $spl[$place]);
> включая необходимость уникальной идентификации объектов.
Это просто значит проверить есть ли объект в списке или нет.
> или набор объектов, игнорируя данные.
Это значит, что в SplOS можно заносить объекты, не привязывая к ним данные. То есть использовать его как структуру аднных Set (множество). Ну например, мы можем сделать 2 множества, множество студентов, которые проходят на математический факультет по баллам, и на физико-технический:
$math = new SplObjectStorage();
$math->attach($student1);
$physics = new SplObjectStorage();
$physics->attach($student1);
$physics->attach($student2);
А потом эффективно (без долгого перебора списка) проверить, есть ли объект в множестве или нет:
if ($math->contains($someStudent)) ....
Ну и может делать какие-то другие операции.
Вообще, в пхп у нас особо нет разных структур данных. У нас есть массивы, которые заменяют сразу несколько структур (Map, Set, Deque, Vector), но в других языках часто эти структуры есть по отдельности. То есть можно создать например Set, можно создать map и тд. Это имеет то преимущество, что мы ограничиваем операции которые можно делать со структурой.
Если тебе интересно, и если у тебя есть время, попробуй почитать что-нибудь про "структуры данных", например:
https://habrahabr.ru/post/263765/
http://kvodo.ru/data-structures-introduction.html
https://ru.wikipedia.org/wiki/Структура_данных
http://ru.stackoverflow.com/questions/12183/Структуры-данных
https://www.lektorium.tv/course/22823
http://aliev.me/runestone/
Несколько структур данных есть и в пхп:
http://php.net/manual/ru/spl.datastructures.php
Зачем они нужны? Ну некоторые операции эффективнее выполнять с помощью одной структуры данных, некоторые с помощью другой. Например, хотя пхп массивы позволяют реализовать дек (двунаправленную очередь), но на больших объемах она будет неэффективна. Или например, операция вставки в середину в двусвязном списке очень быстрая, а в пхп массиве - не очень.
Ну и плюс, в программе использование конкретной структуры вместо просто массива помогает дать понять тому. кто читает код, что с ней делать можно, а что - нет.
То есть разные структуры данных заточены под разные сценарии использования.
Если есть вопросы, задавай.
> Это же копипаста верно? Я подумал что от неё можно избавиться поменяв результаты возвращаемые анонимной функцией местами:
Ну это небольшая копипаста. Можно добавить какую-то переменную, задающую порядок сортировки. Можно не добавлять.
Но эффективнее сортировать в базе, а не на стороне приложения.
> Как можно переименовать переменную $n, чтобы сразу было понятно зачем она нужна?
Назвать напримр $direction, или $sortDirection, и добавить комментарий.
> В какую сторону должна указывать стрелка сортировки
По идее стрелка указывает направление, в котором значения возрастают. Если сортировка по убыванию то вверх, если по возрастанию то вниз. Вроде так. Если ты под виндой, открой любую папку и посмотри как там сделано. (я посмотрел - в винде сделано наоборот - при сортировке по возрастанию стрелка указывает вверх).
То есть стрелка показывает текущее направление сортировки. Если сортировка идет не по этой колонке, то стрелки нет.
Нагуглил вопрос на SO (англ): http://ux.stackexchange.com/questions/37564/use-up-or-down-arrow-to-represent-sort-ascending-at-table-header
Везде при сортировке по возрастанию треугольник указывает вверх. Видимо он символизирует что сверху маленькие значения, а снизу большие.
>https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L30-L34
> Это тоже копипаста?
Да это мелочь, можно ничего не делать с ней.
> Здесь есть баг: если передать $_GET['sort'] = 'hash' или 'salt', то все записи отсортируются по хешу или соли. Но на практике это ничего не даст - всё равно никак не получится взломать пользователя зная только его позицию в сортировке хешу или соли. Стоит ли исправлять такие баги?
Можно не исправлять. Хотя лучше бы такого не допускать. В теории злоумышленник может зарегистрировать 100 аккаунтов, и по ним, зная их хеш, оценить чему примерно равен хеш других студентов. Это снижает число вариантов для перебора - примерно в 100 раз, если предположить что хеши генерируются случайно, то 100 аккаунтов разбивают множество хешей на 100 равных частей.
А еще, тут sql инъекции нет? Значения как-то проверяются перед подстановкой в запрос? Или они вообще в базу не идут?
> я сначала пишу $queries = $this->queries,
Ничего страшного. Хуже то, что у тебя нет комментариев перед полем queries и нельзя понять что это значит (из названия "запросы" я ничего не понял).
Алсо, вот наткнулся на видео https://www.youtube.com/watch?v=w3XUG6oyINI , вроде хвалят мол норм обьяснил парень, я вот сижу смотрю.
Только не изменилось ли кардинально ООП в семёрке?
>>804545
нет
>В теории злоумышленник может зарегистрировать 100 аккаунтов, и по ним, зная их хеш, оценить чему примерно равен хеш других студентов. Это снижает число вариантов для перебора - примерно в 100 раз, если предположить что хеши генерируются случайно, то 100 аккаунтов разбивают множество хешей на 100 равных частей.
Вот тут не понял. Можешь, пожалуйста, разъяснить поподробнее?
Зачем тебе ООП?
Допустим в 10 аккаунтах злоумышленника хеши распределились случайно. Для простоты пусть это будут хеши
acc0 0aaaa
acc1 1bbbb
acc2 2cccc
....
acc9 9xxxxx
Теперь злоумышленник сортирует список студентов по хешу. Допустим список выглядит так:
acc1
ivan ivanov
acc2
acc3
acc4
...
Злоумышленник теперь знает, что хеш ivan ivanov находится где-то между 1bbbb и 2cccc. Пространство для перебора сократилось в 10 раз.
То есть при случайном распроделении хешей имея N аккаунтов можно сократить число вариантов подбора в N раз. Если хеши длинные, то практически возможность взломать их то не даст, так как даже зная первые 3-4 цифры все равно остается еще много символов.
Но если удастся найти возможность задавать произвольный хеш для аккаунта (например через ошибку в форме регистрации или редактирования) то злоумышленник может методом деления пополам подбирать хеши других пользователей за короткое время.
Понял, спасибо.
ну раз макак то есть опыт, начинай решать задачи из учебника по 2-3 главы в день, что бы въехать в синтаксис и размять мозги алгоритмами, изучай параллельно как взаимодействовать с базой с одной стороны и как с юзером с другой (куки, сессии, формы, гет/пост и прочее) + можешь бутстрап навернуть. Хз, имхо если бы у меня под боком сейчас сидел падаван, я бы ему всё что знаю мпомог бы за 2 недели освоить, а если интенсивно, то и за неделю. Ну а далее мы бы с ним погрязли в ООП и прочих современных подходах к разработке, которые сука сам нихуя не понимаю :(
ясен хуй, сидишь ебашишь задачи из учебника http://archive-ipq-co.narod.ru/
кодишь прямо на http://ideone.com/
Хоть сейчас приступай и начинай отчитываться в тред, дерзай.
>пыхп до состояния работаю макакой в днище конторе?
Зачем тебе это? Да ты взвоешь после недели ковыряния в говне из Wordpress и Joomla, будешь ненавидеть свою работу, говорю из личного опыта. Куда все спешат? Не лучше ли годик-два поизучать дома, обзавестись знаниями, чтобы твоей квалификации хватало не только говно чистить, но и делать интересные, сложные задачи?
Опыт, меня скорее всего отчисляют из ненавистной шараги, а значит я могу вкатиться туда, куда мечтал вкатиться еще года полтора назад, к тому же, даже в самой днище конторе я смогу научиться хоть чему нибудь и заиметь хоть какой то опыт.
Думал как же хорошо и всё ништяк, и буду ща по 100 страниц в день осваивать, и за недельку в книгу въеду, и буду у мамы молодцом, а хуй там. На 70-й халява кончилась, пошла муть про абстрактные классы и интерфейсы, и тут я завис, просто реально сидел пытался понять в чем суть написанного и зачем это вкручено в примеры кода, которые там приведены, и так НИФИГА И НЕ ПОНЯЛ, блин. Как же сложна то. Надеюсь что сегодня разберусь таки. Параллельно сейчас сяду писать вектор что ли, хоть я его и писал уже год назад >>803294 но сейчас пожалуй решу с 0, что бы хорошо всё закрепить и повторить, ну и решать не отпизды, а используя почерпнутые в книжке знания.
Нет конечно, они дают только базовые знания о языке. Тебе нужно будет научится устанавливать и настраивать веб сервер с интерпретатором и базой данных, и на базовом уровне освоить хотя бы один MVC фреймворк, чтобы быть хорошим кандидатом в джуниоры. Вот как сделаешь три задачи из ОП поста (студенты, файлообменник и TestHub), тогда можешь считать себя джуниором.
А, я тебя понял. Ты не работаешь в днищеконторе, а только стремишься. Ну кароче пару месяцев займет минимум, в общем прочитай ОП-посты и не спрашивай хуйню. Всё равно придется дохуя работать и писать что бы научиться с 0 МОЧЬ В ВЁБ
Алсо мой хостер при любой ошибке кидает 500 Internal server error. Правильный подход или нет? И как они это делают, хз.
>как стать твоим юным падаваном?
Материализоваться в моей хате прямо здесь и сейчас со своей пекой/ноутом, что бы мне не приходилось отвлекаться на всякие скайпы и прочее говно, а тупо словами в свободное от своих дел время рассказывать как работают циклы и прочие функции.
секретный спойлер: тупо пересказывать тебе учебник опа и отправлять все равно перечитывать каждую главу по 2 раза, но если уж непонятно что, то сесть рядом и на примитивном уровне с 0 всё разжевать
Прост сядь почитать, попробуй пописать. Не будет для тебя никакого супер-легкого пути волшебного, при котором ты раз и уже джун. Придется всё равно всё освоить и всё проработать, что-то мб меньше, а что-то больше. ОТ себя могу посоветовать не сидеть долго на регулярках из учебника ОП-а, если не получается, а сразу переходить к сложным задачам и попытке сделать свои простейшие вещи.
Я просто даже не понимаю с чего начать. Уже неделю наверное у всех выспрашиваю, ктото отвечает про то, что надо начинать изучать базы данных и строение сети интернет, ктото пишет, что нужен html и css, вы советуете php. В итоге какойто анон посоветовал https://www.freecodecamp.com - будет ли с выполнения тамошних заданий профит?
>Поясните все же как надо реализовать MVC
В зависимости от того что и где у тебя на сайте пользователь накликал, запускаются разные контроллеры.
Например если пользователь заходит в раздел статьи (articles), то и запускается скрипт он же контроллер, он же класс articles.php
У контроллеров соответственно могут быть методы вида(показать статью, редактировать статью, создать статью и прочее)
Если пользователь заходит в раздел с другим функционалом, то другой контроллер соответственно всё обрабатывает.
Контроллер так же в свою очередь пытается понять кто пришел, можно ли ему тут быть, что он хочет, и можно ли ему это позволить. (ну например если пришел просто пользователь, то он может статью только посмотреть, а если автор, то и подредактировать, а незареганных нашщ контроллер вообще отправит регаться)
Если пользователь после всех проверок достоен того что хочет, то можно начинать спрашивать с модели вещи, которые позволят нам ответить на его запрос.
Модель это то, что с базой будет работать в этом случае. И например у неё есть методы: сложить в базу статью, спросить с базы статью, переписать в базе статью на новую.
Вот контроллер такой спросил с модели статью.
$article = Model->getArticle($id);
Ну и вот у тебя есть теперь информация, в виде какого-нибудь массива или объекта, которая нужна пользователю в переменной $article
Ну и ты передаешь её во вьюху, которая по сути является html-каркасом, с заготовленными вставками php-переменных.
Например у тебя во вьюхе будут места
<h1><?=$article->title;?></h1>
<p><?=$article->text;?></p>
и прочие ссылки на картинки и другие статьи.
Вот собственно и всё. ПОСМОТРЕЛИ КОНТРОЛЛЕРОМ ЧТО ЮЗЕР ХОЧЕТ, РЕШИЛИ ДАЕМ ЕМУ ЭТО ИЛИ НЕТ, СПРОСИЛИ ЧЕТ С МОДЕЛИ, ОБРАБОТАЛИ ЕСЛИ НАДО И ПЕРЕДАЛИ ВО ВЬЮХУ, В КОТОРОЙ ВСЁ РАССТАВИЛИ ПО МЕСТАМ.
>Поясните все же как надо реализовать MVC
В зависимости от того что и где у тебя на сайте пользователь накликал, запускаются разные контроллеры.
Например если пользователь заходит в раздел статьи (articles), то и запускается скрипт он же контроллер, он же класс articles.php
У контроллеров соответственно могут быть методы вида(показать статью, редактировать статью, создать статью и прочее)
Если пользователь заходит в раздел с другим функционалом, то другой контроллер соответственно всё обрабатывает.
Контроллер так же в свою очередь пытается понять кто пришел, можно ли ему тут быть, что он хочет, и можно ли ему это позволить. (ну например если пришел просто пользователь, то он может статью только посмотреть, а если автор, то и подредактировать, а незареганных нашщ контроллер вообще отправит регаться)
Если пользователь после всех проверок достоен того что хочет, то можно начинать спрашивать с модели вещи, которые позволят нам ответить на его запрос.
Модель это то, что с базой будет работать в этом случае. И например у неё есть методы: сложить в базу статью, спросить с базы статью, переписать в базе статью на новую.
Вот контроллер такой спросил с модели статью.
$article = Model->getArticle($id);
Ну и вот у тебя есть теперь информация, в виде какого-нибудь массива или объекта, которая нужна пользователю в переменной $article
Ну и ты передаешь её во вьюху, которая по сути является html-каркасом, с заготовленными вставками php-переменных.
Например у тебя во вьюхе будут места
<h1><?=$article->title;?></h1>
<p><?=$article->text;?></p>
и прочие ссылки на картинки и другие статьи.
Вот собственно и всё. ПОСМОТРЕЛИ КОНТРОЛЛЕРОМ ЧТО ЮЗЕР ХОЧЕТ, РЕШИЛИ ДАЕМ ЕМУ ЭТО ИЛИ НЕТ, СПРОСИЛИ ЧЕТ С МОДЕЛИ, ОБРАБОТАЛИ ЕСЛИ НАДО И ПЕРЕДАЛИ ВО ВЬЮХУ, В КОТОРОЙ ВСЁ РАССТАВИЛИ ПО МЕСТАМ.
Епт. Начинай со стандартных для любых ЯП конструкций, типа переменных, массивов, циклов, функций и т.п. Эти вещи вообще почти одинаковые во всех Си-подобных языках, можешь вообще любой учебник открыть, там все одно и тоже. Потом ООП учи. Ну а дальше изучай уже конкретно интересную тебе технологию. Ну и конечно же, если ты хочешь в веб, то выучи хотя бы основые html/css, без этого никуда. Почитай еще кстати чем отличается бек-энд от фронт-энда.
Т.е. контролер это тот самый index.php выходит? А вью это уже файл, который показывает статьи и прочее?
Что бы стать джуном в говноконтору, тебе нужно знать строение любой веб страницы, и что за ней за что отвечает. всякие блоки там, ссылки картинки списки таблицы и прочее.
Это собственно html+css
Можешь сюда сходить если всё лень и попробовать пол дня поизучать основы https://htmlacademy.ru даже регаться не нужно вроде, прост начал и пошел делать одно задание за другим.
Но в современном мире нам не достаточно прост страниц которые написаны на html, понимаешь? Интернет как бы ДИНАМИЧЕСКИЙ, возьмем тот же двач, он постоянно меняется, повяляются новые посты, новые треды, новые картинки и прочее, понимаешь?
Для этого и нужен php, потому что он как раз и делает такие сайты как двач динамическим.
Например какой-то вася написал пост, php его обработал и сложил в базу данных (допустим mysql) и когда следующий анон зайдет в тред, опять же специально написанный скрипт сгенерирует ему страницу так, что пост васи там уже есть. Хотя минуту назад его бы там не было.
То есть задача программиста сделать так, что бы наш php-код писал в итоге html-страницы и отдавал юзерам постоянно менающийся контент.
Надеюсь доходчиво пояснено. В общем и целом тебе нужно уметь воспроизводить весь этот цикл, тут мы изучением всего этого и занимаемся.
А задачи начинаются ясен хер с примитивов, ибо сначала нужно научиться писать helol world и складывать числа, а потом уже переходить к умным скриптам, ты бы кстати уже мог пройти 2 главы в учебнике пока тут ищешь легкий путь и выспрашиваешь, как бы тебе не выучить чего лишнего.
>Для этого и нужен php, потому что он как раз и делает такие сайты как двач динамическим.
А двачик то на питоне написан, кек.
>
В самом примитивном виде наверное зачатки мвц 10 лет назад выглядели так:
файл допустим article.php на который юзер заходил site/article.php
всякие проверки
if ($_GET) {
}
if ($_COOKIE) {
}
include('functions.php'); - некий предок современной модели где были свалены функции
$article = get_article($id); -запрос в самописную функцию которая лежит в нашей "модели"
include('template.php'); - подгружаем шаблон, а он же вьюха в современной интерпритации, в котором расставляем по местам всё и генерируем нашу страницу, которую отдаем юзеру.
Сейчас же всё на ООП и написано классами с умным роутингом и всё такое, и у тебя допустим юзер проходит по ссылке вида:
site/article/add и поподает в метод add, контроллера article
Но в целом общая схема не изменилась
Пусть меня обоссут если что, я не особо прошарен, mvc постигал на кодигнайтере.
>
В самом примитивном виде наверное зачатки мвц 10 лет назад выглядели так:
файл допустим article.php на который юзер заходил site/article.php
всякие проверки
if ($_GET) {
}
if ($_COOKIE) {
}
include('functions.php'); - некий предок современной модели где были свалены функции
$article = get_article($id); -запрос в самописную функцию которая лежит в нашей "модели"
include('template.php'); - подгружаем шаблон, а он же вьюха в современной интерпритации, в котором расставляем по местам всё и генерируем нашу страницу, которую отдаем юзеру.
Сейчас же всё на ООП и написано классами с умным роутингом и всё такое, и у тебя допустим юзер проходит по ссылке вида:
site/article/add и поподает в метод add, контроллера article
Но в целом общая схема не изменилась
Пусть меня обоссут если что, я не особо прошарен, mvc постигал на кодигнайтере.
Ну это сложный вопрос. Что бы до совсем нубов довести, целые книги блядь по MVC пишут, я же не буду тебе книгу писать тут, задай конкретный вопрос, я тебе постараюсь ответить.
Ну хотя бы как примерно это реализовать на примере задачи со студентами.
Я сам не знаю как стартануть студентов на pure-php, как я уже говорил, я на примере уже готового фрейморвка знакомился с mvc, и сейчас сам сел за ООП конкретно и сосу в нем БОЛЬШИЕ АБСТРАКТНЫЕ ХУИ >>804813
У меня большие проблемы как стартануть и заткнуть всё с написанием ЯДРА так сказать, и роутинга, поэтому откатился назад и продолжу дрочить другие вещи для лучшего понимания.
Модель в студентах супер-легко
Вроде в этой задаче хватит 1 класса под модель, больше не вижу смысла.
Функции нужно реализовать примерно следующие:
....function getStudent($id) {
........тут всё просто, даем функции $id студента, который например зашел на свою страницу, она нам возвращает всю его инфу
....}
Class StudentModel {
....function getStudents($from, $to) {
........эта будет брать с базы несколько студентов, и возвращать нам большой массив с их именами или что там нужно для первой страницы, где будет весь список студентов. Например ты на первой странице списка и тебе нужно вывести с 1 по 10 студентов, соответственно твой контроллер должен передать этой функции аргументы 1 и 10, ну ты понял.
....}
....function addStudent (array $studentData) {
........Эту функцию будет вызывать контроллер когда студент будет регистрироваться и передавать в неё ту инфу которую студент ввел при регистрации, инфу конечно нужно проверить и обработать на каком-то уровне, сама функция еще всё это должна сложить в базу
....}
....function rewriteStudent($id, array $studentData) {
........Опять же, при редактировании, контроллер передает сюда $id студента которого мы собрались редактировать, а так же массив с редактируемыми данными, допустим такой передали array ('age' => 19, 'name' => 'petya'); соответственно функция должна разбирать этот массив на кусочки и перезаписывать в базе поля age и name у студента с id = $id
....}
Со вьюхами всё тоже предельно просто если ты знаешь хоть немного html
Хотя я не знаю опять же как красиво реализовать подгрузку вьюх в ядре нашего проекта, что бы в контроллере ты просто подгружал вьюху в конце как-то так:
View->load($viewData, 'studentsList.php');
а твой метод парсил $viewData и позволял к его элементам из вьюхи обращаться через переменные, сложна объяснить, игнайтеровское наследие в голове, блджад
Там например в контроллере собирали массив $data
$data['name'] = $this->students->getStudent($this->id)->name;
$data['surname'] = $this->students->getStudent($this->id)->surname;
...
Потом когда всё собрано писали:
$this->load->view('student.php', $data);
а во вьюхе ты мог в нужные места вставлять <?=$name?> и <?=$surname?>
Охуеваешь попытки осмыслить все эти цепочки и что вообще тут делает $this в каждой строчке, если это обращение к методам/полям объекта в контексте себя? То-то же, представь как мой мозг искалечен этим всем.
Надеюсь тебе поможет это, если что спрашивай еще что-нибудь. Модельные методы можно сделать и умнее, что бы например у тебя была всего 1 функция возврата студентов а не две, и там внутри было условие, с разделением. Так же одна функция может отвечать и за запись в базу и за редактирование, но по мне так лучше.
Я сам не знаю как стартануть студентов на pure-php, как я уже говорил, я на примере уже готового фрейморвка знакомился с mvc, и сейчас сам сел за ООП конкретно и сосу в нем БОЛЬШИЕ АБСТРАКТНЫЕ ХУИ >>804813
У меня большие проблемы как стартануть и заткнуть всё с написанием ЯДРА так сказать, и роутинга, поэтому откатился назад и продолжу дрочить другие вещи для лучшего понимания.
Модель в студентах супер-легко
Вроде в этой задаче хватит 1 класса под модель, больше не вижу смысла.
Функции нужно реализовать примерно следующие:
....function getStudent($id) {
........тут всё просто, даем функции $id студента, который например зашел на свою страницу, она нам возвращает всю его инфу
....}
Class StudentModel {
....function getStudents($from, $to) {
........эта будет брать с базы несколько студентов, и возвращать нам большой массив с их именами или что там нужно для первой страницы, где будет весь список студентов. Например ты на первой странице списка и тебе нужно вывести с 1 по 10 студентов, соответственно твой контроллер должен передать этой функции аргументы 1 и 10, ну ты понял.
....}
....function addStudent (array $studentData) {
........Эту функцию будет вызывать контроллер когда студент будет регистрироваться и передавать в неё ту инфу которую студент ввел при регистрации, инфу конечно нужно проверить и обработать на каком-то уровне, сама функция еще всё это должна сложить в базу
....}
....function rewriteStudent($id, array $studentData) {
........Опять же, при редактировании, контроллер передает сюда $id студента которого мы собрались редактировать, а так же массив с редактируемыми данными, допустим такой передали array ('age' => 19, 'name' => 'petya'); соответственно функция должна разбирать этот массив на кусочки и перезаписывать в базе поля age и name у студента с id = $id
....}
Со вьюхами всё тоже предельно просто если ты знаешь хоть немного html
Хотя я не знаю опять же как красиво реализовать подгрузку вьюх в ядре нашего проекта, что бы в контроллере ты просто подгружал вьюху в конце как-то так:
View->load($viewData, 'studentsList.php');
а твой метод парсил $viewData и позволял к его элементам из вьюхи обращаться через переменные, сложна объяснить, игнайтеровское наследие в голове, блджад
Там например в контроллере собирали массив $data
$data['name'] = $this->students->getStudent($this->id)->name;
$data['surname'] = $this->students->getStudent($this->id)->surname;
...
Потом когда всё собрано писали:
$this->load->view('student.php', $data);
а во вьюхе ты мог в нужные места вставлять <?=$name?> и <?=$surname?>
Охуеваешь попытки осмыслить все эти цепочки и что вообще тут делает $this в каждой строчке, если это обращение к методам/полям объекта в контексте себя? То-то же, представь как мой мозг искалечен этим всем.
Надеюсь тебе поможет это, если что спрашивай еще что-нибудь. Модельные методы можно сделать и умнее, что бы например у тебя была всего 1 функция возврата студентов а не две, и там внутри было условие, с разделением. Так же одна функция может отвечать и за запись в базу и за редактирование, но по мне так лучше.
Есть у тебя сайт, есть такой запрос site.com/home/student/4
class FrontController обрабатывает входящий запрос и исходя из этого понимает, что нужно запустить class HomeController и функцию student($id){}
Ты получил запрос и в контроллере ты его обрабатываешь то есть в функции student($id){} ты обращаешься к модели у которой запрашиваешь студента с таким айдишником и модель возвращает тебе обьект Student со свойствами нужного тебе студента.
( модель это класс который работает с бд, зачастую делается одна таблица - одна модель, в данной ситуации модель будет называться Student )
Далее ты в контроллере либо запускаешь класс который запускает представление либо просто пишешь так reqiure ('твой файлик php') и каким-то хуем передаешь еще туда и свой обьект и уже в представлении показываешь свойства своего обьекта и человек получает инфу о студенте с таким-то айдишником
это тебе лишь примерно показал пример, очень простой и примитивный, конечно же делать такой запрос тупо как home/student/5 тупо потому что он очень длинный, можешь во фреймворках как -то реализовано
мимо-другой-анон
Одному классу выдели один файл, да.
Далее можешь просто инклудить, можешь написать свой класс подгрузчик, который будет инклудить файлы вместо тебя.
например в том же игнайтере если ты в контроллере хочешь получить доступ к модели, то можно сначала написать
$this->load->model('ModelName.php');
Ну и ты можешь что-то подобное реализовать у себя в "ядре"
Можешь так же заняться тем, чему ОП будет рад, и написать автолоадер прочитав вот это
http://php.net/manual/ru/language.oop5.autoload.php
http://php.net/manual/ru/function.spl-autoload-register.php
>Большинство разработчиков объектно-ориентированных приложений используют такое соглашение именования файлов, в котором каждый класс хранится в отдельно созданном для него файле.
А зачем так делать?
Наверное потому что в каком-нибудь проекте большом у тебя не одна моделька, а 100, а еще и не ты 1 работаешь над всеми этими модельками, а например еще 10 ребят. Ну и вот, тип для удобства, поиска класса в файлах.
Опять же что бы просто заинклудить файлик User.php, а не искать модель юзеров в MegaProjectModel.php среди 100500 других классов и всё такое. Наверное корни еще растут губоко в те времена, когда не было систем контроля версий и ты мог затереть чужие правки в файлах.
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
http://archive-ipq-co.narod.ru/
Я ни в коем случае не ищу легких путей, просто два дня одно поизучаешь, потом оказывается что ты учил херню, потом два дня учишь другое, оказывается, ты не знаешь основ языка, учишь третье, в итоге получается херня, так еще и время потрачено. Вот смотри, выучусь я по твоим рекомендациям, и уже есть шанс пойти в говноконтору? Или по крайней мере фриланс?
Значит я запутался, просто думал там типичный учебник по конкретным функциям языка, где не объясняются основы программирования. Сори за ебланство
так ты обьясни конкретно, что ты хочешь учить, не понятно же нихрена?
напиши конкретно, что ты не понимаешь и хочешь понять на столько доступно на сколько сможешь
мимо-другой-анон
Ну там ну тип хочу, вот недельку ну тип поебланить и уже джун, что бы потом хуяк-хуяк и уже мидол через год, в общем ничего не делать и всё было, ну там зп 5к$, в японию потом уеду, там говорят всё есть))))
простите
Если конкретно, начать с основных основ программирования (что такое массивы, функции и т.д.), потому как вкатываюсь с нуля, после этого изучить html/css/php, по возможности вкатиться в Джаваскрипт, проблема в том, что, я даже не уверен, что именно это мне нужно. В общем, вкатиться в веб-программирование
Даун, не? Заранее сказал, что готов учиться столько, сколько нужно, тому, чему нужно, но мне надо узнать что именно учить. Усидчивость есть, с людьми могу хоть неделями не разговаривать, работать и учиться всегда готов. Просто я серьезно не могу разобраться, потому что каждый советует по разному
>Заранее сказал, что готов учиться столько, сколько нужно, тому, чему нужно...
Я тоже готов каждый день ебать тянку своим 18см болтом, но проблема в том, что у меня тянки нету. А их столько вокруг ходит, что я прост не знаю какую выбрать, ага, хуй знает в общем, они все такие разные, вдруг прогадаю, выебу тянку, а она не та самая, зря время потратил тольк. Продолжу лучше по улице ходить да на тянок смотреть, но не подходить к ним.
сложно все обьяснить в двух словах о всем, что тебе нужно знать.
Скажу тебе так начинай с учебника ОПа, а потом по ходу дела разберешься и со временем придет понимание, для меня это тоже было проблемой поначалу.
Двачую братишку, веб сука объемная штука. Тут дохуя всего задействованно, что бы обходить костыли устаревших до момента выхода протоколов и эмулировать работу обычных приложений. Надеюсь веб будущего будет куда лучше в этом плане.
>Если конкретно, начать с основных основ программирования (что такое массивы, функции и т.д.), потому как вкатываюсь с нуля
Так начинай, лол, в чем проблема?
Читай шапку треда, там для старта в пыху более чем достаточно. До момента ООП вообще нихуя сложного. Тем более, что открыв учебник по любому си-подобному ЯП ты найдешь все тоже самое.
>echo "homoCreditTotal: {$homoCreditTotal} руб.\n";
Потому что ты строку выводишь я так понял.
https://ideone.com/tB0W85
Алсо твоя функция нихуя не возвращает же.
Попробуей дописать в функции return $homoCreditTotal;
И выводи echo getBalanceInFuture(какие у тебя там значения, ну ты понел);
Мог бы и не пожлобиться на коменты, нуфагу, он может и так не понять. Короче слушай - функция должна всегда-то что-то возвращать, иначе она бесполезна.
Нет не бесполезна. Функция может и просто эхать что-то на экран. Например целую html страницу готовую, почему бы и нет.
Просто он вызывает функцию внутри самой себя и ничего не ретернит и не понимает о том, что переменные доступные внутри функции и переменные снаруже - это два разных мира :(
Стоит еще в коментах дописать, что аргументы это далеко не обязательно какие-то переменные.
А что еще? Предлагаешь ему сразу рассказать что можно передать функцию в функцию или что?
Чому бы и нет? Будет нуфак знать насколько пыха богата возможностями.
Интересно, что за удача "ждете" меня сегодня вечером. ) Надеюсь молния не ударит ) Переписал последнюю строку без условия просто else.
Нашел прикольный онлайн интерпретатор
http://codepad.org/M7vtRNPd
Указывает, что за ошибка и в какой строке.
Тупанул с этой задачей )
Что бы интерпритатор понимал, что в них не строка а код.
Привет, аноны. Пишу интернет магаз на yii2 и вот дошел до админки, назрел вопрос. как лучше сделать админку:
1) написать отдельный контроллер Admin?
2) создать директорию в корневой и названием Admin и там писать приложение?
как делать правильно, какие плюсы и минусы?
>1) написать отдельный контроллер Admin?
Ну да, звучит разумно. Пишешь новый контроллер, ему делаешь свои вьюхи. По возможности расширяешь модель слегка, что бы можно было делать все то же что и юзер но больше.
>2) создать директорию в корневой и названием Admin и там писать приложение?
То есть хочешь как бы второе приложение написать с доступом к той же базе? Придется энивей копипастить код и модели, так зачем? Разве суть ООП как раз не в расширяемом без копипасты коде?
Спасибо, няша. Ты меня доступно убедил)
Данные по 1 циклу показывает, там за 60 тысяч должно быть
>Объясните плиз
Учись сам добывать информацию, у тебя под носом гигантская база знаний.
Допустим, у тебя есть переменная $a, равна она 1. Тогда:
echo "qwe{$a}qwe"; // Выведет "qwe1qwe"
echo "qwe$aqwe"; // Ошибка, так как интерпретатор будет искать переменную $aqwe
Проблема в том, что нужно организовать удаление сообщений по чекбоксам. И загвоздка тут в том, что мне нужно организовать кнопку за рамками формы.
Как мне передать значения чекбоксов в скрипт? Нужно ли этот скрипт писать в отдельном файле?
Сама форма + чекбоксы с таблицей:
<tbody>
<form id='checkBox' method='post' target='delete_mail.php'>
<?php
if(isset($_COOKIE['id']))
{
$result = mysqli_query(mysqli_connect("localhost", "login", "password", "database"), "SELECT * FROM messages WHERE user_id='".mysqli_real_escape_string(mysqli_connect('localhost', 'login', 'password', 'database'), $_COOKIE['id'])."'");
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
echo "<tr><td>Отметить: <input type='checkbox' name='item[]' value='".$row["message_id"]."'></td><td><a data-toggle='popover' title='Текст письма' data-content='".$row["message_body"]."'>" . $row["message_to"]. "</td><td> " . $row["message_subject"]. "</td><td>" . $row["message_date_time"]. "</td></tr>";
}
} else {
echo "<tr><td>0 results</td></tr>";
}
}
?>
</form>
</tbody>
Проблема в том, что нужно организовать удаление сообщений по чекбоксам. И загвоздка тут в том, что мне нужно организовать кнопку за рамками формы.
Как мне передать значения чекбоксов в скрипт? Нужно ли этот скрипт писать в отдельном файле?
Сама форма + чекбоксы с таблицей:
<tbody>
<form id='checkBox' method='post' target='delete_mail.php'>
<?php
if(isset($_COOKIE['id']))
{
$result = mysqli_query(mysqli_connect("localhost", "login", "password", "database"), "SELECT * FROM messages WHERE user_id='".mysqli_real_escape_string(mysqli_connect('localhost', 'login', 'password', 'database'), $_COOKIE['id'])."'");
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
echo "<tr><td>Отметить: <input type='checkbox' name='item[]' value='".$row["message_id"]."'></td><td><a data-toggle='popover' title='Текст письма' data-content='".$row["message_body"]."'>" . $row["message_to"]. "</td><td> " . $row["message_subject"]. "</td><td>" . $row["message_date_time"]. "</td></tr>";
}
} else {
echo "<tr><td>0 results</td></tr>";
}
}
?>
</form>
</tbody>
Причина кнопки за рамками формы в том, что она портит структуру таблицы.
>Зачем нужна инкапсуляция? Ну например если у тебя логика хеширования скрыта внутри класса и ты захочешь поменять ее, тебе достаточно будет поменять только этот класс и не искать, не вызываются ли методы где-то еще.
Но тогда всё равно же придётся искать метод который предоставляем наружу. Если мы поменяем внутреннюю логику метода так, что он будет возвращать свершено другой результат, например заместо строки массив, то метод который мы предоставляем наружу, тоже нужно будет поменять, и для этого нужно так же искать где он вызывается.
Я перечитал твой мануал по инкапсуляции и могу сказать, что она нужно скорее чтобы скрывать внутреннюю логику, а не облегчение её редактирования.
Так же, мне теперь кажется, что я зря в некоторых сущностях делал свойства закрытыми, ведь при работе с ними нет никакой внутренней логики, мы просто их меняем. И чтобы их не поменяли на неверное значение есть класс валидации.
https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Student.php#L8-L16
https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Student.php#L50-L97
Я не могу вспомнить как я научился такому методу. У тебя случайно не было так написано в уроке по DI? Так вообще делают?
>>804386
>А ты кстати смотришь код других анонов?
Да, смотрю, но только чтобы понять как работают отдельные функции, чтобы самому не запутаться. У них там всё равно всё сделано через роутер, а я даже не знаю откуда они берут эту задачу чтобы делать через него, не говоря уже о том, что я не знаю зачем он нужен и как он работает. Я бы хотел сделать свою задачу через него, но я не знаю даже что начать читать чтобы его сделать.
Еще у этого анона есть такие классы как от Request, Response - мне это тоже не понятно зачем они нужны.
Я не могу обещать что я сразу же возьмусь за эти задачи, т.к. я хочу побыстрей уже взяться за задачу на Slim'е, но я могу точно сказать, что если ты мне подскажешь с чего начать, я буду это изучать во время решения других задач.
>но ты можешь просто для сравнения посмотреть на его код.
У него, в отличии от моего кода, логика регистрации, залогинивания, а так же хеширования и создания соли, сокрыта в хелпере. Раньше я думал, что контроллер отвечает за логику того или иного действия, а модель это, исходя из названий содержащихся в ней классов, всего лишь вспомогательные методы для него. Ведь как может отвечать за всю логику лишь Помощник? Валидатор тоже не может отвечать за всю логику. Класс с работой с БД - тоже. Это сбивает с толку. Так почему в Модели, которая отвечает за логику, за внутреннее состояние программы, мы не содержим классы как AuthModel или просто Auth(orization)?
>>804386
>Насчет авторизации - по моему, у тебя там многовато кук ставится. Целых 3 куки. зачем так много?
>
>Одна кука, допустим (id), идентифицирует пользователя
>Другая (hash), допустим, аутентифицирует его (то есть подтверждает что это он, а не хакер, подделавший id)
>
>Ну то есть 2 куки - это что-то вроде формы с логином и паролем. Логин идентифицирует, пароль подтверждает подлинность.
>
>Но третья-то зачем?
Так токен же, для csrf протекции.
Я тоже сомневался стоит ли её создавать и при регистрации.
>>804434
>Ну например, поставить в соответствие студенту место, которое он занимает в списке лучших по баллам:
>
>$place = 10;
>$spl[$student] = $place;
>
>А позже можно взять это значение:
>
>printf("%s занял %d место\n", $student->name, $spl[$place]);
$spl[$place] вернет NULL. Ты наверно хотел написать $spl[$student] вместо этого?
>>804434
>Это значит, что в SplOS можно заносить объекты, не привязывая к ним данные.
О каких данных здесь может быть речь?
>>804445
>А еще, тут sql инъекции нет? Значения как-то проверяются перед подстановкой в запрос? Или они вообще в базу не идут?
Нет, не идут, но сейчас я буду переделывать используя LIMIT, а не перебирать n студентов. Я уже прочитал новый урок про инъекции и знаю как с этим бороться.
>Зачем нужна инкапсуляция? Ну например если у тебя логика хеширования скрыта внутри класса и ты захочешь поменять ее, тебе достаточно будет поменять только этот класс и не искать, не вызываются ли методы где-то еще.
Но тогда всё равно же придётся искать метод который предоставляем наружу. Если мы поменяем внутреннюю логику метода так, что он будет возвращать свершено другой результат, например заместо строки массив, то метод который мы предоставляем наружу, тоже нужно будет поменять, и для этого нужно так же искать где он вызывается.
Я перечитал твой мануал по инкапсуляции и могу сказать, что она нужно скорее чтобы скрывать внутреннюю логику, а не облегчение её редактирования.
Так же, мне теперь кажется, что я зря в некоторых сущностях делал свойства закрытыми, ведь при работе с ними нет никакой внутренней логики, мы просто их меняем. И чтобы их не поменяли на неверное значение есть класс валидации.
https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Student.php#L8-L16
https://github.com/someApprentice/Students/blob/master/app/Model/Entity/Student.php#L50-L97
Я не могу вспомнить как я научился такому методу. У тебя случайно не было так написано в уроке по DI? Так вообще делают?
>>804386
>А ты кстати смотришь код других анонов?
Да, смотрю, но только чтобы понять как работают отдельные функции, чтобы самому не запутаться. У них там всё равно всё сделано через роутер, а я даже не знаю откуда они берут эту задачу чтобы делать через него, не говоря уже о том, что я не знаю зачем он нужен и как он работает. Я бы хотел сделать свою задачу через него, но я не знаю даже что начать читать чтобы его сделать.
Еще у этого анона есть такие классы как от Request, Response - мне это тоже не понятно зачем они нужны.
Я не могу обещать что я сразу же возьмусь за эти задачи, т.к. я хочу побыстрей уже взяться за задачу на Slim'е, но я могу точно сказать, что если ты мне подскажешь с чего начать, я буду это изучать во время решения других задач.
>но ты можешь просто для сравнения посмотреть на его код.
У него, в отличии от моего кода, логика регистрации, залогинивания, а так же хеширования и создания соли, сокрыта в хелпере. Раньше я думал, что контроллер отвечает за логику того или иного действия, а модель это, исходя из названий содержащихся в ней классов, всего лишь вспомогательные методы для него. Ведь как может отвечать за всю логику лишь Помощник? Валидатор тоже не может отвечать за всю логику. Класс с работой с БД - тоже. Это сбивает с толку. Так почему в Модели, которая отвечает за логику, за внутреннее состояние программы, мы не содержим классы как AuthModel или просто Auth(orization)?
>>804386
>Насчет авторизации - по моему, у тебя там многовато кук ставится. Целых 3 куки. зачем так много?
>
>Одна кука, допустим (id), идентифицирует пользователя
>Другая (hash), допустим, аутентифицирует его (то есть подтверждает что это он, а не хакер, подделавший id)
>
>Ну то есть 2 куки - это что-то вроде формы с логином и паролем. Логин идентифицирует, пароль подтверждает подлинность.
>
>Но третья-то зачем?
Так токен же, для csrf протекции.
Я тоже сомневался стоит ли её создавать и при регистрации.
>>804434
>Ну например, поставить в соответствие студенту место, которое он занимает в списке лучших по баллам:
>
>$place = 10;
>$spl[$student] = $place;
>
>А позже можно взять это значение:
>
>printf("%s занял %d место\n", $student->name, $spl[$place]);
$spl[$place] вернет NULL. Ты наверно хотел написать $spl[$student] вместо этого?
>>804434
>Это значит, что в SplOS можно заносить объекты, не привязывая к ним данные.
О каких данных здесь может быть речь?
>>804445
>А еще, тут sql инъекции нет? Значения как-то проверяются перед подстановкой в запрос? Или они вообще в базу не идут?
Нет, не идут, но сейчас я буду переделывать используя LIMIT, а не перебирать n студентов. Я уже прочитал новый урок про инъекции и знаю как с этим бороться.
$frontController=new Project\Controllers\FrontController($container);
нормально читается (то есть автозагрузчик composer'а работает нормально), а в container.php строка
45 return new Project\Classes\Authorization($c['table'])
уже выдаёт ошибку
Насчет системы публикации скриптов. Можешь объяснить или дать ссылку как это все работает (как например заставить бутстрап попасть в паблик папку)? Гуглю и ничего не понимаю, как-то сложно по сравнению с композером все вручную ставить. Поставил gulp (потому что он вроде в отличии остальных на виндоус и на него хоть что-то в гугле откопал) и завис в туториалах. Это все потом будет в таком файле как у анона https://github.com/foobar1643/filehosting/blob/master/post-install.sh и подцепляться в composer.json?
<?php
error_reporting(-1);
$humanDice1 = mt_rand (1, 6);
$humanDice2 = mt_rand (1, 6);
$compDice1 = mt_rand (1, 6);
$compDice2 = mt_rand (1, 6);
echo "У человека выпало ($humanDice1) и ($humanDice2)\nУ компьютера выпало ($compDice1) и ($compDice2)\n";
$humanSum = ($humanDice1 + $humanDice2);
$compSum = ($compDice1 + $compDice2);
if ($humanSum > $compSum) {
echo "HUMAN WINS!!!";
} elseif ($humanSum < $compSum) {
echo "HUMAN NOT WINS!!!";
} elseif (($humanDice1 == $humanDice2) && ($compDice1 == $compDice2)) {
echo "DABLS!!!";
} else ($humanSum == $compSum) {
echo "HUMAN IS LIKE COMPUTER!!!";
}
<?php
error_reporting(-1);
$humanDice1 = mt_rand (1, 6);
$humanDice2 = mt_rand (1, 6);
$compDice1 = mt_rand (1, 6);
$compDice2 = mt_rand (1, 6);
echo "У человека выпало ($humanDice1) и ($humanDice2)\nУ компьютера выпало ($compDice1) и ($compDice2)\n";
$humanSum = ($humanDice1 + $humanDice2);
$compSum = ($compDice1 + $compDice2);
if ($humanSum > $compSum) {
echo "HUMAN WINS!!!";
} elseif ($humanSum < $compSum) {
echo "HUMAN NOT WINS!!!";
} elseif (($humanDice1 == $humanDice2) && ($compDice1 == $compDice2)) {
echo "DABLS!!!";
} else ($humanSum == $compSum) {
echo "HUMAN IS LIKE COMPUTER!!!";
}
Понял где проебался, сори за офтоп, помощь ненужна
Алсо еще хотел поговорить про цветовые схемы. Недавно читал, что я кобы ЧБ схема меньше грузит глаза, это правда? Кто-то сравнивал по ощущениям, допустим 8 часов работы с черным и 8 часов работы с белым фоном?
Я люблю светлые схемки. Но сижу только на чёрной, потому что в код на светлой схеме мне приходится вглядываться. На тёмной код читается сам собой.
Общая идея такая. При выгрузке сайта у нас может появиться необходимость что-то делать со статическими файлами (js/css/картинки), например:
- копировать файлы библиотек в публичную папку (твой случай)
- склеивать css файлы в один и минифицировать ради ускорения загрузки сайта
- конвертировать SVG картинки (которые не везде и не всегда корректно отображаются) в PNG-картинки, да еще и в разных размерах.
- объединять мелкие картинки в спрайты и править соответствующий css ради оптимизации
Для решения всех этих задач надо сделать программу или скрипт, который будет это делать. Это может быть самописный скрипт или ты можешь использовать существующие программы: gulp, make.
Вот пример скрипта копирования файлов на bash:
function copyFiles() {
cp -R "$@" public
}
copyFiles vendor/jquery/dist
copyFiles vendor/library/lib.css
Вот пример скрипта на php:
<?php
$rootDir = ....;
$sources = [
$rootDir . '/vendor/jquery/dist/',
$rootDir . '/vendor/library/lib.js'
];
foreach ($sources as $source) {
copyToPublicDir($source);
}
Примеры скриптов на make или gulp ты можешь попробовать написать сам, почитав мануалы и туториалы к ним.
Там еще можно придумать всякие оптимизации - например, на линуксе вместо копирования можно создавать симлинки, что быстрее.
Имея скрипт публикации, ты можешь вызывать его в любой момент чтобы скопировать статичесские файлы. Также ты можешь прописать его вызов в composer.json, чтобы он вызывался после установки или обновления зависимостей: https://getcomposer.org/doc/articles/scripts.md (англ, при желании наверно можно найти и русскую статью).
Главнвй принцип, что такие вещи надо автоматизировать. Чтобы для разворачивания сайта надо было выполнить несколько команд и не делать рутинных действий.
Уточни, что именно тебе непонятно.
> Можешь объяснить или дать ссылку как это все работает (как например заставить бутстрап попасть в паблик папку)?
Либо написать скрипт руками либо настроить gulp или make. Я бы написал руками так как случай тривиальный и я знаю bash.
> Это все потом будет в таком файле как у анона https://github.com/foobar1643/filehosting/blob/master/post-install.sh и подцепляться в composer.json?
да, но для разворачивания твоего проекта надо будет сначала поставить ноду и gulp. На линуксе впрочем это недолго.
Пример у анона - как раз самописный скрипт на bash.
> и завис в туториалах.
Ну нужно знание яваскрипта и хотя бы базовые представления о среде Node.JS.
Общая идея такая. При выгрузке сайта у нас может появиться необходимость что-то делать со статическими файлами (js/css/картинки), например:
- копировать файлы библиотек в публичную папку (твой случай)
- склеивать css файлы в один и минифицировать ради ускорения загрузки сайта
- конвертировать SVG картинки (которые не везде и не всегда корректно отображаются) в PNG-картинки, да еще и в разных размерах.
- объединять мелкие картинки в спрайты и править соответствующий css ради оптимизации
Для решения всех этих задач надо сделать программу или скрипт, который будет это делать. Это может быть самописный скрипт или ты можешь использовать существующие программы: gulp, make.
Вот пример скрипта копирования файлов на bash:
function copyFiles() {
cp -R "$@" public
}
copyFiles vendor/jquery/dist
copyFiles vendor/library/lib.css
Вот пример скрипта на php:
<?php
$rootDir = ....;
$sources = [
$rootDir . '/vendor/jquery/dist/',
$rootDir . '/vendor/library/lib.js'
];
foreach ($sources as $source) {
copyToPublicDir($source);
}
Примеры скриптов на make или gulp ты можешь попробовать написать сам, почитав мануалы и туториалы к ним.
Там еще можно придумать всякие оптимизации - например, на линуксе вместо копирования можно создавать симлинки, что быстрее.
Имея скрипт публикации, ты можешь вызывать его в любой момент чтобы скопировать статичесские файлы. Также ты можешь прописать его вызов в composer.json, чтобы он вызывался после установки или обновления зависимостей: https://getcomposer.org/doc/articles/scripts.md (англ, при желании наверно можно найти и русскую статью).
Главнвй принцип, что такие вещи надо автоматизировать. Чтобы для разворачивания сайта надо было выполнить несколько команд и не делать рутинных действий.
Уточни, что именно тебе непонятно.
> Можешь объяснить или дать ссылку как это все работает (как например заставить бутстрап попасть в паблик папку)?
Либо написать скрипт руками либо настроить gulp или make. Я бы написал руками так как случай тривиальный и я знаю bash.
> Это все потом будет в таком файле как у анона https://github.com/foobar1643/filehosting/blob/master/post-install.sh и подцепляться в composer.json?
да, но для разворачивания твоего проекта надо будет сначала поставить ноду и gulp. На линуксе впрочем это недолго.
Пример у анона - как раз самописный скрипт на bash.
> и завис в туториалах.
Ну нужно знание яваскрипта и хотя бы базовые представления о среде Node.JS.
Скорее всего Project... отсчитывается от текущего неймспейса и надо писать \Project\.... Либо автозагрузчик еще не подключен. Либо опечатка в имени класса.
Ты можешь попробовать отдебажить ситуацию, натыкав echo или var_dump в autoload.php
>>805318
Кнопку можно привязать к форме в новых бразузерах специальным HTML5 атрибутом. Можно обрабатывать нажатие скриптом. Но лучше конечно поправить кривую верстку и поместить кнопку в форме.
>>805214
Мануал http://php.net/manual/ru/language.types.string.php#language.types.string.parsing
>>805219
Для админки обычно есть такие варианты:
- сделать 2 отдельных приложения (модуля или как там это называется) - frontend (сам сайт) и admin. профит в том, что мы можем например централизованно разрешать доступ к админке только по паролю.
https://yiiframework.com.ua/ru/doc/guide/2/structure-modules/
http://www.yiiframework.com/doc-2.0/guide-structure-modules.html
- сделать базовый админский контроллер и наследовать контроллеры админки от него. В базовом контроллере сделать проверку логина и всякие полезные функции. Недостаток в том, что если забыть отнаследоваться от нужного контроллера можно например случайно отключить систему авторизации.
Я бы делал через модули.
Вообще, я скажу что модули пригодятся при разработке огромных проектов. Потому что если у тебя 20 человек несколько лет пишет код и они валят все контроллеры в одну папку то скоро эта папка станет нечитамой. Разделение сайта на модули позволяет организовать код лучше.
>>805231
Модули есть в Юи 2.
>>805206
Может удача в том, что ты решишь задачу про кредит с первого раза? Это редкость.
>>805019
Для основ - наш учебник из ОП поста или любой другой аналогичный, если найдешь.
Также заведи привычку гуглить все функции, которые встречаешь, и читать официальный мануал по ним. Официальный мануал на php.nat это справочник, он не совсем для изучения языка, а для изучения как та или иная фича работает во всех подробностях.
Насчет "много информации" - в хороших учебниках в начале всегда пишут, что надо знать чтобы его читать. Соответственно ты можешь отсеять те книги или статьи для которых у тебя пока маловато знаний.
>>804955
Наш учебник как раз для тех, кто вообще ничего не знает и ни одной программы в жизни не написал даже на уроке информатики.
>>804943
Может он знает, просто что-то напутал. Но конечно перед студентами Вектор надо бы решить.
Скорее всего Project... отсчитывается от текущего неймспейса и надо писать \Project\.... Либо автозагрузчик еще не подключен. Либо опечатка в имени класса.
Ты можешь попробовать отдебажить ситуацию, натыкав echo или var_dump в autoload.php
>>805318
Кнопку можно привязать к форме в новых бразузерах специальным HTML5 атрибутом. Можно обрабатывать нажатие скриптом. Но лучше конечно поправить кривую верстку и поместить кнопку в форме.
>>805214
Мануал http://php.net/manual/ru/language.types.string.php#language.types.string.parsing
>>805219
Для админки обычно есть такие варианты:
- сделать 2 отдельных приложения (модуля или как там это называется) - frontend (сам сайт) и admin. профит в том, что мы можем например централизованно разрешать доступ к админке только по паролю.
https://yiiframework.com.ua/ru/doc/guide/2/structure-modules/
http://www.yiiframework.com/doc-2.0/guide-structure-modules.html
- сделать базовый админский контроллер и наследовать контроллеры админки от него. В базовом контроллере сделать проверку логина и всякие полезные функции. Недостаток в том, что если забыть отнаследоваться от нужного контроллера можно например случайно отключить систему авторизации.
Я бы делал через модули.
Вообще, я скажу что модули пригодятся при разработке огромных проектов. Потому что если у тебя 20 человек несколько лет пишет код и они валят все контроллеры в одну папку то скоро эта папка станет нечитамой. Разделение сайта на модули позволяет организовать код лучше.
>>805231
Модули есть в Юи 2.
>>805206
Может удача в том, что ты решишь задачу про кредит с первого раза? Это редкость.
>>805019
Для основ - наш учебник из ОП поста или любой другой аналогичный, если найдешь.
Также заведи привычку гуглить все функции, которые встречаешь, и читать официальный мануал по ним. Официальный мануал на php.nat это справочник, он не совсем для изучения языка, а для изучения как та или иная фича работает во всех подробностях.
Насчет "много информации" - в хороших учебниках в начале всегда пишут, что надо знать чтобы его читать. Соответственно ты можешь отсеять те книги или статьи для которых у тебя пока маловато знаний.
>>804955
Наш учебник как раз для тех, кто вообще ничего не знает и ни одной программы в жизни не написал даже на уроке информатики.
>>804943
Может он знает, просто что-то напутал. Но конечно перед студентами Вектор надо бы решить.
Чтобы:
- когда ты создаешь класс, было понятно в каком файле он должен лежать и не было споров и сомнений
- когда ты ищешь класс, ты бы знал в каком он файле
Если не делать стандартов вроде PSr-4 то каждый будет делать по-своему и будет бардак. А у меня есть как раз урок по нему: https://github.com/codedokode/pasta/blob/master/php/autoload.md
Правило один класс = один файл также нужно чтобы не было гигантских файлов с которыми неудобно работать.
Вообще, в проекте нужны стандарты по любому поводу. Как называть файлы, как оформлять код, для чего какая папка, как работать с БД, и тд. Иначе в команде каждый начнет делать по своему и ты замучаешься исправлять все.
>>804941
Не просто. Автозагрузчик позволяет вообще не писать реквайры/инклуды. Это избавляет от рутинных действий и убирает из кода пути к файлам.
> а не искать модель юзеров в MegaProjectModel.php среди 100500 других классов
Правило: каждый класс в отдельном файле. Ничего искать не придется, если соблюдать PSR-4 то имя файла определяется именем класса. И в MegaProjectModel.php может быть только класс MegaProjectModel и ничего больше.
>>804905
А ты читал комментарии к задаче про студентов? Там много чего написано и про MVC в том числе.
>>804863
А комментарии к задаче читал?
>>804858
MVC это разделение кода на 3 части. https://github.com/codedokode/pasta/blob/master/student-list.md#mvc
>>804847
Да, контороллер может быть в простейшем случае просто скриптом который вызывает другие классы и подключает файлы.
>>804840
С учебника в ОП посте либо с HTML/CSS. По которым у нас тоже есть задания в ОП посте.
Чтобы:
- когда ты создаешь класс, было понятно в каком файле он должен лежать и не было споров и сомнений
- когда ты ищешь класс, ты бы знал в каком он файле
Если не делать стандартов вроде PSr-4 то каждый будет делать по-своему и будет бардак. А у меня есть как раз урок по нему: https://github.com/codedokode/pasta/blob/master/php/autoload.md
Правило один класс = один файл также нужно чтобы не было гигантских файлов с которыми неудобно работать.
Вообще, в проекте нужны стандарты по любому поводу. Как называть файлы, как оформлять код, для чего какая папка, как работать с БД, и тд. Иначе в команде каждый начнет делать по своему и ты замучаешься исправлять все.
>>804941
Не просто. Автозагрузчик позволяет вообще не писать реквайры/инклуды. Это избавляет от рутинных действий и убирает из кода пути к файлам.
> а не искать модель юзеров в MegaProjectModel.php среди 100500 других классов
Правило: каждый класс в отдельном файле. Ничего искать не придется, если соблюдать PSR-4 то имя файла определяется именем класса. И в MegaProjectModel.php может быть только класс MegaProjectModel и ничего больше.
>>804905
А ты читал комментарии к задаче про студентов? Там много чего написано и про MVC в том числе.
>>804863
А комментарии к задаче читал?
>>804858
MVC это разделение кода на 3 части. https://github.com/codedokode/pasta/blob/master/student-list.md#mvc
>>804847
Да, контороллер может быть в простейшем случае просто скриптом который вызывает другие классы и подключает файлы.
>>804840
С учебника в ОП посте либо с HTML/CSS. По которым у нас тоже есть задания в ОП посте.
У меня обычно глаза устают от темной схемы так как в браузере все светлое и переключаться неудобно. Ну то есть не то, чтобы так уж устают, но светлая тема воспринимается лучше. Некоторые даже консоль делают черным по белому.
Установить советую php companion для работы с неймспейсами.
У меня такие плагины: php-twig, docblockr (вставляет doc комментарии), emmet (для html кода), jshint gutter или как-то так, который умеет проверять синтаксис и находить сомнительные места в js коде.
http://ideone.com/9aVD5D
Так вот, объясните нуфагу, а почему оно так? Почему что бы я не делал, пхп все сводит к числам? Зачем оно так? Разве не логично, что строки и числа нельзя сравнивать?
> Ты можешь попробовать отдебажить ситуацию, натыкав echo или var_dump в autoload.php
Какие-то чудеса. Одинаковые на вид строки оказываются не одинаковыми и дают разный результат. Пока не пойму как такое возможно
Если в строке первой идет число, то php при арифметических операция остальное обрезает и считает за число. Если первой идет буква, то дальше за строку считает, независимо от того, сколько там цифр дальше. Если надо как строки добавлять, используй . оператор, + для чисел же.
Уже семь часов это насилую. Уже не понимаю как убрать "озвучку" нулей в единичных числах (пятьсот сорок ноль тысяч)
Что за функцию в целов, стоит учить дальше? Я безнадежен
Что именно ты не понимаешь? У тебя есть массив
[a, b, c, d, e, f, g]
Ты можешь сделать так что бы у тебя случайный набор из этих букв сгенерировался?
Берешь случайный элемент массива, потом еще один, потом еще один и так столько раз сколько тебе нужно
А, ладно. Набыдлокодил всё таки. Спасибо за внимание!
Да, я понял. Спасибо.
Вот так получилось.
http://ideone.com/xjzGHH
Чёт мне уже страшно с этого языка. Особенно с преобразованием первого символа в заглавный.
Наверное я чего-то не понимаю.
И что тебя смущает? Вроде бы всё правильно сделал. Тут же главное в голове придумать алгоритм из зарание доступных тебе кирпичиков, а потом его в языке воплотить, и всё собственно.
Чем больше занимаешься, тем лучше видишь связь между придумыванием и воплощением в языке.
>Особенно с преобразованием первого символа в заглавный.
Я бы делал через известную мне функцию mb_strtoupper(), причем достаточно калично, отрезал бы первый символ имени, перегонял его в большой, и потом приклеивал назад
Ты сделал еще лучше, без дополнительных лишних отрезов и склеиваний, пока смотрел на твою http://php.net/manual/ru/function.mb-convert-case.php функцию в мануале еще одну увидел интересную
http://php.net/manual/ru/function.ucfirst.php
Если она поддерживает кирилицу, то можно через неё делать и не париться.
Я попробую. Спасибо.
Ты там русскую букву вместо латинской не вставил? Можно проверить программой-опечаточником если она у тебя еще есть.
>>805558
В php7 вроде исправлили проблему с "10 котят" - это будет выдавать варнинг. Само преобразование нужно так как часто данные, пришедшие от пользователя (в $_GET), из файла, базы данных, представлены в виде строк и без этого надо было бы делать явные преобразования.
>>805643
До php7, даже если там нет чисел, php приведет строку к числу 0: 100 + "test" => 100
>>805707
Тебе надо разбить длинную стену кода на отдельные функции. Что касается проблемы с нулем, то нало разбивать число на миллионы, тысячи, единицы, и если в какой-то группе ноль (ноль тысяч) то пропускать эту группу.
>>805733
> $name = mb_convert_case($name, MB_CASE_TITLE, "UTF-8");
Эта штука у тебя стоит внутри цикла и поому будет выполнена 4 раза. По логике, преобразование надо делать только 1 раз, значит команду надо ставить после цикла.
Ты должен полностью понимать что ты делаешь, а не ставить строчки наугад пока не заработает.
>>805737
ucfirst не поддерживает utf8.
Ты там русскую букву вместо латинской не вставил? Можно проверить программой-опечаточником если она у тебя еще есть.
>>805558
В php7 вроде исправлили проблему с "10 котят" - это будет выдавать варнинг. Само преобразование нужно так как часто данные, пришедшие от пользователя (в $_GET), из файла, базы данных, представлены в виде строк и без этого надо было бы делать явные преобразования.
>>805643
До php7, даже если там нет чисел, php приведет строку к числу 0: 100 + "test" => 100
>>805707
Тебе надо разбить длинную стену кода на отдельные функции. Что касается проблемы с нулем, то нало разбивать число на миллионы, тысячи, единицы, и если в какой-то группе ноль (ноль тысяч) то пропускать эту группу.
>>805733
> $name = mb_convert_case($name, MB_CASE_TITLE, "UTF-8");
Эта штука у тебя стоит внутри цикла и поому будет выполнена 4 раза. По логике, преобразование надо делать только 1 раз, значит команду надо ставить после цикла.
Ты должен полностью понимать что ты делаешь, а не ставить строчки наугад пока не заработает.
>>805737
ucfirst не поддерживает utf8.
У опа написано, что абстрактные нужны мол только как основа от которой потом будем наследоваться и всё. Ну тип создаем абстрактный класс машина а от неё наследуем уже бмв и мерседес. Вот тип объект бмв и мерседес мы можем создать, а вот объект машина нет. И с пониманием этой части у меня проблем нет.
Но неужели нельзя просто использовать абстрактный класс для целей просто инициализации чего-то.
Например нужен нам класс управляющий, который будет наводить движуху в нашем приложении. Почему не сделать его абстрактным? Он будет просто то-то проверять и вызывать. В нем и не нужно ничего кроме методов. А описывать такой класс как обычный что бы в коде потом была нахер не нужная, но при этом как бы необходимая строчка:
$engine = new Engine;
просто что бы иметь возможность запустить движуху:
$engine->run();
Вместо простой и понятной
Engine::run();
>Почему не сделать его абстрактным?
Ну тип короч абстрактный как бы подразумевает ёпта, что тип от него короч как бы обязательно тип наследников создавать, короче без них тип абстрактный класс нахер не нужен. Более того, абстрактный класс тип существует только ради наследников.
>Вместо простой и понятной Engine::run();
Это почти то же, что и обычная функция. Ты тянешь процедурное мышление в ООП. Попробуй почитать пасту ОПа про DI, есть в репозитории pasta.
Да я и пытаюсь въехать. Я понимаю у нас тут ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ как бы, но всё же, зачем доводить до абсолюта? Если мне и не нужен в каком-то месте сам объект, то нахуя его плодить?
Мы
Классов - уже лет 7+ как (Было вроде ещё в PHP5). Проверка скалярных типов (int, string, bool и т.д) есть в PHP7
Чего ты не гуглишь?
Я просто где-то что-то слышал, и было много разговоров и прочего, а чет в итоге http://php.net/manual/ru/language.oop5.typehinting.php
и нихуя.
>есть в PHP7
Так есть или будет? php7 уже релизнулась или нет? Почему в доках написано PHP 5.6.24 is released
А то у меня шиндоус.
>Почему в доках написано PHP 5.6.24 is released
Потому, что тебе лень проскроллить страницу вниз.
Параллельно несколько веток у PHP выпускается.
Не ну класс только для наследования это раз, объектов этого типа я создавать не буду, только наследников потом.
Конструктор для каждого дочернего класса будет таким же, так что тоже не вижу смысл не писать его тут.
https://ideone.com/NCoM6P вот, зацени мой велосипед. Если таки все хорошо (что маловероятно, так как наверняка можно было обойтись без вложенного фоича через рекурсивные итераторы, но я не нашел на stackoverflow как заставить прочитать вложенные папки), то куда его положить этот класс? В хелперы?
> как заставить прочитать вложенные папки
Не так сказал. Короче я нагуглил много советов, если ссылка на папку одна, а у меня массив ссылок. В документации вообще без примеров.
Хех, оно еще и не работает, чтож так сложно-то. Там как-то с объектом композера надо взаимодействовать наверное, да?
А если ты просто в консоли напишешь ./postInstall.php, то у тебя ведь ничего не заработает, верно? Нужно было ставить Linux.
Вообще, команда ./script обозначает "запустить скрипт из текущей директории с помощью интерпретатора, путь к которому указан в первой строке скрипта после #!". Это для Bash, насчёт других шеллов не знаю. Например, у меня интерпретатор PHP имеет абсолютный путь /usr/bin/php, поэтому я бы указал в качестве первой строки #!/usr/bin/php, Bash бы всё понял и запустил скрипт.
Короче, попробуй запустить скрипт из консоли, если у тебя путь к интерпретатору PHP есть в переменной окружения PATH, то команда "php path/to/script.php" должна заработать. Если заработает - то эту команду и пихай в конфиг композера.
>Ошибка постинга: В сообщении присутствует слово из спам листа.
Скажи спасибо абу, и мучайся читая с картинки ту хуйню кароче
Ну я в принципе так и понял что такое инкапсуляция. Короче, насколько я соображаю, на производительность кода это не влияет, только на безопасность, не? ООП учу второй день, если что. Алсо, все фишки ООП в других языках выглядят так же, как и в пхп?
Ну и еще вопрос - а зачем нужны интерфейсы? Это типа на начальном этапе разработки их делают как наброски, а потом имплементируют?
Прости, больше я ебе помочь не могу, я сам учу ООП 3 месяца но не продвинулся дальше тебя. Про другие языки я не скажу, а про интерфейсы нихуя не понял сам :(
Ну нужны тебе интерфейсы, раз второй день учишь. Я понял зачем они нужны только тогда, когда прочитал о инверсии зависимостей.
И ещё:
1) Зачем в скрипте ООП? Простые одноразовые вещи нужно реализовывать просто, а не тянуть избыточные абстракции.
2) В твоём случае можно создать bat-скрипт. Считай, что это как Bash-скрипт, только очень ограниченный и под винду. Запускается тоже в консоли.
Тебе нужно просто нагуглить команды для копирования файла и папки в bat-скрипте.
Например, так копируется папка: http://stackoverflow.com/questions/4601161/copying-all-contents-of-folder-to-another-folder-using-batch-file
бамп. Ну ответьте же, сидите тут рассуждаете об инверсии зависимостей, шарите явно больше меня и всё такое. Это важно для меня.
По идее ты должен в абстрактном классе задать какие-то функции, которые обязательно надо реализовать в наследниках. Вроде как это и есть суть абстрактных классов.
Но если я не хочу переопределять в наследниках ничего кроме полей. Да и разве стуь не в том, что бы ОТ НЕГО НАСЛЕДОВАТЬСЯ
Если у всех наследников Worker'а есть какой-то метод с одним и тем же названием, но реализовывать его нужно по-разному для разных наследников, то делай этот метод абстрактным и переопределяй в наследниках. PHP не обязывает тебя добавлять в абстрактные классы абстрактные методы, хотя по моему диванному мнению так было бы наглядней. Есть абстрактные методы - делаем класс абстрактным, нет - делаем просто базовым, от которого наследуемся.
>>806216
Что значит "переопределить поле"?
Мне кажется, таким как мы с тобой пока лучше не ебать себе мозги всякими абстракциями да интерфейсами, а лучше просто пытаться в ООП кодинг на практике. Авось потом само дойдет.
Опять же я пишу в классе
worker такие поля как salary, coffe
хотя мог бы и не писать по идее, ведь они как бы все переопределяются в наследниках, но у меня в классе worker есть методы, которые как бы обращаются к этим полям, и если эти поля не писать в самом классе, то правильно ли тогда в классе иметь поля, которых нет в классе, но которые есть в наследниках???
А сегодня я прочел о том, что Uber переходит с postgres на mysql. Так-то!
https://eng.uber.com/mysql-migration/
Что касается PostgresQL, я считаю что это хороший проект, у него много интересных фич и конечно стоит его изучать. И для многих проектов это будет хороший выбор. Но когда дело доходит до сложных высоконагруженных проектов, приходится делать выбор, тщательно взвешивая все особенности продукта, а не доверяясь мнениям популярных блогеров.
Мне кажется, на этой доске точно нет людей которые могли бы раскидать это все по полочкам.
Почему не применяется CSS к кнопке #1but c текстом About? Где ошибка?
Ух тыж какой умник, сразу и бутсрап, и жиквери. А если серьезно - ты уверен, что на этом респурсе именно так и делают линк на таблицу стилей?
Разве можно идентификаторы в css начинать с цифры?
https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
> In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item). For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".
> they cannot start with a digit
Типа надо что-то одно - или бутстрап или жыкерри? Я не умник, я только вкатываюсь.
Да.
Ну как тебе сказать. Если сходу лезть во фреймворки, то ты не язык сам учишь, а модули к нему. Я бы посоветовал тебе дропнуть эти курсы.
Бутстрап и jquery - полезные и нужные библиотеки. Но перед ними надо научиться писать CSS и JS код руками без них. У тебя, на мой взгляд, код пока не очень.
У нас кстати в ОП-посте есть задачи и по CSS и по JS по которым ты можешь оценить свой уровень и которые ты бы мог решать параллельно с другими курсами. мы проверим решения и дадим подсказки если что-то непонятно.
>jquery
Чет в последнее время я все чаще и чаще слышу мнение от js-кодеров, что жикверы говно и быдлокод. Есть тут кто шарит тему?
Вот у тех, кто говорит, и спроси. Если высокоуровневый инструмент попадает в руки неопытного, то некачественный код на выходе - не вина высокоуровнего инструмента. Что делать? Изучать низкоуровневые вещи, чтобы не было пикрилейтед.
У ОПа есть. jQuery полезная библиотека, которая содержит много нужных в повседневном использовании функций. Но у нее есть и недостатки:
- монолитность, нельзя взять то что нужно,надо тянуть всю библиотеку
- любят свой подход вместо стандартов, например у них своя нестандартная реализация промисов
- скрытие ошибок: если передавать в функции аргументы неправильного типа, они часто не выдают никакого сообщения об ошибке
- не умеет искать поля формы по имени
Ну и многие из тех верстальщиков, кто пишет код на джейквери не знает толком ни яваскрипта ни самой джейквери, возможно отсюда и складывается такое впечатление.
> Ты там русскую букву вместо латинской не вставил?
Оно самое. Печально, что такие глупости отнимают столько времени.
ОП, ответь на вот эти вопросы >>798277 а то я уже не знаю, что мне еще править
Поищи тогда плагины для spellchecking'а, чтобы такие глупости не отнимали много времени. Не ОП.
Калькулятор.
Стоит ли потом после прочтения ооп возвращаться и переписывать калькулятор(Как в учебнике с ооп и скобками) для того чтоб получше въехать(Или это будет невыполнимо для новичка?)
в документации нашел, что нужно задавать в пространство имен контроллеров, нашел переменную в документации , но где мне искать ее в своих файлах, или мне добавлять динамически?
> Мне на самом деле эта строка нужна была, чтобы указать в какой папке вью. Если заменю "view": "status/register_ok" на "folder": "status" - будет норм?
Это по идее неправильно. Роутер отвечает за разбор УРЛ, а вид логично задавать в контроллере. Тут конечно можно при желании извернуться и разрешить в роуте указывать кроме имени действия дополнительные опции и уже в них - имя шаблона. Но мне конечно не очень нравится сама идея указывать имена шаблонов в роутере. Это конечно дложно быть в контроллере.
И зачем тебе эти шаблоны? Почему бы при успешной регистрации не редиректить например на список студентов и выводить там уведомление над списком?
> - В чём заключается непонятность структуры? Ты предлагаешь делать методы типа getDBLogin(), getDBPass() и т.д. или как?
Я имел в виду, раз у тебя есть класс для чтения конфига, можно было бы возвращать объект этого класса. И например получать значения через $config->get('db.login')
Можно и массив конечно.
> проверь контроллер
В общем, стало лучше.
> $isAuthorized=$this->c['isAuthorized'];
Вот это мне кажется странным, по идее контейнер для хранения каких-то не привязанных к текущему запросу вещей. У тебя есть сервис авторизации - это надо у него выяснять, залогинен пользователь или нет.
Ну например , что если мы хотим обработать несколько запросов, ты обновишь значения isAuthorised перед каждым? А если это значение уже успел получить и сохранить какой-то сервис? В контейнере должны быть значения, не привязанные к текущему запросы. Потому что их может быть несколько, или вооьще не быть (например в командной строке).
В Симфони кстати тоже раньше хранили объект request в контейнере, потом поняли что это плохая идея, извернулись и добавили scope. Мне конечно не нравится, я за то чтобы его там вообще не было.
Текущий пользователь, город IP адрес и прочее - это не для контейнера сервисов, если рассуждать об идеальном коде.
> $find=isset($_GET['find']) ? $_GET['find'] : NULL;
Надежнее писать strval($GET[...]) на случай если передадут массив например
Еще мне у тебя не нравится неймспейс Project\Classes - тут целых 2 слова которые не несут никакого смысла. По идее должно быть что-то вроде StudentList\???. ЧТо написать вместо Classes - трудно сказать, может просто класть тогда классы на 1 папку выше чтобы было app/Validator.php ?
> foreach ($_POST as $post) {$post=trim(strval($post));}
> Он делает trim и strval, разве нет?
$post это не элемент массива, а копия его значения. Ты меняешь переменную, а не исходный массив.
И менять $_POST тоже плохо. Это ведь пришедшие данные - вдруг они где-то еще нужны. Относись к нему как к массиву только для чтения.
> Мне на самом деле эта строка нужна была, чтобы указать в какой папке вью. Если заменю "view": "status/register_ok" на "folder": "status" - будет норм?
Это по идее неправильно. Роутер отвечает за разбор УРЛ, а вид логично задавать в контроллере. Тут конечно можно при желании извернуться и разрешить в роуте указывать кроме имени действия дополнительные опции и уже в них - имя шаблона. Но мне конечно не очень нравится сама идея указывать имена шаблонов в роутере. Это конечно дложно быть в контроллере.
И зачем тебе эти шаблоны? Почему бы при успешной регистрации не редиректить например на список студентов и выводить там уведомление над списком?
> - В чём заключается непонятность структуры? Ты предлагаешь делать методы типа getDBLogin(), getDBPass() и т.д. или как?
Я имел в виду, раз у тебя есть класс для чтения конфига, можно было бы возвращать объект этого класса. И например получать значения через $config->get('db.login')
Можно и массив конечно.
> проверь контроллер
В общем, стало лучше.
> $isAuthorized=$this->c['isAuthorized'];
Вот это мне кажется странным, по идее контейнер для хранения каких-то не привязанных к текущему запросу вещей. У тебя есть сервис авторизации - это надо у него выяснять, залогинен пользователь или нет.
Ну например , что если мы хотим обработать несколько запросов, ты обновишь значения isAuthorised перед каждым? А если это значение уже успел получить и сохранить какой-то сервис? В контейнере должны быть значения, не привязанные к текущему запросы. Потому что их может быть несколько, или вооьще не быть (например в командной строке).
В Симфони кстати тоже раньше хранили объект request в контейнере, потом поняли что это плохая идея, извернулись и добавили scope. Мне конечно не нравится, я за то чтобы его там вообще не было.
Текущий пользователь, город IP адрес и прочее - это не для контейнера сервисов, если рассуждать об идеальном коде.
> $find=isset($_GET['find']) ? $_GET['find'] : NULL;
Надежнее писать strval($GET[...]) на случай если передадут массив например
Еще мне у тебя не нравится неймспейс Project\Classes - тут целых 2 слова которые не несут никакого смысла. По идее должно быть что-то вроде StudentList\???. ЧТо написать вместо Classes - трудно сказать, может просто класть тогда классы на 1 папку выше чтобы было app/Validator.php ?
> foreach ($_POST as $post) {$post=trim(strval($post));}
> Он делает trim и strval, разве нет?
$post это не элемент массива, а копия его значения. Ты меняешь переменную, а не исходный массив.
И менять $_POST тоже плохо. Это ведь пришедшие данные - вдруг они где-то еще нужны. Относись к нему как к массиву только для чтения.
В конфиге может? ты точно внимательно читал руководство, а также изучил неймспейсы?
>>806518
> floatval($char);
правильнее все же intval так как одна цифра дать дробное число никак не может. А так, в общем верно.
Стоит ли делать - ну а ты попробуй изучи ООП сначала. Я думаю, после изучения у тебя хватит энтузиазма и на калькулятор. Тем более что там в основном надо использовать готовые алгоритмы.
>>806485
А лучше плагины для поиска символов разных алфавитов в одном слове (или шрифт где они разные). Спеллчекинг будет ругаться на всякие сокращения и названия функций.
>>806415
Первый раз слышу.
Нельзя обращаться к полям, которых нет в текущем классе, так что ты делаешь правильно. Но подумай вот о чем. Вот допустим кто-то хочет унаследовать твой класс и создать новую профессию. Как он догадается что надо переопределить поля?
В некоторых случаях лучше использовать абстрактне методы вместо полей. Их нельзя забыть переопределить. Поля можно использовать когда в них по умолчанию разумные значения и переопределять их не обязательно.
>>806238
В getWorkerSalary нет ретурна.
>>806189
А где у него ООП?
Бат скрипты настолько примитивны что их лучше не трогать вообще (как насчет обработки ошибок? ). И пхп кроссплатформенный в отличие от них.
Инкапсуляция нужна для лучшей читаемости кода и для упрощения внесения изменений в код. Пасты:
------
Инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.
Суть инкапсуляции в том, что класс скрывает (инкапслирует) в себе логику работы с данными и сами данные, а наружу выставляет методы. Пользователю этих методов не важно, как класс устроен внутри, как он хранит данные, ему достаточно вызвать нужный метод чтобы получить результат.
Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему). Также, это упрощает изменение кода: если какое-то свойство имеет уровень private то доступ к нему возможен только из того же класса и тебе не надо бегать по всему коду и смотреть что там с этим свойством делается, тебе достаточно просмотреть один файл с этим классом.
Инкапсуляция это хорошо. Так как весь код, который занимается одной задачей, оказывается заключен внутри одного класса. Противоположный случай это когда код (или знание о его внутреннем устройстве) вылезает из класса и размазывается по всей программе.
Если проводить аналогии, то можно представить кофе-машину. Ты нажимаешь кнопку (=вызываешь публичный метод) и получаешь кофе (=результат вызова этого метода), при этом ты не видишь что происходит внутри нее и тебе не надо в этом разбираться.
------
Вот представь себе кофе-машину без инкапсуляции, то есть такую, у которой всякие внутренние части и кнопки выведены наружу. Чтобы ей пользоваться, тебе надо сначала разобраться как она работает, где что засыпается, где подогревается и ты должен сам догадаться сколько минут его греть и перемешивать. Фактически знание о процессе приготовления кофе не заключено в машине, а размазано по машине и голове пользователя. если мы хотим поменять рецепт приготовления, мы меняем не только конструкцию машины но и переобучаем всех пользователей этой машины. А что если кому-то мы забыли рассказать о том, что конструкция поменялась?
Так же и код. Каждый класс должен выполнять какую-то свою задачу. Если ты не делаешь инкапсуляцию, то код относящийся к задаче, не заперт внутри класса, а размазан по классу и другим частям приложения. Это усложняет его понимание и изменение.
Инкапсуляция нужна для лучшей читаемости кода и для упрощения внесения изменений в код. Пасты:
------
Инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.
Суть инкапсуляции в том, что класс скрывает (инкапслирует) в себе логику работы с данными и сами данные, а наружу выставляет методы. Пользователю этих методов не важно, как класс устроен внутри, как он хранит данные, ему достаточно вызвать нужный метод чтобы получить результат.
Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему). Также, это упрощает изменение кода: если какое-то свойство имеет уровень private то доступ к нему возможен только из того же класса и тебе не надо бегать по всему коду и смотреть что там с этим свойством делается, тебе достаточно просмотреть один файл с этим классом.
Инкапсуляция это хорошо. Так как весь код, который занимается одной задачей, оказывается заключен внутри одного класса. Противоположный случай это когда код (или знание о его внутреннем устройстве) вылезает из класса и размазывается по всей программе.
Если проводить аналогии, то можно представить кофе-машину. Ты нажимаешь кнопку (=вызываешь публичный метод) и получаешь кофе (=результат вызова этого метода), при этом ты не видишь что происходит внутри нее и тебе не надо в этом разбираться.
------
Вот представь себе кофе-машину без инкапсуляции, то есть такую, у которой всякие внутренние части и кнопки выведены наружу. Чтобы ей пользоваться, тебе надо сначала разобраться как она работает, где что засыпается, где подогревается и ты должен сам догадаться сколько минут его греть и перемешивать. Фактически знание о процессе приготовления кофе не заключено в машине, а размазано по машине и голове пользователя. если мы хотим поменять рецепт приготовления, мы меняем не только конструкцию машины но и переобучаем всех пользователей этой машины. А что если кому-то мы забыли рассказать о том, что конструкция поменялась?
Так же и код. Каждый класс должен выполнять какую-то свою задачу. Если ты не делаешь инкапсуляцию, то код относящийся к задаче, не заперт внутри класса, а размазан по классу и другим частям приложения. Это усложняет его понимание и изменение.
Обычно интерфейсы исплоьзуются библиотеках. Благодаря им автор задает ограничения, которые должны соблюдать пользователи, желающие использовать свой класс вместе с библиотекой.
Ну и конечно использовать их можно и при одиночной работе - задавать определенные требования к классам которые куда-то передаются.
-----------
Интерфейс это набор требований к классу. «требование» здесь значит требование чтобы в классе был определенный метод.
Если класс реализует интерфейс, в нем обязаны быть эти методы.Обычно интерфйес представляет собой какое-то умение: классы, реализующие этот интерфейс, умеют что-то делать.
Допустим мы делаем сайт где можно ставить лайки постам и комментам. Допустим у нас есть классы User, Post и Comment.
Вот у нас есть пост и коммент, мы можем увеличить число лайков, допустим методом increaseLikeCount и узнавать сколько у них лайков методом getLikeCount, то есть у них есть что-то общее, но как описать это в коде? Как сказать что эти 2 класса в отличие от других умеют работать с лайками?
Второй пример, мы хотим сделать функцию, которая допустим ставит лайк от определенного пользователя определенному посту или комментарию:
function addLike(User $user, $object) ...
Мы сказали что $user должен быть объектом класса User, а как сказать что $object должен быть классом, умеющим работать с лайками?
Обе проблемы решают интерфейсы. Объявим интерфейс Likeable, который представляет собой умение получать лайки. Опишем какие методы обязаны реализовать такие классы:
interface Likeable
{
public function increaseLikeCount( );
public function getLikeCount( );
}
Теперь укажем в коде что посты и комменты можно лайкать:
class Post implements Likeable { ... }
class Comment implements Likeable { ... }
на этом этапе php проверит, не забыли ли мы реализовать в классах упомянутые методы. Если забыли — выдаст ошибку. Как удобно!
Ну и теперь мы можем использовать интерфейс чтобы указать какие аргументы принимает функция addLike:
function addLike(User $user, Likeable $object) { ... }
заметь что благодаря интферйесам наш код стал расширяем. Допустим завтра мы добавим класс Photo который тоже можно лайкать. Если он будет реализовывать интерфейс Likeable то функция вроде addLike сможет работать и с ним без переписывания кода.
В общем интерфейс представляет какую-то способность класса и требует от него реализовать определенные методы.
Обычно интерфейсы исплоьзуются библиотеках. Благодаря им автор задает ограничения, которые должны соблюдать пользователи, желающие использовать свой класс вместе с библиотекой.
Ну и конечно использовать их можно и при одиночной работе - задавать определенные требования к классам которые куда-то передаются.
-----------
Интерфейс это набор требований к классу. «требование» здесь значит требование чтобы в классе был определенный метод.
Если класс реализует интерфейс, в нем обязаны быть эти методы.Обычно интерфйес представляет собой какое-то умение: классы, реализующие этот интерфейс, умеют что-то делать.
Допустим мы делаем сайт где можно ставить лайки постам и комментам. Допустим у нас есть классы User, Post и Comment.
Вот у нас есть пост и коммент, мы можем увеличить число лайков, допустим методом increaseLikeCount и узнавать сколько у них лайков методом getLikeCount, то есть у них есть что-то общее, но как описать это в коде? Как сказать что эти 2 класса в отличие от других умеют работать с лайками?
Второй пример, мы хотим сделать функцию, которая допустим ставит лайк от определенного пользователя определенному посту или комментарию:
function addLike(User $user, $object) ...
Мы сказали что $user должен быть объектом класса User, а как сказать что $object должен быть классом, умеющим работать с лайками?
Обе проблемы решают интерфейсы. Объявим интерфейс Likeable, который представляет собой умение получать лайки. Опишем какие методы обязаны реализовать такие классы:
interface Likeable
{
public function increaseLikeCount( );
public function getLikeCount( );
}
Теперь укажем в коде что посты и комменты можно лайкать:
class Post implements Likeable { ... }
class Comment implements Likeable { ... }
на этом этапе php проверит, не забыли ли мы реализовать в классах упомянутые методы. Если забыли — выдаст ошибку. Как удобно!
Ну и теперь мы можем использовать интерфейс чтобы указать какие аргументы принимает функция addLike:
function addLike(User $user, Likeable $object) { ... }
заметь что благодаря интферйесам наш код стал расширяем. Допустим завтра мы добавим класс Photo который тоже можно лайкать. Если он будет реализовывать интерфейс Likeable то функция вроде addLike сможет работать и с ним без переписывания кода.
В общем интерфейс представляет какую-то способность класса и требует от него реализовать определенные методы.
Плюс благодаря инкапсуляции ты можешь гарантировать корректность работы классы. Ну допустим у тебя нет инкапсуляции и есть публичное свойство обозначающее возраст пользователя . Где гарантия что в него не запишут строку или ноль?
При использовании инкапсуляции поле недоступно и менять возраст можно только через метод который может проверить данные и гарантировать что неправильное значение не будет принято и сохранено.
>>806127
Пхп скрипт это не исполняемый файл. Если ты под виндой, надо писать php file.php
Если ты под Линуксом то можно добавить файлу право +x (execute) и написать в начале что-то вроде
#!/usr/bin/env php
Тогда файл станет исполняемым.
https://ru.wikipedia.org/wiki/Шебанг_(Unix)
Кстати, кроме внешней программы, в композере можно просто указать статический метод класса.
>>806102
> if (strcmp($extension, "js") === 0) {
$extension == "js"
Вообще, перемешивание скриптов не лучшая идея. Что с относительными ссылками на картинки и шрифты в css?
И почему все кроме скриптов и стилей идет в fonts?
Я думаю лучше копировать папку dist из библиотеки целиком как есть.
Для рекурсивного поиска файлов нужен http://php.net/manual/ru/class.recursivedirectoryiterator.php
Хороший повод изучить итераторы.
> то куда его положить этот класс? В хелперы?
Обычно для вспомогательных скриптов делают папку bin, util, scripts. Но если ты хочешь подключать его из композера через статический метод то он должен быть автозагружаемый.
> mkdir($path, 0700, true);
Обычно веб-сервер имеет права "другой" а в твоем случае файл доступен только владельцу.
Плюс благодаря инкапсуляции ты можешь гарантировать корректность работы классы. Ну допустим у тебя нет инкапсуляции и есть публичное свойство обозначающее возраст пользователя . Где гарантия что в него не запишут строку или ноль?
При использовании инкапсуляции поле недоступно и менять возраст можно только через метод который может проверить данные и гарантировать что неправильное значение не будет принято и сохранено.
>>806127
Пхп скрипт это не исполняемый файл. Если ты под виндой, надо писать php file.php
Если ты под Линуксом то можно добавить файлу право +x (execute) и написать в начале что-то вроде
#!/usr/bin/env php
Тогда файл станет исполняемым.
https://ru.wikipedia.org/wiki/Шебанг_(Unix)
Кстати, кроме внешней программы, в композере можно просто указать статический метод класса.
>>806102
> if (strcmp($extension, "js") === 0) {
$extension == "js"
Вообще, перемешивание скриптов не лучшая идея. Что с относительными ссылками на картинки и шрифты в css?
И почему все кроме скриптов и стилей идет в fonts?
Я думаю лучше копировать папку dist из библиотеки целиком как есть.
Для рекурсивного поиска файлов нужен http://php.net/manual/ru/class.recursivedirectoryiterator.php
Хороший повод изучить итераторы.
> то куда его положить этот класс? В хелперы?
Обычно для вспомогательных скриптов делают папку bin, util, scripts. Но если ты хочешь подключать его из композера через статический метод то он должен быть автозагружаемый.
> mkdir($path, 0700, true);
Обычно веб-сервер имеет права "другой" а в твоем случае файл доступен только владельцу.
Даст готовый роутер для красивых УРЛ, объекты запроса и ответа, обработчик ошибок, полистай мануал, там написано что есть в микрофреймворке.
>>805945
Для приватных полей это нужно так как в классе с наследованием может быть несколько одноименных приватных полей из разных классов.
>>805940
Тайп-хинты частично есть начиная с php5. В php7 все улучшено.
>>805857
Сегодня у тебя в классе нет свойств, а завтра появятся. Да и я не вижу проблемы, одна строка на все приложение по моему ничего не решает. Ведь все остальные классы у тебя в DI контейнере. Более того, твой Engine в тот же DI контейнер не засунуть будет.
А что у тебя будет в этом классе?
> Но неужели нельзя просто использовать абстрактный класс для целей просто инициализации чего-то.
Это нелогично так как будет сбивать люде с толку. Абстрактный класс не предназначен для исплоьзования.
> Например нужен нам класс управляющий, который будет наводить движуху в нашем приложении.
Вот это уже странно. Ты там случайно не собрался полприложения в этом класс не написать? зачем это тебе такой класс?
Вдохновлена Apache Ant, конфиги на XML.
Но по моему она несколько громоздкая.
>Первый раз слышу.
Эт я после прочтения статейки понял: http://www.martinfowler.com/bliki/AnemicDomainModel.html
http://ideone.com/sjOtp9
> Но если ты хочешь подключать его из композера через статический метод то он должен быть автозагружаемый.
А как сделать автозагрузку? Она же в вендоре/автолоад.пхп, я ж не могу ее редактировать. Или ты имеешь ввиду использовать use 'mystaticclass'?
Хотя я так понял вызов статического метода будет прямо в json фалйе, тогда вообще не понятно как автозагружать.
>Напишите программу конвертирующую набор чисел и других символов в телефонный номер, состоящий из блоков размером в 3 числа. Последние 1-2 блока могут быть размером 2 числа.
>
>Пример: "9 - 33 2176--856" >>> "933-217-68-56"
http://ideone.com/AmfogH
Обоссыте
Задачки по регуляркам:
1) https://ideone.com/4gty5H Приведение номера к единому формату.
2) https://ideone.com/tZI7Fp Автозамена слова "Дурак".
3) https://ideone.com/L7JdaE Вывод e-mail'ов.
4) https://ideone.com/qKlxkQ «Grammar Nazi» с автоматическим исправлением.
5) https://ideone.com/LoFKwm «Опечаточники»
Задачки из раздела "Повторим?":
1) https://ideone.com/0HTZhW Задачка "Клавиша shift"
2) https://ideone.com/P8euld "Yoda Speak"
3) https://ideone.com/AO9sGB "Калькулятор"
Этот банкомат забрал мой сон. Все не пойму как с ограниченным кол-вом банкнот работать
https://ideone.com/D338lm
Здравствуй, это ты всем тут подробно отвечаешь на вопросы? Я в тред только вкатился, как и в похапе, но у меня есть пара серьезных хоть и дебиловатых вопросов которые я бы хотел очень обсудить лично, возможно ли с тобой связаться по фейкомыльцу?
https://jsfiddle.net/czeo0c8n/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-2
https://jsfiddle.net/9ygm244j/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-3
https://jsfiddle.net/16m3g5ta/1/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-4
https://jsfiddle.net/211Le60v/5/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-5
https://jsfiddle.net/h3cez9f7/1/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-6
>Ширина меню навигации 200px
А это не слишком много? В шаблоне на картинке она в 3 раза меньше бокса с контентом.
https://jsfiddle.net/L5orb28e/3/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-7
https://jsfiddle.net/5g31m30j/1/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-8
А можно подсказку как сделать чтобы примечание не растягивала контейнер в котором оно содержится? У меня пока получилось только так https://jsfiddle.net/tsuh4gjw/4/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-9
https://jsfiddle.net/kxdx27f1/2/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-10
А что это за атрибут такой в <em data-ref="1">? Это случайно не для jQuery нужно? Можно подсказку как слева на строке у элемента с этим атрибутом сделать те цифры в квадратных скобках?
И можно еще подсказку как сделать <figcaption> внизу картинки? Очевидно, сначала нужно использовать position: absolute, но как сделать чтобы элемент был внизу? Неужели задавать координаты с помощью top, left, ...?
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-11
https://jsfiddle.net/fp8o0exq/4/
У меня не получилось сделать точь в точь как у тебя. Как на глаз определить тень и шрифт? Еще у меня наверно рамка не такая как у тебя...
>я смог решить задание, используя 3 тега на кнопку (label, input, i)
А почему ты выбрал именно наклонный текст? Лучше же span взять - он не меняет стиля текста.
>это задание рассчитано на современные браузеры. Но если ты сделаешь, чтобы код работал и в старых (за счет яваскрипта), это будет плюсом. Или если в старых браузерах будет выводиться просто набор чекбоксов, это тоже лучше, чем ничего
Я пока не знаю javascript, можно я доделаю это позже? Можно пока подсказку как сделать чтобы в старых браузерах просто выводился набор чекбоксов?
>твои CSS стили должны применяться только к элементам внутри переключателя. Недопустимо писать стили вроде label {... } меняющие вид всех label на странице.
Я забыл про этот пункт пока делал задание, можем мы это опустить? В "боевых" задачах я естественно так не буду делать.
>чтобы определить состояние «кнопка вжата», можно использовать селектор label:active (на самом деле input:active)
Я сначала подумал, что ты ошибся насчет :active, что надо было :checked за место этого. Нужно еще и :active делать? Какой у неё должен стиль? Как у :checked?
>дополнительный пункт: если ты посмотришь на обычные, не стилизованные радиокнопки и чекбоксы, то увидишь что по ним можно перемещать фокус с клавиатуры кнопками Tab, Shift + Tab, стрелками и переключать пробелом. Попробуй сделать поддержку клавиатурной навигации и в стилизованных кнопках. Подсказка: для этого надо отказаться от display: none на input, так как перемещать фокус по скрытым элементам нельзя.
А можно еще подсказку как и это сделать?
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
А нужно прям точь в точь как шаблоне делать стили? У меня пока так сделано https://jsfiddle.net/tb7k9dw9/3/ . Если нужно как там то легко исправлю.
>старайся не использовать id в верстке так как с ними не получится вывести на странице несколько блоков вкладок. Разрешается использовать классы или data-атрибуты для связи вкладок и заголовков.
Это касается даже при использовании for у лейблов? Как тогда реализовать переключение вкладок, если вкладывать элементы уже во внутрь лейбла? Не получиться обращаться к соседним или родственным элементам, потому что сначала нужно проверить на :checked у input.
>сверстай блок так, чтобы блок с вкладками можно было вложить в страницу блока вкладок
Нужно чтобы можно было скопировать вкладки в контентную страницу? Может лучше чтобы в контентной странице был свой элемент со вкладками? Так для это следует задать ему собственные атрибуты и стили. Зачем делать по два раза одно и тоже? Я что-то недопонял?
https://jsfiddle.net/czeo0c8n/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-2
https://jsfiddle.net/9ygm244j/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-3
https://jsfiddle.net/16m3g5ta/1/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-4
https://jsfiddle.net/211Le60v/5/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-5
https://jsfiddle.net/h3cez9f7/1/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-6
>Ширина меню навигации 200px
А это не слишком много? В шаблоне на картинке она в 3 раза меньше бокса с контентом.
https://jsfiddle.net/L5orb28e/3/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-7
https://jsfiddle.net/5g31m30j/1/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-8
А можно подсказку как сделать чтобы примечание не растягивала контейнер в котором оно содержится? У меня пока получилось только так https://jsfiddle.net/tsuh4gjw/4/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-9
https://jsfiddle.net/kxdx27f1/2/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-10
А что это за атрибут такой в <em data-ref="1">? Это случайно не для jQuery нужно? Можно подсказку как слева на строке у элемента с этим атрибутом сделать те цифры в квадратных скобках?
И можно еще подсказку как сделать <figcaption> внизу картинки? Очевидно, сначала нужно использовать position: absolute, но как сделать чтобы элемент был внизу? Неужели задавать координаты с помощью top, left, ...?
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-11
https://jsfiddle.net/fp8o0exq/4/
У меня не получилось сделать точь в точь как у тебя. Как на глаз определить тень и шрифт? Еще у меня наверно рамка не такая как у тебя...
>я смог решить задание, используя 3 тега на кнопку (label, input, i)
А почему ты выбрал именно наклонный текст? Лучше же span взять - он не меняет стиля текста.
>это задание рассчитано на современные браузеры. Но если ты сделаешь, чтобы код работал и в старых (за счет яваскрипта), это будет плюсом. Или если в старых браузерах будет выводиться просто набор чекбоксов, это тоже лучше, чем ничего
Я пока не знаю javascript, можно я доделаю это позже? Можно пока подсказку как сделать чтобы в старых браузерах просто выводился набор чекбоксов?
>твои CSS стили должны применяться только к элементам внутри переключателя. Недопустимо писать стили вроде label {... } меняющие вид всех label на странице.
Я забыл про этот пункт пока делал задание, можем мы это опустить? В "боевых" задачах я естественно так не буду делать.
>чтобы определить состояние «кнопка вжата», можно использовать селектор label:active (на самом деле input:active)
Я сначала подумал, что ты ошибся насчет :active, что надо было :checked за место этого. Нужно еще и :active делать? Какой у неё должен стиль? Как у :checked?
>дополнительный пункт: если ты посмотришь на обычные, не стилизованные радиокнопки и чекбоксы, то увидишь что по ним можно перемещать фокус с клавиатуры кнопками Tab, Shift + Tab, стрелками и переключать пробелом. Попробуй сделать поддержку клавиатурной навигации и в стилизованных кнопках. Подсказка: для этого надо отказаться от display: none на input, так как перемещать фокус по скрытым элементам нельзя.
А можно еще подсказку как и это сделать?
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
А нужно прям точь в точь как шаблоне делать стили? У меня пока так сделано https://jsfiddle.net/tb7k9dw9/3/ . Если нужно как там то легко исправлю.
>старайся не использовать id в верстке так как с ними не получится вывести на странице несколько блоков вкладок. Разрешается использовать классы или data-атрибуты для связи вкладок и заголовков.
Это касается даже при использовании for у лейблов? Как тогда реализовать переключение вкладок, если вкладывать элементы уже во внутрь лейбла? Не получиться обращаться к соседним или родственным элементам, потому что сначала нужно проверить на :checked у input.
>сверстай блок так, чтобы блок с вкладками можно было вложить в страницу блока вкладок
Нужно чтобы можно было скопировать вкладки в контентную страницу? Может лучше чтобы в контентной странице был свой элемент со вкладками? Так для это следует задать ему собственные атрибуты и стили. Зачем делать по два раза одно и тоже? Я что-то недопонял?
В основном нужно Российские, желательно но необязательно международные.
Не хочется изобретать свою регулярку которая все все равно будет неправильно срабатывать для каких-то регионов.
Ессть же FILTER_VALIDATE_EMAIL, неужели для телефонов ничего похожего?
Надо было страничку промотать вверх, написал:
>window.scrollTo(0, 0);
Но так как на сайте куча мобильных юзеров, решил не рисковать юзнуть жиквери с его перделками:
>$("body").animate({ scrollTop: 0 }, "slow");
В итоге на виндоус фонах страничка не проматывалась и клиент очень обидно отхуесосил за это. Больше жикверям не доверяю в плане кроссбраузерности.
В некоторых браузерах прокрутка делается через body, в некоторых через html. Я когда-то писал свою функцию для абстрагирования от этого.
И при чем тут jquery? Виноват тут только ты что не знал про эту особенность. jquery просто сделал то, что ты написал.
А так да. window.scrollTo() кроссбраузерный. И если его вызывать например по таймеру то будет и с анимацией.
Да, кажется с html и писал, потом посмотрел в гугле на предлагаемые костыли с решениями и забил
http://stackoverflow.com/questions/16681094/jquery-animating-scroll-top-to-0-not-working-on-windows-phone
Спасибо, анон. Не учел что сумма может быть равна номиналу купюры.
Пофиксил строку if ($note < $amount) на if ($note <= $amount)
http://ideone.com/XBhXTO
Я начал с Symfony2. Мне нравится.
До симфони совсем чуть-чуть ковырял Silex, но это не щитаеца.
Думаю, что можно начинать с симфони.
Только не пытайся проглотить всё разом - у нее много возможностей. А освоить работу с основным функционалом, содержащимся в каждом фреймворке, особого труда составить не должно.
Советую прочесть доку. Если засомневаешься, можешь поиграть с микрофреймворком вроде Slim, Silex.
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
ПЕРЕКАТ https://2ch.hk/pr/res/807538.html (М)
Кокой из тредов теперь легитимный? Посоны, мне нужна жс галерейка типа такой:
http://www.family.su/woman.html
+ в идеале, подписи запилить к каждой
увеличиваемой пикче.
+ очень опционально - форма заказа.
Сам вряд ли справлюсь. Подскажете какую-нибудь готовую и максимум лаконичную и понятную реализацию, просто готовый скрипт "встрой в страницу и забудь" или русскоязычный гайд по самостоятельному запилу подобного на жс? Попова не предлагать, там не то и еще большие азы.
Этот тред. Пока ОП лично не объявит перекат.
>> `cookie_token` varchar(100) NOT NULL,
>Я бы тут добавил уникальный ключ для защиты от глупых ошибок, например когда туда вставляется пустая строка или что-то такое.
Гугл говорит, что в MySQL для запрета вставки пустой строки нужно писать триггер. CHECK молча игнорирует проверку. Не думал, что уникальный ключ можно использовать для этого. Правда, таки один студент с пустым токеном в таблице для этого нужен, но его можно и самому создать.
> Эта штука мне напоминает тест. Это не тест? Тебе определенно стоит почитать урок про тесты
Я читал ещё твои посты по тестированию, адресованные другим анонам, мне очень нравится идея автотестов. Попробую начать с простого - написать тесты к калькулятору. Если разберусь, потом посмотрю в сторону функциональных и опробую их на студентах.
> В реализации роутов у тебя есть подвох. Параметры роута определяются по порядковым номерам, а не по названиям. То есть можно легко написать в роуте плейсхолдеры /:a/:b/:c, а в контроллере function doSomething($c, $b, $a) и не заметить ошибки.
Сделал проверку на соответствие плейсхолдеров с именами аргументов экшна. То есть теперь имена аргументов экшна должны идеально совпадать с плейсхолдерами. Это не так плохо, как если бы ошибки просто умалчивались, но и никакого автоматического связывания аргументов нет.
Вот коммит, отвечающий за изменения в роутинге: https://github.com/applejacky/students/commit/f996fe2fcf3bb978047e4135e427a7bd4abc9a73
>> protected static $table;
> Лучше делать это через абстрактный метод. А то где гарантия что переопределят имя таблицы?
>> public static $table = 'students';
> Непонятно почему тут public.
В общем, все эти проблемы были из-за AbstractMapper, который использовал позднее статическое связывание. Идея такая: у всех мапперов методы findById, findAll, и т.д. одинаковые, меняется только название таблицы в SQL-запросе. Позднее статическое связывание позволяет наследнику вызывать метод родителя, подставляя туда свои статические значения. Но, поле должно быть публичным. Делать абстрактную функцию (чтобы гарантировать возвращение $table), а потом использовать $table в контексте статического связывания кажется бредовейшей идеей, поэтому я просто удалил AbstractMapper.
> https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php
> тут мне не нравится, что отдельные функции для GET и POST
Я всё поправил кроме этого. Вот старая версия с методами getRegisterOrUpdate и postRegisterOrUpdate: https://github.com/applejacky/students/blob/6402ad4269599b63a12c6e67b47bed1f858bacba/app/Controller/FormController.php#L72
Суть в том, что для GET и POST на одну страницу у меня используются разные экшны (как во фреймворках), поэтому после объединения методов даже для меня код стал сложнее читаем ввиду множественных ветвлений. Роутер только ради этого и писал, чтобы он на основе HTTP-метода определял контроллер и экшн, тогда в экшнах не нужно писать if'ы вроде if request = GET { ... } elseif request = POST { ... }
Если делать так, то и роутер можно выбрасывать.
> https://github.com/applejacky/students/blob/master/app/Lib/StudentValidator.php#L36
> Здесь странно что проверки email и пароля делаются только для новых студентов. А что, редактировать email или пароль нельзя?
Нет, нельзя, email используется для регистрационного токена, то есть при смене email нужно токен перегенерировать.
> Нет ли тут ошибки, что пользователь может при обновлении передать емайл или пароль и они принимаются без валидации?
Думаю что нет, на странице редактирования профиля нет возможности изменить email и пароль: https://github.com/applejacky/students/blob/master/app/View/auth/index.phtml#L54
В валидатор приходят не пустые email и пароль, пользователь во время редактирования профиля уже изменяет объект студента со своими данными: https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php#L88
Если пользователь регистрируется, а не изменяет профиль, то он "заполняет" нового студента: https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php#L129
Думаешь, стоит реализовать смену email?
>> `cookie_token` varchar(100) NOT NULL,
>Я бы тут добавил уникальный ключ для защиты от глупых ошибок, например когда туда вставляется пустая строка или что-то такое.
Гугл говорит, что в MySQL для запрета вставки пустой строки нужно писать триггер. CHECK молча игнорирует проверку. Не думал, что уникальный ключ можно использовать для этого. Правда, таки один студент с пустым токеном в таблице для этого нужен, но его можно и самому создать.
> Эта штука мне напоминает тест. Это не тест? Тебе определенно стоит почитать урок про тесты
Я читал ещё твои посты по тестированию, адресованные другим анонам, мне очень нравится идея автотестов. Попробую начать с простого - написать тесты к калькулятору. Если разберусь, потом посмотрю в сторону функциональных и опробую их на студентах.
> В реализации роутов у тебя есть подвох. Параметры роута определяются по порядковым номерам, а не по названиям. То есть можно легко написать в роуте плейсхолдеры /:a/:b/:c, а в контроллере function doSomething($c, $b, $a) и не заметить ошибки.
Сделал проверку на соответствие плейсхолдеров с именами аргументов экшна. То есть теперь имена аргументов экшна должны идеально совпадать с плейсхолдерами. Это не так плохо, как если бы ошибки просто умалчивались, но и никакого автоматического связывания аргументов нет.
Вот коммит, отвечающий за изменения в роутинге: https://github.com/applejacky/students/commit/f996fe2fcf3bb978047e4135e427a7bd4abc9a73
>> protected static $table;
> Лучше делать это через абстрактный метод. А то где гарантия что переопределят имя таблицы?
>> public static $table = 'students';
> Непонятно почему тут public.
В общем, все эти проблемы были из-за AbstractMapper, который использовал позднее статическое связывание. Идея такая: у всех мапперов методы findById, findAll, и т.д. одинаковые, меняется только название таблицы в SQL-запросе. Позднее статическое связывание позволяет наследнику вызывать метод родителя, подставляя туда свои статические значения. Но, поле должно быть публичным. Делать абстрактную функцию (чтобы гарантировать возвращение $table), а потом использовать $table в контексте статического связывания кажется бредовейшей идеей, поэтому я просто удалил AbstractMapper.
> https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php
> тут мне не нравится, что отдельные функции для GET и POST
Я всё поправил кроме этого. Вот старая версия с методами getRegisterOrUpdate и postRegisterOrUpdate: https://github.com/applejacky/students/blob/6402ad4269599b63a12c6e67b47bed1f858bacba/app/Controller/FormController.php#L72
Суть в том, что для GET и POST на одну страницу у меня используются разные экшны (как во фреймворках), поэтому после объединения методов даже для меня код стал сложнее читаем ввиду множественных ветвлений. Роутер только ради этого и писал, чтобы он на основе HTTP-метода определял контроллер и экшн, тогда в экшнах не нужно писать if'ы вроде if request = GET { ... } elseif request = POST { ... }
Если делать так, то и роутер можно выбрасывать.
> https://github.com/applejacky/students/blob/master/app/Lib/StudentValidator.php#L36
> Здесь странно что проверки email и пароля делаются только для новых студентов. А что, редактировать email или пароль нельзя?
Нет, нельзя, email используется для регистрационного токена, то есть при смене email нужно токен перегенерировать.
> Нет ли тут ошибки, что пользователь может при обновлении передать емайл или пароль и они принимаются без валидации?
Думаю что нет, на странице редактирования профиля нет возможности изменить email и пароль: https://github.com/applejacky/students/blob/master/app/View/auth/index.phtml#L54
В валидатор приходят не пустые email и пароль, пользователь во время редактирования профиля уже изменяет объект студента со своими данными: https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php#L88
Если пользователь регистрируется, а не изменяет профиль, то он "заполняет" нового студента: https://github.com/applejacky/students/blob/master/app/Controller/AuthController.php#L129
Думаешь, стоит реализовать смену email?
Добавь тред в избранное, зачем перекат? Вот гайд для нетерпеливых, здесь кто-то спрашивал об этом. Несколько тредов назад.
кто-то создавал тред что не нашел пхп, этот я еле отрыл где-то очень далеко внизу, увидел что уже 600+ постов, запилил перекат, но если нет так нет
Есть же поиск по тредам. Или ты всегда скроллишь до треда, если он у тебя не в избранных?
*л
Тоже мне, программист. Оптимизировать всё нужно и искать самые быстрые и простые пути.
буду стараться
https://habrahabr.ru/post/306564/
Или не читай.
Не знаю, а что?
Нашел такое объяснение:
TIMESTAMPДата и время в формате timestamp. Однако при получении значения поля оно отображается не в формате timestamp, а в виде ГГГГММДДЧЧММСС, что сильно умаляет преимущества его использования в PHP
http://www.spravkaweb.ru/mysql/sql/vartype
Как-то не понимаю как без посылания значения-то, если я сам выставляю метку из пхп кода.
Внимательно прочитай подсказки к задаче. Сам этого не сделал и долго мучался (в конце поста скинул)
Возьми свою 1000 рублей и вставь в функции.
кредитный баланс получается минусовое значение. Общий платеж тоже минус, потому что ежемесячный платеж больше.
Это минусовое значение подставляется в ежемесячный платеж и выплат тоже минус. Банк должен ). Подумай, как сделать так , чтобы избавится от минуса и чтобы он рассчитывал реальное значение долга.
"Исправь и переделай программу, чтобы она работала нормально. Например, эта версия позволяет школьнику переплатить за кредит и уйти в минус, так, что банк ему становится должен — это плохо! Подсказка: перед тем, как платить, надо проверять, сколько осталось долга, и если он меньше 5000, то платить только остаток и завершать цикл через break"
>В некоторых случаях лучше использовать абстрактне методы вместо полей. Их нельзя забыть переопределить. Поля можно использовать когда в них по умолчанию разумные значения и переопределять их не обязательно.
Эм, простите я не понял.
То есть именно абстрактные методы в абстрактном родителе, вместо пустых полей?
Вместо
private $coffe;
public function getCoffe() {
return $this->coffe;
}
в родителе и
private $coffe = 20; в наследнике
нужно писать что-то типа:
abstract private function getBasicCoffe();
public function getCoffe() {
$result = $this->getBasicCoffe() * ....
return $result;
}
в предке, и соответственно
private function getBasicCoffe() {
return 20;
}
в наследниках?
Я понимаю вроде как идею, тип у нас такая вот напоминалка получается. Но для такого нуба как я это только лишнее запутывание :(
>В некоторых случаях лучше использовать абстрактне методы вместо полей. Их нельзя забыть переопределить. Поля можно использовать когда в них по умолчанию разумные значения и переопределять их не обязательно.
Эм, простите я не понял.
То есть именно абстрактные методы в абстрактном родителе, вместо пустых полей?
Вместо
private $coffe;
public function getCoffe() {
return $this->coffe;
}
в родителе и
private $coffe = 20; в наследнике
нужно писать что-то типа:
abstract private function getBasicCoffe();
public function getCoffe() {
$result = $this->getBasicCoffe() * ....
return $result;
}
в предке, и соответственно
private function getBasicCoffe() {
return 20;
}
в наследниках?
Я понимаю вроде как идею, тип у нас такая вот напоминалка получается. Но для такого нуба как я это только лишнее запутывание :(
Я в упор не вижу какой-то блядский косяк
http://ideone.com/WP0lUQ
У Мэтта Зандстры в книге такой же код блджад. Я в огне
> Я в упор не вижу какой-то блядский косяк
Интерпретатор тебе выдал более чем доходчивое объяснение.
Если класс содержит абстрактный метод, то классу нужно приписывать abstract
> echo $mouse->findThreats;
Ты пытаешься вызвать метод класса как свойство.
Как думаете. Можно ли это использовать в ответе на один из самых УЕБАНСКИХ вопросов на собеседовании, а именно: ПОЧЕМУ PHP?
Просто ебальник бы бил за него нахуй.
А так отвечаешь что мол у нас всё збс, топовый язык же.
Норм вопрос, если ты писал на нескольких языках и можешь провести параллели и обосновать почему PHP для тебя подходит лучше. Здесь в ход идёт твой кругозор программиста.
Я на джуниора претендую это раз.
Во вторых у меня в резюме нет ни строчки о других языках, то есть вообще. Я как бы начинал вкатываться в програмирование именно с php, на его основе учил все примитивы и всё в таком духе.
И тут те такой вопрос: А ПОЧЕМУ ПХП? А ОПИШИТЕ ПЛЮСЫ И МИНУСЫ?
> Я на джуниора претендую
Странная отговорка.
> И тут те такой вопрос: А ПОЧЕМУ ПХП? А ОПИШИТЕ ПЛЮСЫ И МИНУСЫ?
Ну вот а действительно, почему ты из языков именно PHP выбрал? А что если другие лучше, а ты жрёшь говно, даже сам этого не осознавая? Увидел много вакансий - так и скажи, ничего зазорного, все кушать хотят. Повторяю, нормальный вопрос, тем более для джуна. Позволяет набрать дополнительные плюсики.
> мол у нас всё збс,
Понятно, мы вам перезвоним.
Ладно кароче, на следующем собеседовании говорю, что начала учить пхп, потому что увидел тред на дваче, с простым и понятным учебником, дружелюбным обсуждением ну и кароче не надо было ебать мозги, прост сел и через час ты уже что-то умеешь, ну а дальше понеслось.
Если кароче меня не берут после такого откровения, то ты пидор.
Боже блядь, почему не сделать просто возможность сделать свойства абстрактными? Это же пиздец получается костыль во имя обхода хуйни.
Ну делаю я абстрактный класс, хули у него не может быть абстрактных свойств, алло разрабы, алло? Скажите мне пожалуйста, что в 7 версии это есть.
Или я как нуб не понимаю что несу, и если дать возможность делать свойства абстрактными, то это выпустит ктулху?
Автозагруззка классов, это вот это
function _autoload($classname){
include_once("controllers/$classname.php");
}
что ли?
Подсказка
spl_autoload_register() предоставляет более гибкую альтернативу для автоматической загрузки классов. По этой причине использовать __autoload() не рекомендуется, а сама функция в будущем может перестать поддерживаться или быть удалена.
В Java тоже нет абстрактных свойств.
Меня, надеюсь, поправят, если ошибаюсь:
"Абстрактный" обозначает, что у нас есть декларация, но нет определения (definition), поэтому интерпретатор выбрасывает ошибку, если метод не переопределить (точнее, не выставить ему тело в наследниках). В PHP нет понятия декларации функции и её определения (В C/C++ есть). Декларация функции - имя функции, количество и тип принимаемых параметров. Тело функции (определение), думаю, знаешь, что такое. Когда ты делаешь метод абстрактным, ты используешь только декларацию функции, без тела.
Так вот переменную мы не можем задекларировать, она уже существует, когда мы только написали $foo.
>>808132
Ну написано же всё: https://github.com/codedokode/pasta/blob/master/php/autoload.md
Зачем мне эти мусорные поля в объектах от родительского абстрактного класса и как этого избежать?
То есть, нет общей системы ORM?
Просто устроился на работу, а там БИТРИКС(самому стыдно, но опыт) и мне сказали, что нужно читать по ORM.
Ну я просто не знаю, в какую сторону копать, решил спросить у знающего анона. Спасибо за советы.
Опыт? Я бы не называл Битрикс опытом. Это так же как с вордпрессом блядь. Ковыряние в битриксе и прочей подобной хуйне делает тебя чисто знакомым с Битриксом. То есть если ты учил php, потом шел на битрикс, то ты можешь стать неплохим Битрикс-специалистом, но если захочешь слинять, то придется возвращаться туда, откуда ты начал своё знакомство с битриксом, а то и раньше, что бы освежать свои знания. Инфа 99.734656%
Так я имею ввиду опыт работы, чтобы меня потом нахуй не посылали на собеседованиях.
Анон, ты не понял. Если тебе сформулировали задание, а ты ничего не понял, но не подал виду, а молча кивнул, не задавая никаких вопросов, то это плохо. Ты либо учишься спрашивать у начальства что непонятно, либо тебя выпнут, так как ты сидишь без толку, ничего не понимая, боясь лишний раз уточнить что-то.
А вот за этот совет спасибо втройне. Часто ловлю себя на мысли, что боюсь переспросить. Хотя последнее время научился перебарывать себя: меня за вопрос не побьют, денег с меня за вопрос не возьмут, мать не откажется. Спасибо за то, что подбодрил.
Так тебя только на собеседования в битрикс-конторы и не будут посылать :3
+ echo. Можно ли как то очищать экран в процессе ?
http://ideone.com/GIHFpR
Увидел, спасибо. Думал ошибка именно в 18-й строке ))
> $isAuthorized=$this->c['isAuthorized'];
> Ну например , что если мы хотим обработать несколько запросов
А это как? Как пользователь может передать несколько запросов? Типа изменить данные, а потом выйти из системы одним нажатием url'а? Тут я не очень догоняю.
Просто я понимаю, что это происходит так: в начале выполнения моего мега-кода происходит проверка на авторизацию и в течение выполнения программы статус авторизации не меняется вплоть до отсылания представления пользователю. Если он сделает logOut, то при следующем запуске программы статус будет отрицательным так же от начала до конца выполнения программы.
В стандартной схеме работы пхп интерпретатор на каждый запрос запускает отдельную копию скрипта и скрипт обрабатывает только один запрос.
Однако есть и другие подходы. Например, мы самостоятельно можем открыть порт, принимать HTTP запросы, вызвать нужны контроллер и отдавать ответ (HTML страницу) обратно. В такой схеме наш код будет запускаться од н раз и обрабатывать запросы в цикле. И тут недостатки твоего подхода станут хорошо заметны.
>>808326
Тебе надо установить апач + пхп (что-то напоминающее инструкции есть в ОП посте). Затем почитать урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
Затем комментарии к студентам.
Понял, щас исправлю. А можешь привести примеры где используется такой нестандартный подход?
Я почему решил сделать контейнер isAuthorized. В коде он несколько раз вызывается и каждый раз проверяет куки и в базу заходит
Хочу сделать TestHub на Symfony2.
Курс рассчитан на абсолютных новичков. Но довольно интенсивен.
http://javarush.ru/cs50.html
Также упомяну, что там присутствует и PHP.
Объекты содержимое которых задается один раз и больше не изменяется. Например, http://php.net/manual/en/class.datetimeimmutable.php
Имеют такие преимущества:
- можно передавать их в функцию и иметь гарантию что она не поменяет объект
- если ты отслеживаешь изменения (например в ORM), то если объект остался тот же, то можно не проверять его на изменения
У них есть еще другие особенности, которые важны например в многопоточной среде, но для php это неактуально. В пхп они вообще особо не используются.
>>808576
Не против, делай. Симфони хороший фреймворк, только готовься читать докмуентацию и ковыряться в исходниках, а не скачи по верхам.
>>808560
Некоторые используют это для оптимизации, чтобы приложение не надо было инициализировать на каждый запрос. В любом случае, суть контейнера в том, что бы хранить сервисы, а не что-то что относится к текущему запросу.
> В коде он несколько раз вызывается и каждый раз проверяет куки и в базу заходит
Это исправляется тем, что можно кешировать текущий объект пользователя внутри сервиса авторизации и возвращать его при повторном обращении. Не забывай сбрасывать кеш при разлогинировании/залогинивании.
> public function makeReport() { //хз куда если не сюда сложить подобный метод
Ну посмотри внимтельно, он же даже по стилю не соответствет другим методам. Это надо вынести куда-то наружу, в отдельную функцию например.
> if (is_subclass_of($worker, 'Worker')) {
Используй лучше instanceof . Также, вопрос, а что если передано что-то неправильное? Молча проигнорируем? Это не выход. Лучше выбросить исключение.
> public function getTotalDepStuff ($something) { //Salary, Coffe, Papers В процессе написания оказались 3 одинаковых функции, объединил их
Это плохая идея так делать. Вот смотри, у тебя имя функции формируется по кускам и явно целиком нигде не вписано: $something = 'getWorker' . mb_convert_case($something, MB_CASE_TITLE);
Что если я хочу например проверить поиском, где используется функция getWorkerSalary? Поиск не найдет эту строчку. Потому надо стараться не формировать имена функций динамически, а если без этого никак, то делать это хотя бы в том же классе что и сами методы.
Более того, нет даже никаких проверок, правильно
В твоем случае можно либо передавать имя функции целиком, либо (что лучше) передавать анонимную функцию как аргумент. Этой функции передается очередной департамент, и она возвращает интересующую характеристику. И конечно от пользователя все это стоит скрыть, сделав 3 метода с названиями вроде getTotalSalary(). А не заставлять пользователя угадывать как ему получить то или иное значение и разбирать кривой код.
> как почитаю про исключения, то заменю
> return "N/A";
почитай и замени
> //private $salary; //и без них всё работает, но если их разкоментить, то будут в наследниках мусорные пустые поля от родителя
Это неправильно. Не должно быть в классе обращений к полям которых в этом классе нет. Есть такой принцип "класс не должен знать ничего о своих наследниках". Вот я сейчас напишу наследника к классу Worker и где гарантия что я сделаю это поле? Это неправильно.
Вообще использовать тут поля плохая идея. Как ты гарантируешь что тот кто наследует класс, их переопределит? Тут должны быть абстрактные методы. Они специально для этого предназначены. А у тебя все на честном слове держится.
Ну и давай тогда еще делай и антикризисные меры.
>>808279
Скорее всего нет. Есть какие-то ANSI коды для управления терминалом, но они могут быть разные в разных системах. Есть консольная команда. Но зачем очищать экран? Суть терминала вообще-то в том что на нем остается лог введенных команд и ответов на них. Какая выгода от того что твоя команда его очистит? Это вообще не задача скрипта миграции очищать терминал.
> делаю вывод через ob_implicit_flush(true) и ob_flush()
Ты делаешь что-то странное. Ты в браузере что ли скрипт запускаешь? Бросай эту дурь, скрипты миграции надо запускать в командной строке а не через костыли. Что если на середине процесса соединения разорвется или вкладка в браузере упадет? Специально для таких вещей придумана консоль а ты какие-то костыли лепишь.
>>808149
Это не мусорные поля. Приватное поле принадлежит только одному классу и потому в объекте может быть несколько одноименных приватных полей от разных классов.
> public function makeReport() { //хз куда если не сюда сложить подобный метод
Ну посмотри внимтельно, он же даже по стилю не соответствет другим методам. Это надо вынести куда-то наружу, в отдельную функцию например.
> if (is_subclass_of($worker, 'Worker')) {
Используй лучше instanceof . Также, вопрос, а что если передано что-то неправильное? Молча проигнорируем? Это не выход. Лучше выбросить исключение.
> public function getTotalDepStuff ($something) { //Salary, Coffe, Papers В процессе написания оказались 3 одинаковых функции, объединил их
Это плохая идея так делать. Вот смотри, у тебя имя функции формируется по кускам и явно целиком нигде не вписано: $something = 'getWorker' . mb_convert_case($something, MB_CASE_TITLE);
Что если я хочу например проверить поиском, где используется функция getWorkerSalary? Поиск не найдет эту строчку. Потому надо стараться не формировать имена функций динамически, а если без этого никак, то делать это хотя бы в том же классе что и сами методы.
Более того, нет даже никаких проверок, правильно
В твоем случае можно либо передавать имя функции целиком, либо (что лучше) передавать анонимную функцию как аргумент. Этой функции передается очередной департамент, и она возвращает интересующую характеристику. И конечно от пользователя все это стоит скрыть, сделав 3 метода с названиями вроде getTotalSalary(). А не заставлять пользователя угадывать как ему получить то или иное значение и разбирать кривой код.
> как почитаю про исключения, то заменю
> return "N/A";
почитай и замени
> //private $salary; //и без них всё работает, но если их разкоментить, то будут в наследниках мусорные пустые поля от родителя
Это неправильно. Не должно быть в классе обращений к полям которых в этом классе нет. Есть такой принцип "класс не должен знать ничего о своих наследниках". Вот я сейчас напишу наследника к классу Worker и где гарантия что я сделаю это поле? Это неправильно.
Вообще использовать тут поля плохая идея. Как ты гарантируешь что тот кто наследует класс, их переопределит? Тут должны быть абстрактные методы. Они специально для этого предназначены. А у тебя все на честном слове держится.
Ну и давай тогда еще делай и антикризисные меры.
>>808279
Скорее всего нет. Есть какие-то ANSI коды для управления терминалом, но они могут быть разные в разных системах. Есть консольная команда. Но зачем очищать экран? Суть терминала вообще-то в том что на нем остается лог введенных команд и ответов на них. Какая выгода от того что твоя команда его очистит? Это вообще не задача скрипта миграции очищать терминал.
> делаю вывод через ob_implicit_flush(true) и ob_flush()
Ты делаешь что-то странное. Ты в браузере что ли скрипт запускаешь? Бросай эту дурь, скрипты миграции надо запускать в командной строке а не через костыли. Что если на середине процесса соединения разорвется или вкладка в браузере упадет? Специально для таких вещей придумана консоль а ты какие-то костыли лепишь.
>>808149
Это не мусорные поля. Приватное поле принадлежит только одному классу и потому в объекте может быть несколько одноименных приватных полей от разных классов.
используй spl_autoload_register.
>>808117
Как свойство может быть абстрактным? Оно просто хранит в себе какое-то значение. Для твоего случая придуманы абстрактные методы.
Абстрактный метод это значит метод без тела, у него определен прототип (тип передаваемых аргументов и что он должен делать), а вот реализации нет.
>>808114
Это можно сказать как "много доступной и понятной документации на русском языке, хороший мануал". Правда на это можно получить ответный вопрос, а почему ты не хочешь учить английский и читать оригинальную документацию?
>>808051
Давай я еще раз напишу. Если у тебя есть значения полей по умолчанию и их не обязательно переопределять в наследнике, то можно использовать поля. Если же каждый наследник имеет свои значения зарплаты, кофе (или свою уникальную логику их расчета), то надо использовать абстрактные методы.
Абстрактные методы очень даже хороши:
- видно, какие методы надо переопредедить при наследовании
- php напомнит если забыть их переопределить
>>807974
Вообще, это неправда. TIMESTAMP отображается также как и DATETIME, в виде '2016-01-01 12:00:00'. И соответственно передавать его в базу надо в таком же виде. Отличие TIMESTAMP от DATETIME в том, что TS - это конкретный момент времени (с учетом часового пояса), а DATETIME - это просто день и время, без указания часового пояса.
>>807896
А не надо хранить в базе метки в виде чисел. Как это потом читать, как с этим работать? Почитай мануал и выбери TIMESTAMP либо DATETIME.
http://www.mysql.ru/docs/man/DATETIME.html
http://dev.mysql.com/doc/refman/5.7/en/datetime.html
>>807732
У языков есть достоинства и недостатки. Нужно уметь их сравнивать и выбирать исходя из этого.
используй spl_autoload_register.
>>808117
Как свойство может быть абстрактным? Оно просто хранит в себе какое-то значение. Для твоего случая придуманы абстрактные методы.
Абстрактный метод это значит метод без тела, у него определен прототип (тип передаваемых аргументов и что он должен делать), а вот реализации нет.
>>808114
Это можно сказать как "много доступной и понятной документации на русском языке, хороший мануал". Правда на это можно получить ответный вопрос, а почему ты не хочешь учить английский и читать оригинальную документацию?
>>808051
Давай я еще раз напишу. Если у тебя есть значения полей по умолчанию и их не обязательно переопределять в наследнике, то можно использовать поля. Если же каждый наследник имеет свои значения зарплаты, кофе (или свою уникальную логику их расчета), то надо использовать абстрактные методы.
Абстрактные методы очень даже хороши:
- видно, какие методы надо переопредедить при наследовании
- php напомнит если забыть их переопределить
>>807974
Вообще, это неправда. TIMESTAMP отображается также как и DATETIME, в виде '2016-01-01 12:00:00'. И соответственно передавать его в базу надо в таком же виде. Отличие TIMESTAMP от DATETIME в том, что TS - это конкретный момент времени (с учетом часового пояса), а DATETIME - это просто день и время, без указания часового пояса.
>>807896
А не надо хранить в базе метки в виде чисел. Как это потом читать, как с этим работать? Почитай мануал и выбери TIMESTAMP либо DATETIME.
http://www.mysql.ru/docs/man/DATETIME.html
http://dev.mysql.com/doc/refman/5.7/en/datetime.html
>>807732
У языков есть достоинства и недостатки. Нужно уметь их сравнивать и выбирать исходя из этого.
> Гугл говорит, что в MySQL для запрета вставки пустой строки нужно писать триггер. CHECK молча игнорирует проверку. Не думал, что уникальный ключ можно использовать для этого. Правда, таки один студент с пустым токеном в таблице для этого нужен, но его можно и самому создать.
Ну уникальный индекс хорошо бы добавить так как значения здесь должны быть уникальные. CHECK да, в mysql не работает, если будешь Postgres изучать, он там работает.
> Я читал ещё твои посты по тестированию, адресованные другим анонам, мне очень нравится идея автотестов. Попробую начать с простого - написать тесты к калькулятору. Если разберусь, потом посмотрю в сторону функциональных и опробую их на студентах.
Отлично, и урок почитай: https://gist.github.com/codedokode/a455bde7d0748c0a351a
> Сделал проверку на соответствие плейсхолдеров с именами аргументов экшна.
Здесь только есть одна проблема. Код проверки у тебя вписан прямо стеной в index.php: https://github.com/applejacky/students/blob/f996fe2fcf3bb978047e4135e427a7bd4abc9a73/public/index.php#L32
Не лучше ли вынести часть этого кода в какие-то функции, методы? Хотя бы в каком-нибудь хелпере.
> AbstractMapper, который использовал позднее статическое связывание.
Это в общем плохая идея, лучше использовать обычный абстрактный метод. То есть в базовом классе мы пишем:
abstract protected function getTableName();
...
$table = $this->getTableName();
абстрактные методы для таких случаев и предназнаечны. Это намного лучше чем надеяться на то, что не забудут переопределить публичное статическое поле.
Вообще, я считаю что вот это вот "позднее статическое связывание" - это плохая штука и плохо ложится на концепции ООП. В ООП статический метод/поле - это такое поле, которое принадлежит классу. Так как оно принадлежит классу, ты всегда можешь написать Class::$field. А вот это вот "позднее статическое связывание" - это какая-то пародия на наследование, только хуже, без абстрактных методов например. Мне оно не нравится. Тут одназначно можно было бы использовать обычное наследование.
> Думаешь, стоит реализовать смену email?
Думаю, стоит. И пароля тоже. А то ты упрощаешь себе задачу такими ограничениями, подгоняя требования под твою архитектуру. В задаче есть возможность редактировать email.
>>807343
начать со Slim/Silex, затем Yii2, затем Symfony если у тебя на все есть время. Если нет - Yii2 пропустить.
>>807342
Считает верно, но вот если посомтреть на алгоритм, то там какие-то "костыли". Вот после цикла стоит строчка " $total += $credit;". Зачем ты после выплаты кредита прибавляешь остаток баланса назад к общей сумме? Как-то нелогично ведь? Нельзя ли не уходить в минус?
>>807042
А как они будут использоваться? Можно сделать какие-то минимальные проверки, вроде "не меньше N цифр", но в общм номера могут быть самые разные и если их будт читать человек то лучше не ограничивать формат.
Алсо википедия https://ru.wikipedia.org/wiki/Телефонный_план_нумерации
> Гугл говорит, что в MySQL для запрета вставки пустой строки нужно писать триггер. CHECK молча игнорирует проверку. Не думал, что уникальный ключ можно использовать для этого. Правда, таки один студент с пустым токеном в таблице для этого нужен, но его можно и самому создать.
Ну уникальный индекс хорошо бы добавить так как значения здесь должны быть уникальные. CHECK да, в mysql не работает, если будешь Postgres изучать, он там работает.
> Я читал ещё твои посты по тестированию, адресованные другим анонам, мне очень нравится идея автотестов. Попробую начать с простого - написать тесты к калькулятору. Если разберусь, потом посмотрю в сторону функциональных и опробую их на студентах.
Отлично, и урок почитай: https://gist.github.com/codedokode/a455bde7d0748c0a351a
> Сделал проверку на соответствие плейсхолдеров с именами аргументов экшна.
Здесь только есть одна проблема. Код проверки у тебя вписан прямо стеной в index.php: https://github.com/applejacky/students/blob/f996fe2fcf3bb978047e4135e427a7bd4abc9a73/public/index.php#L32
Не лучше ли вынести часть этого кода в какие-то функции, методы? Хотя бы в каком-нибудь хелпере.
> AbstractMapper, который использовал позднее статическое связывание.
Это в общем плохая идея, лучше использовать обычный абстрактный метод. То есть в базовом классе мы пишем:
abstract protected function getTableName();
...
$table = $this->getTableName();
абстрактные методы для таких случаев и предназнаечны. Это намного лучше чем надеяться на то, что не забудут переопределить публичное статическое поле.
Вообще, я считаю что вот это вот "позднее статическое связывание" - это плохая штука и плохо ложится на концепции ООП. В ООП статический метод/поле - это такое поле, которое принадлежит классу. Так как оно принадлежит классу, ты всегда можешь написать Class::$field. А вот это вот "позднее статическое связывание" - это какая-то пародия на наследование, только хуже, без абстрактных методов например. Мне оно не нравится. Тут одназначно можно было бы использовать обычное наследование.
> Думаешь, стоит реализовать смену email?
Думаю, стоит. И пароля тоже. А то ты упрощаешь себе задачу такими ограничениями, подгоняя требования под твою архитектуру. В задаче есть возможность редактировать email.
>>807343
начать со Slim/Silex, затем Yii2, затем Symfony если у тебя на все есть время. Если нет - Yii2 пропустить.
>>807342
Считает верно, но вот если посомтреть на алгоритм, то там какие-то "костыли". Вот после цикла стоит строчка " $total += $credit;". Зачем ты после выплаты кредита прибавляешь остаток баланса назад к общей сумме? Как-то нелогично ведь? Нельзя ли не уходить в минус?
>>807042
А как они будут использоваться? Можно сделать какие-то минимальные проверки, вроде "не меньше N цифр", но в общм номера могут быть самые разные и если их будт читать человек то лучше не ограничивать формат.
Алсо википедия https://ru.wikipedia.org/wiki/Телефонный_план_нумерации
https://github.com/TheSidSpears/Students/blob/master/app/views/modules/bottom.php
> А не надо хранить в базе метки в виде чисел
А это специалист в своем курсе советовал, хех. Ну а действительно, почему бы и нет, зато потом можно выбрать удобный для себя формат вывода.
А таймзону куда будешь класть?
Можешь заюзать это: https://www.sencha.com/products/extjs/
Там вообще верстать не надо, для всего многих вещей есть готовые виджеты.
спасибо конечно, но мне самому нужно уметь верстать, я конечно могу взять, да спиздить шаблон, но это же надо умеьть
1. не используй регулярки без крайней необходимости.
2. Заменяй +7 на 8 через str_replace
3. Не используй ключ в конструкции foreach если не собираешься использовать в цикле.
...но если ты даже хтмл не знаешь, то совет заюзать эту библиотеку - плохой совет.
>Симфони хороший фреймворк, только готовься читать докмуентацию и ковыряться в исходниках, а не скачи по верхам.
Да, на работе его и используют. Собственно, я и хочу что-то своё написать с целью изучить уже известные вещи более глубоко.
Ясно. Я, правда, со своей проблемой уже кое-как справился (надо было плюс в квадратные скобки занести), но за советы всё равно спасибо.
Наследуешься от datamanager, переопределяешь метод getMap, описывая в нем поля своей таблицы, и собственно вот тебе весь орм
Ну а можно пример замены свойства в абстрактном классе на абстрактный метод?
Я просто не понимаю в итоге, что делать то нужно, вот как тут >>808051
делаем? И вместо
public $coffe = 20;
везде пишем
public returnCoffe () { return 20; }
?
Это же не просто так тип взял по фанчику заменил в родителе свойства методами, это потом в наследниках с этим работать, и в других классах возможно тоже.
Я уже не знаю, перебробовал несколько вариантов синтаксиса, но ничего не работает. Может у меня как-то mysql не так настроен?
у тебя там вопросы что делают? Ты же не подготовленный запрос делаешь.
Ты и пиши стандартный mysql запрос
$sql = "INSERT INTO catalog (title, author, pubyear, price) VALUES ($title, $author, $price, $pubdate)";
Только ковычки не забудь двойные, ну и переменные расставить в правильном порядке.
Ох, там я еще просто mysqli_prepare и mysqli_stmt_bind_param($stmt, "ssii", $title, $author, $pubyear, $price) делал раньше. Не суть, все равно не работет.
Забыл ошибку показать:
Warning: mysqli_prepare() expects parameter 1 to be mysqli, null given in C:\OpenServer\domains\eshop.com\inc\lib.inc.php on line 5
> mysqli_prepare() expects parameter 1 to be mysqli, null given
Т.е. он почему-то считает, что я ему передаю не линк на бд, а какое-то левый параметр я так понял. Но что я делают не так понять не могу.
Я понял в чем у меня ошибка была. Я пытался из функции общараться к внешней переменной, т.е. $link у меня там не было, зато смог через $GLOBAL["link]. Это нормальный подход, или лучше так не делать?
http://ideone.com/zqAqXA
PHP Parse error: syntax error, unexpected 'if' (T_IF), expecting ']' in /home/19XEJy/prog.php on line 15
написано же.
в 14 строке [ вместо {
Иди в JS тред, а ещё лучше в /web
>Хуже читаемость.
Ну очень спорно же, с конкатенацией мне проще на новую строку код переносит и я сразу вижу, что есть текст, а что переменная.
К тому же, элемент массива или свойство объекта удобнее вставлять.
http://ideone.com/e6GYFK
Окай. Какую ты преследуешь цель? Для души? Учи что хочешь. Для работы? Найди вакансии в своём городе на должность руби, питона. Сделай выводы.
Хочу зарабатывать бапки на фрилансе, а потом, поднабравшись опыта, может быть вкатиться в офис. Просто как только я наткнусь на php в каких-либо форумах, то сразу же начинают пиздеть, что язык говно и говорят про Python и Ruby.
Я не хочу тратить время... Вдруг правда, через несколько годиков php станет никому не нужен и придется вкатываться в другие языки.
Уже скачал дохуище курсов по php, но меня одолевает гора сомнений, поэтому никак не могу приняться за изучение.
Знаю C++ на среднем уровне, но на нем ничего стоящего не писал, только решал олимпиадные задачки и баловался со всякими графическими библиотеками, ну и Qt.
Сначала я занялся программированием для души, мне просто это понравилось и прочитав пару гуидов про создание игр, начал учить C++. Потом, покончив с играми, мне наконец захотелось зарабатывать деньги на своем любимом деле, но как только я начал гуглить, понял, что я полный ноль и мне нужно поднабраться знаниями. Позже нашел инфу, что чтобы зарабатывать бапки на программировании, лучше вкатиться в веб. Короче блять, я не знаю зачем это написал, но пусть будет.
>сразу же начинают пиздеть, что язык говно и говорят про Python и Ruby.
Не надо так. Присмотрись внимательнее и увидишь что каждый язык так или иначе смешивают с грязью.
>Позже нашел инфу, что чтобы зарабатывать бапки на программировании, лучше вкатиться в веб. Короче блять, я не знаю зачем это написал, но пусть будет.
Ну PHP никому не нужен чистым. Все хотят PHP + HTML5+CSS+Javascripts+%Framevorkname% готов ли ты потратить года 2 на изучение этого всего?
Ну зайди на фриланс биржи и посмотри для какого из языков больше заказов, что ты как маленький.
Кратко: вакансии есть на всех трёх языках, учи какой хочешь. На PHP вакансий больше, потому как много обезьяньей работы вроде пикрилейтед.
> Просто как только я наткнусь на php в каких-либо форумах, то сразу же начинают пиздеть, что язык говно и говорят про Python и Ruby.
Говнокодить можно на любом языке, руби же своими магией и фривольностью тебя к этому будет ещё и подталкивать.
Твой код ищет любые латинские буквы в любых словах. А в здадче надо искать слова содержащие буквы разных алфавитов. Если слово полностью английское то ошибки быть не должно.
Надо чуть доделать программу.
>>810118
Сложные выражения удобнее комбинировать через sprintf, а для простых кавычки и точки создают визуальный мусор.
>>809986
Я не знаю какая галерея тебе нужна, найди статьи с обзорами и выбери ту что подходит.
>>809769
Нет, это плохой подход. Все, что функции нужно, лучше передавать через аргументы.
Алсо вместо mysqli удобнее использовать PDO.
В твоем коде например нет обработки ошибок. После каждой mysqli функции надо проверять не вернула ли она ошибку, смотри примеры кода в мануале.
>каждый язык так или иначе смешивают с грязью.
Ну мне все таки кажется что php обсирают больше. Хотя это мода наверное такая просто.
>Ну PHP никому не нужен чистым.
Да, конечно я в курсе, что одного php не хватит. Я просто пытаюсь выбрать бэкенд язык.
----------
>>809726
Неправильно вставлять переменные прямо в запрос, читай урок https://github.com/codedokode/pasta/blob/master/security/sql-injection.md
>>809254
> везде пишем
> public getBaseCoffeeAmount () { return 20; }
да. если ставка всегда постоянная то просто вызвай $this->getBaseCoffeeAmount()
Если значения может меняться (ну например базовая ставка зарплаты) то придется копировать из метода в поле.
В любом случае суть абстрактных методов в том что ты как бы ими задаешь вещи которые будут определяться в наследниках.
>>808168
У ОПа есть такой урок по теме https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>808763
Ему верстку надо учить, и эта библиотека для файлообменника абсолютно не годится. Только усложняет все. Надо мегабайт яваскрипта загрузить что ли?
>>808751
Проходить задания по HTML/CSS из ОП поста.
>>808734
Никак. Лучше всего возвращать результат через ретурн, в крайнем случае можно передать объект и менять его свойства, но скорее всего ты что-то делаешь неправильно.
>>808729
Знак плюс воспринимается как спецсимвол (задающий число повторений).
>>808718
Ну вот мы и видим уровень этого "специалиста".
>>808689
margin-bottom? Это тебе надо в своих стилях делать.
>>806661
>>808719
> Она же в вендоре/автолоад.пхп, я ж не могу ее редактировать.
А этот файл на основе чего генерируется? На основе правил в composer.json, в ключе autoload. Допиши туда нужное правило.
----------
>>809726
Неправильно вставлять переменные прямо в запрос, читай урок https://github.com/codedokode/pasta/blob/master/security/sql-injection.md
>>809254
> везде пишем
> public getBaseCoffeeAmount () { return 20; }
да. если ставка всегда постоянная то просто вызвай $this->getBaseCoffeeAmount()
Если значения может меняться (ну например базовая ставка зарплаты) то придется копировать из метода в поле.
В любом случае суть абстрактных методов в том что ты как бы ими задаешь вещи которые будут определяться в наследниках.
>>808168
У ОПа есть такой урок по теме https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>808763
Ему верстку надо учить, и эта библиотека для файлообменника абсолютно не годится. Только усложняет все. Надо мегабайт яваскрипта загрузить что ли?
>>808751
Проходить задания по HTML/CSS из ОП поста.
>>808734
Никак. Лучше всего возвращать результат через ретурн, в крайнем случае можно передать объект и менять его свойства, но скорее всего ты что-то делаешь неправильно.
>>808729
Знак плюс воспринимается как спецсимвол (задающий число повторений).
>>808718
Ну вот мы и видим уровень этого "специалиста".
>>808689
margin-bottom? Это тебе надо в своих стилях делать.
>>806661
>>808719
> Она же в вендоре/автолоад.пхп, я ж не могу ее редактировать.
А этот файл на основе чего генерируется? На основе правил в composer.json, в ключе autoload. Допиши туда нужное правило.
Есть несколько способов:
1) На сайте JetBrains выбираешь студенческую лицензию, высылаешь им туда фотку студбилета, дают на год лицензию на все их программы. Я так сделал.
2) Пользуешься триал версией в 30 дней, потом удаляешь PHPStorm (конфиги не удаляешь), ставишь опять эту IDE, она говорит тебе мол у вас есть конфиги, применить ли их, тыкаешь да. И так каждый месяц, но ничего заново настраивать не нужно.
На винде геморно при каждой установке 10 раз нажимать next, а вот на линуксе это всё легко автоматизируется, так как софт ставится через пакетный менеджер.
3) Брать бесплатную IDE, например NetBeans. Сомневаюсь, что ты почувствуешь разницу между PHPStorm.
>>810864
По-моему, нужно лесом обходить компании, которые требуют от меня сертификаты, а не знания или гитхаб.
Rutracker.
Ну почему сразу требуют? Просто если у меня есть гитхаб, знания и сертификаты. Не будет ли это плюсом?
Нет, это будет минусом.
>По-моему, нужно лесом обходить компании, которые требуют от меня сертификаты, а не знания или гитхаб.
>требование, начичие CCNA или CCNB...
>Зарплата 180 000 рублей.
>лесом обходить компании, которые требуют от меня сертификаты
Обходи.
Но так я вижу строку, почти в том виде, в котором она отобразится, а со sprintf, все не так просто
> Cisco Certified Network Associate (CCNA)
> Сisco
Значение знаешь? И чего ты вакансию не указал, там поди инженер Cisco какой-нибудь, логично, что от него будут требовать сертификаты Cisco, а не гитхаб, он же не кодер, к нему другие требования. И 180k это помидор с многолетним опытом, который знает сам что ему нужно. Переформулирую: я бы лесом обходил компании, требующие для должности PHP-джуна какие-то сертификаты, а не знания и гитхаб.
>> Она не умеет считать русские буквы, имей в виду.
> Я так понял, это справедливо для всех str_* функций без префикса mb? А как тогда выравнивать? Сделал sprintf'ом.
Да, почти для всех, кроме нескольких, для которых работа с байтами или буквами ничего не меняет (str_replace, strtr - их можно использовать). sprintf кстати тоже не умеет считать правильно. Приходится для таких случаев писать что-то свое на основе mb_ функций.
> https://github.com/applejacky/arithmetic_expression_calculator/blob/master/test.php#L24
> '2^(1/2)' => SimpleFraction::SIGN_INACCURATE . pow(2, 1 / 2),
Вот здесь конечно тест получился плохой, так как содержит в себе по сути копию кода, который тестирует. Более того, он жестко определяет число знаков после запятой - если твой код вернет чуть более точный результат, тест провалится.
В такой ситуации лучше бы как-то задать рамки или погрешность - например "1.41 +- 0.02". Разумеется, можно использовать не 2, а например 6 знаков после запятой. Но главное что мы не пытаемся сравнивать посимвольно неточные числа.
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/test.php#L56
> '4 - 3' => ' 1',
Тут закрался лишний пробел - это не проблема?
Насчет поточности - нет, парсер не поточный, так как он разом делит строку на массив токенов и возвращает на выходе массив. Для выражений это вполне нормально, но парсеры текстов программ обычно пишутся немного по-другому. Обычно они пишутся как некий итератор, который при каждом вызове возвращает следующий токен. При этом входной файл они тоже могут читать побайтово или построчно:
$lexer = new Lexer($inputStream);
while ($token = $lexer->next()) {
...
}
Или, если объект поддерживает интерфейс Iterator, можно писать так:
$lexer = new Lexer($inputStream);
foreach ($lexer as $token) {
....
}
Для математических выражений это не требуется, но в PHP есть интересная штука, которая упрощает поточную обработку данных - она назвается генераторы. С ней можно писать так:
$lexer = new Lexer($inputStream);
foreach ($lexer->tokenize() as $token) {
...
}
Это напоминает итератор, но реализация на основе генераторов получается более простой и красивой. Наверно для математических выражений это не нужно, но если бы тебе надо было обрабатвать какие-то большие наборы сущностей (например гигантские XML файлы), такой подход мог бы помочь. Советую почитать про итераторы и генераторы.
> if ($operandsCount !== $binaryOperatorsCount + 1) {
> throw new InvalidInfixException('Количество бинарных операторов должно быть на один меньше, чем количество чисел');
> if ($parenthesisDeep !== 0) {
> throw new InvalidInfixException('Неправильно расставлены скобки');
Эти ошибки наверно должен отлавливать алгоритм сортировочной станции?
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/InfixParsing/ShuntingYard.php#L22
> public function createRpnQueueFromTokens(\SplQueue $tokens)
Мелочь, но хотел бы обратить внимание. Здесь ведь не принципиально иметь на входе именно SplQueue, нам подойдет любая коллекция, которую можно перебирать. В новом php для этого будет тайп хинт iterable, а сейчас пока можно только проверять типы вручную командой вроде
assert(is_array($x) || $x instanceof \Traversable);
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/InfixParsing/ShuntingYard.php#L47
> $operatorTop = $this->operatorStack->top();
> if (!$operatorTop instanceof LeftParenthesis) {
> $outputQueue->enqueue($this->operatorStack->pop());
> }
> $this->operatorStack->pop();
Вот здесь нет ли ошибки? Если присмотреться к коду то видно что если на стеке не скобка, то мы снимаем оператор со стека и добавляем в выходну очередь, а затем снимаем еще один оператор - а есть ли гарантия что это 100% скобка? Я бы как минимум if или assert туда поставил.
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/Operator/AbstractOperator.php
Здесь ты обращаешься к статическому несуществующему полю. Это в общем плохо так как класс ничего не должен знать о своих потомках. Для указания приоритета надо завести абстрактный метод. Так наследующий класс поймет что он должен определить.
> if ($rightOperand->getNumerator() === '0') {
Я бы сделал для удобства метод isZero()
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/Operator/Parenthesis.php
Следовало объявить абстрактным
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/Operator/Power.php#L23
> $result = (new Division())->operate($oneAsFraction, $newDenominator);
1 поделить на дробь это просто переворот дроби.
Что касается возведения в дробную степень, я бы разбил ее на 2 части: возведение в степень и извлечение корня. Ну наример возведение в 2/3 лучше делать как возведение в квадрат, затем взятие корня. Иначе мы округляем 2/3 и можем что-то потерять по дороге. Плюс, проверку на точность ты делаешь только для степени 1/3 в этом случае.
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/SimpleFraction.php#L55
> public function invert()
Вот здесь тоже есть неочевидность: создается ли новая дробь или меняется сущестсующая? Если меняется, то лучше бы ничего не возвращать, а то кажется что создается новая.
> public function __toString()
Насчет этой функции - я не люблю ее использлвать так как из-за нее можно например использовать объект как-то неправильно и не получить при этом ошибки.
Ну и мне по прежнему кажется, что удобно было бы иметь возможность складывать и умножать дроби не создавая для этого объекты токенов.
Так, в общем, хорошо сделано.
>> Она не умеет считать русские буквы, имей в виду.
> Я так понял, это справедливо для всех str_* функций без префикса mb? А как тогда выравнивать? Сделал sprintf'ом.
Да, почти для всех, кроме нескольких, для которых работа с байтами или буквами ничего не меняет (str_replace, strtr - их можно использовать). sprintf кстати тоже не умеет считать правильно. Приходится для таких случаев писать что-то свое на основе mb_ функций.
> https://github.com/applejacky/arithmetic_expression_calculator/blob/master/test.php#L24
> '2^(1/2)' => SimpleFraction::SIGN_INACCURATE . pow(2, 1 / 2),
Вот здесь конечно тест получился плохой, так как содержит в себе по сути копию кода, который тестирует. Более того, он жестко определяет число знаков после запятой - если твой код вернет чуть более точный результат, тест провалится.
В такой ситуации лучше бы как-то задать рамки или погрешность - например "1.41 +- 0.02". Разумеется, можно использовать не 2, а например 6 знаков после запятой. Но главное что мы не пытаемся сравнивать посимвольно неточные числа.
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/test.php#L56
> '4 - 3' => ' 1',
Тут закрался лишний пробел - это не проблема?
Насчет поточности - нет, парсер не поточный, так как он разом делит строку на массив токенов и возвращает на выходе массив. Для выражений это вполне нормально, но парсеры текстов программ обычно пишутся немного по-другому. Обычно они пишутся как некий итератор, который при каждом вызове возвращает следующий токен. При этом входной файл они тоже могут читать побайтово или построчно:
$lexer = new Lexer($inputStream);
while ($token = $lexer->next()) {
...
}
Или, если объект поддерживает интерфейс Iterator, можно писать так:
$lexer = new Lexer($inputStream);
foreach ($lexer as $token) {
....
}
Для математических выражений это не требуется, но в PHP есть интересная штука, которая упрощает поточную обработку данных - она назвается генераторы. С ней можно писать так:
$lexer = new Lexer($inputStream);
foreach ($lexer->tokenize() as $token) {
...
}
Это напоминает итератор, но реализация на основе генераторов получается более простой и красивой. Наверно для математических выражений это не нужно, но если бы тебе надо было обрабатвать какие-то большие наборы сущностей (например гигантские XML файлы), такой подход мог бы помочь. Советую почитать про итераторы и генераторы.
> if ($operandsCount !== $binaryOperatorsCount + 1) {
> throw new InvalidInfixException('Количество бинарных операторов должно быть на один меньше, чем количество чисел');
> if ($parenthesisDeep !== 0) {
> throw new InvalidInfixException('Неправильно расставлены скобки');
Эти ошибки наверно должен отлавливать алгоритм сортировочной станции?
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/InfixParsing/ShuntingYard.php#L22
> public function createRpnQueueFromTokens(\SplQueue $tokens)
Мелочь, но хотел бы обратить внимание. Здесь ведь не принципиально иметь на входе именно SplQueue, нам подойдет любая коллекция, которую можно перебирать. В новом php для этого будет тайп хинт iterable, а сейчас пока можно только проверять типы вручную командой вроде
assert(is_array($x) || $x instanceof \Traversable);
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/InfixParsing/ShuntingYard.php#L47
> $operatorTop = $this->operatorStack->top();
> if (!$operatorTop instanceof LeftParenthesis) {
> $outputQueue->enqueue($this->operatorStack->pop());
> }
> $this->operatorStack->pop();
Вот здесь нет ли ошибки? Если присмотреться к коду то видно что если на стеке не скобка, то мы снимаем оператор со стека и добавляем в выходну очередь, а затем снимаем еще один оператор - а есть ли гарантия что это 100% скобка? Я бы как минимум if или assert туда поставил.
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/Operator/AbstractOperator.php
Здесь ты обращаешься к статическому несуществующему полю. Это в общем плохо так как класс ничего не должен знать о своих потомках. Для указания приоритета надо завести абстрактный метод. Так наследующий класс поймет что он должен определить.
> if ($rightOperand->getNumerator() === '0') {
Я бы сделал для удобства метод isZero()
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/Operator/Parenthesis.php
Следовало объявить абстрактным
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/Operator/Power.php#L23
> $result = (new Division())->operate($oneAsFraction, $newDenominator);
1 поделить на дробь это просто переворот дроби.
Что касается возведения в дробную степень, я бы разбил ее на 2 части: возведение в степень и извлечение корня. Ну наример возведение в 2/3 лучше делать как возведение в квадрат, затем взятие корня. Иначе мы округляем 2/3 и можем что-то потерять по дороге. Плюс, проверку на точность ты делаешь только для степени 1/3 в этом случае.
https://github.com/applejacky/arithmetic_expression_calculator/blob/master/src/SimpleFraction.php#L55
> public function invert()
Вот здесь тоже есть неочевидность: создается ли новая дробь или меняется сущестсующая? Если меняется, то лучше бы ничего не возвращать, а то кажется что создается новая.
> public function __toString()
Насчет этой функции - я не люблю ее использлвать так как из-за нее можно например использовать объект как-то неправильно и не получить при этом ошибки.
Ну и мне по прежнему кажется, что удобно было бы иметь возможность складывать и умножать дроби не создавая для этого объекты токенов.
Так, в общем, хорошо сделано.
http://ideone.com/T9fe92
Теперь все верно. Там правда пробел затесался лишний, но это мелочи.
>>799256
>> Надо ставить фигурные скобки. Вместо копипастоы ифов лучше сделать массив с цифрами и словами и циклом искать совпадения в нем.
> Я ничегошеньки не понял как это делать, кто-нибудь может подсказать?
я имею в виду делаешь массив вида
[0 => 'few', 4 => 'several', 9 => 'pack', ...]
и обходишь его циклом, ища подходящее слово.
> 6 задача: http://ideone.com/ZockRi
> if ($i % 2 == 0 and $i == $first) {
Это ведь никогда не сработает
> $second = 0139;
Ты в курсе что это получается восьмеричное число? http://php.net/manual/ru/language.types.integer.php
https://github.com/never3ver/students_list
Почему этот код всегда убивается? По синтаксису вроде правильно же все, не?
Да кстати, подключение к ДБ есть, там все нормально.
> stderr
> PHP Parse error: syntax error, unexpected '<' in /home/dxAupK/prog.php on line 3
> PHP Parse error: syntax error, unexpected '<' in /home/dxAupK/prog.php on line 3
> PHP Parse error: syntax error, unexpected '<' in /home/dxAupK/prog.php on line 3
> PHP Parse error: syntax error, unexpected '<' in /home/dxAupK/prog.php on line 3
Так лучше видно?
http://ideone.com/riyP25
Вот весь мой код грубо говоря. Никаких ошибок с подключение он не показывает. Но
Warning: mysqli_stmt_bind_param() expects parameter 1 to be mysqli_stmt, boolean given in C:\OpenServer\domains\testWork1\dbraste.php on line 17
1) Можно погуглить: http://stackoverflow.com/questions/2228430/mysqli-throws-warning-mysqli-stmt-bind-param-expects-parameter-1-to-be-mysql
2) Лучше брать PDO и выставлять error mode в exception, тогда все ошибки будут видны.
1) Читал этот пост. Никаких ошибок соединение не показывает, проблема в $stmt = mysqli_prepare($connection, $sql); который у меня всегда фолс.
2) Пока пдо я не осиливаю.
>>812305
Алсо, я вот думаю, а может у меня БД плохо настроена? Может быть такое, что таблица создана так, что в нее нельзя ничего добавить?
Проверь, что сервер MySQL запущен. Понапихай везде var_dump'ов, чтобы проверить, до какой строки код выполняется, а начиная с какой уже нет. Обмажь код функциями mysqli_connect_error(), mysqli_error(), mysqli_stmt_error() где нужно.
Потому и советуют использовать PDO вместо MySQLi, так как первый может выбрасывать исключения, а второй молчит при ошибках, отдавая false и попробуй разберись с этим. Проще в PDO разобраться. Я читал phptherightway, погугли, там написано как с PDO работать.
http://ideone.com/riyP25
А вот так все заработало. Да, походу я как-то неправильно создал таблицу, хотя как - вот убей не пойму что там можно не так сделать. И вообще ты прав, надо пдо учить, а то ебанешься каждый раз писать эти проверки.
> materialized path
> При этом способе path хранится в поле вроде TEXT или BINARY, по нему делается индекс. Выбрать всех потомков можно запросом SELECT WHERE path LIKE '001.001.%' ORDER BY path, который использует индекс.
Что за индекс такой? Это как-то связано со сфинксом? Т.е. анон в этот момент должен быть знаком со сфинксом?
nnmclub.to
https://gist.github.com/codedokode/10539213#Индексы
http://ruhighload.com/post/Работа+с+индексами+в+MySQL
Есть у меня гигансткий масив вида http://ideone.com/ArpBjk
Естественно его надо выводить в удобочитаемый вид, нужны только названия городов. Как я понимаю, его надо выводить через foreeach. Но никак не могу правильно это дело написать. Объясните идиоту как это правильно делается.
Foreach проходит по всем элементам массива. В твоем случае достаточно пройтись по всем элементам массива data.
http://ideone.com/raIgwb
Ага, сам разобрался. Забыл что надо было обращаться не в целом к массиву, а во вложенный массив Data.
И тебе спасибо за уделенное время.
http://ideone.com/1Nk5P2
> if ($op == '+') {
> $result += $number;
> }
> if ($op == '-') {
> $result -= $number;
Тут лучше использовать if/elseif - нагляднее будет
Плюс, считает неправильно, для выражения "200 - 200" получается ответ 200: http://ideone.com/Q3N2cZ
http://ideone.com/IcRBhd
та же проблема: http://ideone.com/Hztwjm
>>801090
мне не нравится, так как имена получаются нечитаемые.
Лучше либо переводить их в латиницу транслитом либо использовать номер илит дату загрузки, что-то человекопонятное.
>>801171
hh.ru, мой круг, geekjob, вроде в ОП посте же перечислены.
>>801191
на своем компе можно поднять Апач для начала. Либо виртуалка с дебианом и в ней поднять.
>>801319
Если ты арендуешь shared hosting то там Апач уже установлен и настроен
Если ты арендуещь сервер то ставить и настраивать надо тебе самому, для этого надо изучать командную строку линукса, в ОП посте есть паста для начала.
>>801316
Все решено верно. Единственный совет:
> http://ideone.com/ug2qIV — игра в кубики
> }elseif ($anonSum == $compSum){
Тут можно было использовать просто else
>>801455
Тут надо вписать массив номеров, которые приведены в учебнике, и проверить что она все обрабатываются правильно.
> if (preg_match("/\+7/", $number)) {
Этот if не требуется, можно сразу писать preg_replace
В общем, регулярка правильная.
заменяет слово "ааааа", которое не должна заменять: https://ideone.com/I0imO6
Не находит домены с цифрами: https://ideone.com/B7WvPS
http://ideone.com/1Nk5P2
> if ($op == '+') {
> $result += $number;
> }
> if ($op == '-') {
> $result -= $number;
Тут лучше использовать if/elseif - нагляднее будет
Плюс, считает неправильно, для выражения "200 - 200" получается ответ 200: http://ideone.com/Q3N2cZ
http://ideone.com/IcRBhd
та же проблема: http://ideone.com/Hztwjm
>>801090
мне не нравится, так как имена получаются нечитаемые.
Лучше либо переводить их в латиницу транслитом либо использовать номер илит дату загрузки, что-то человекопонятное.
>>801171
hh.ru, мой круг, geekjob, вроде в ОП посте же перечислены.
>>801191
на своем компе можно поднять Апач для начала. Либо виртуалка с дебианом и в ней поднять.
>>801319
Если ты арендуешь shared hosting то там Апач уже установлен и настроен
Если ты арендуещь сервер то ставить и настраивать надо тебе самому, для этого надо изучать командную строку линукса, в ОП посте есть паста для начала.
>>801316
Все решено верно. Единственный совет:
> http://ideone.com/ug2qIV — игра в кубики
> }elseif ($anonSum == $compSum){
Тут можно было использовать просто else
>>801455
Тут надо вписать массив номеров, которые приведены в учебнике, и проверить что она все обрабатываются правильно.
> if (preg_match("/\+7/", $number)) {
Этот if не требуется, можно сразу писать preg_replace
В общем, регулярка правильная.
заменяет слово "ааааа", которое не должна заменять: https://ideone.com/I0imO6
Не находит домены с цифрами: https://ideone.com/B7WvPS
Ссылка не открывается, точнее открывается но без кода.
>>801909
А что ты умеешь, а на чем запнулся?
>>802291
ПО поводу этого скрипта: https://github.com/TheSidSpears/Students/blob/master/cmd.php
Всю работу с таблицей студентов (выборку студентов) надо бы собрать в одном классе, и использовать твой класс работы с БД а не писать функцию.
> $validator=new StudentValidator($student,$container,$student->getId());
Тут мне не нравится то, что студент передается в конструтор, отдельно зачем-то его id. Контейнер передавать в валидатор неправильно, это же нарущение DI. Студента логичнее передавать не в конструктор, а в функицю валидации. задача конструктора - инициализировать объект. Лучше сделать многоразовый валидатор.
> > перечитай урок про DI. Это service locator и это плохая вещь.
> Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
да, есть те, кто считает что контроллер тоже надо делать как сервис, но это получается сложнее, и не очень понятно, а нужно ли оно. Проще в контроллер передавать контейнер. Контроллер это все равно не повторно используемый код и его вызвать откуда-то нельзя.
>> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
> Добавил setHash(). Еще что-то нужно? У меня нет идей
> Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
нет, это плохо так как не очевидно. Легко добавить публичное поле и внезапно оно становится доступно для редактирвоания пользователем. Это неправильно, надо чтобы все было безопасно по умолчанию, а не превращать код в минное поле.
> потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
Нет, лучше чтобы валидация делалась в методе validate. Логично ведь что валидация это функция, которая принимает на вход модель и возвращает список ошибок. Это позволяет например проверить нескольких студентов одним валидатором. мне кажется так будет удобнее. Хотя конечно твой подход тоже имеет право на жизнь, но мне кажется что лучше для валидации иметь отдельный метод, а не нагружать этим конструктор.
>>803294
> $allEngineers = array_filter($dep->workers, $askEngineer);
правильнее было бы в департаменте закрыть достпу к полю workers и вместо этого предлагать метод поиска работников.
Также, не хватает сортировки работников чтобы увольнять в первую очередь работников определенного ранга.
> foreach ($this->workers as $num => $worker) {
> if ($employee === $worker) {
Можно использовать array_search с флагом точного сравнения
> public function fireEmployee($employee)
тут стоит поставить тайп-хинт
>if (is_array($employee)) {
> $this->workers = array_merge($this->workers, $employee);
> } else {
Это плохая идея, принимать значения разных типов. Это оставляет незамеченными ошибки в коде, не позволяет исопльзовать тайп хинты, усложняет код. Лучше сделать 2 отдельных метода.
> class Employee
Надо пометить его абстрактным. Также, стоит использовать абстрактные методы для переопределения базовой ставки, а не надеяться, что поля не забудут переопределить.
Ну и не хватает одного из антикризисных методов. И применяется только один метод, а надо применить все 3 независимо.
Ссылка не открывается, точнее открывается но без кода.
>>801909
А что ты умеешь, а на чем запнулся?
>>802291
ПО поводу этого скрипта: https://github.com/TheSidSpears/Students/blob/master/cmd.php
Всю работу с таблицей студентов (выборку студентов) надо бы собрать в одном классе, и использовать твой класс работы с БД а не писать функцию.
> $validator=new StudentValidator($student,$container,$student->getId());
Тут мне не нравится то, что студент передается в конструтор, отдельно зачем-то его id. Контейнер передавать в валидатор неправильно, это же нарущение DI. Студента логичнее передавать не в конструктор, а в функицю валидации. задача конструктора - инициализировать объект. Лучше сделать многоразовый валидатор.
> > перечитай урок про DI. Это service locator и это плохая вещь.
> Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
да, есть те, кто считает что контроллер тоже надо делать как сервис, но это получается сложнее, и не очень понятно, а нужно ли оно. Проще в контроллер передавать контейнер. Контроллер это все равно не повторно используемый код и его вызвать откуда-то нельзя.
>> Сам класс авторизации странный, половины функций связанных с авторизацией, в нем нет, они в контроллере.
> Добавил setHash(). Еще что-то нужно? У меня нет идей
> Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
нет, это плохо так как не очевидно. Легко добавить публичное поле и внезапно оно становится доступно для редактирвоания пользователем. Это неправильно, надо чтобы все было безопасно по умолчанию, а не превращать код в минное поле.
> потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
Нет, лучше чтобы валидация делалась в методе validate. Логично ведь что валидация это функция, которая принимает на вход модель и возвращает список ошибок. Это позволяет например проверить нескольких студентов одним валидатором. мне кажется так будет удобнее. Хотя конечно твой подход тоже имеет право на жизнь, но мне кажется что лучше для валидации иметь отдельный метод, а не нагружать этим конструктор.
>>803294
> $allEngineers = array_filter($dep->workers, $askEngineer);
правильнее было бы в департаменте закрыть достпу к полю workers и вместо этого предлагать метод поиска работников.
Также, не хватает сортировки работников чтобы увольнять в первую очередь работников определенного ранга.
> foreach ($this->workers as $num => $worker) {
> if ($employee === $worker) {
Можно использовать array_search с флагом точного сравнения
> public function fireEmployee($employee)
тут стоит поставить тайп-хинт
>if (is_array($employee)) {
> $this->workers = array_merge($this->workers, $employee);
> } else {
Это плохая идея, принимать значения разных типов. Это оставляет незамеченными ошибки в коде, не позволяет исопльзовать тайп хинты, усложняет код. Лучше сделать 2 отдельных метода.
> class Employee
Надо пометить его абстрактным. Также, стоит использовать абстрактные методы для переопределения базовой ставки, а не надеяться, что поля не забудут переопределить.
Ну и не хватает одного из антикризисных методов. И применяется только один метод, а надо применить все 3 независимо.
https://ideone.com/SIa8FK - вставляет запятую в фразу "Все хорошо. Но могло...". Плюс пытается вставить пробел после знака вопроса в конце.
Не ищет буквы вроде B или H. Реагирует на любые английские слова: https://ideone.com/wtqtVR
>>803869
Что значит "зациклить"? Цикл это просто выполнение записанных в теле цикла команд несколько раз подряд.
>>803932
тебе надо сначала изучить MVC и посмотреть чужие движки, фреймворки, например, Yii2 или Symfony 2
>>804123
Надо добавить папку с PHP в PATH. В ОП посте есть паста по командной строке и там вроде это объясняется. И конечно лушче бы установить PHP самому - в ОП посте тоже есть статья по теме.
>>804597
Не знаю. Ты попробуй и посмотри что получится. У нас в ОП посте есть задания - чтобы проверить получил ты нужные знания или еще нет.
По HTML есть htmlbook, htmlacademy, в ОП посте есть задания.
>>804795
Прочитал как "вкатиться в ИГ"
>>804813
Абстрактные классы позоляют тебе задать правила для тех кто наследуется от твоего класса. ты как бы делаешь заготовку, которую они дополняют.
Интерфейсы позволяют отнести класс к какой-то группе или опсиать опредленное умение. Ты можешь их использовать, чтобы твои функции могли работать не с одним классом, а с любым. поддерживающим интерфейс. Урок по теме: https://github.com/codedokode/pasta/blob/master/php/interfaces.md
https://ideone.com/SIa8FK - вставляет запятую в фразу "Все хорошо. Но могло...". Плюс пытается вставить пробел после знака вопроса в конце.
Не ищет буквы вроде B или H. Реагирует на любые английские слова: https://ideone.com/wtqtVR
>>803869
Что значит "зациклить"? Цикл это просто выполнение записанных в теле цикла команд несколько раз подряд.
>>803932
тебе надо сначала изучить MVC и посмотреть чужие движки, фреймворки, например, Yii2 или Symfony 2
>>804123
Надо добавить папку с PHP в PATH. В ОП посте есть паста по командной строке и там вроде это объясняется. И конечно лушче бы установить PHP самому - в ОП посте тоже есть статья по теме.
>>804597
Не знаю. Ты попробуй и посмотри что получится. У нас в ОП посте есть задания - чтобы проверить получил ты нужные знания или еще нет.
По HTML есть htmlbook, htmlacademy, в ОП посте есть задания.
>>804795
Прочитал как "вкатиться в ИГ"
>>804813
Абстрактные классы позоляют тебе задать правила для тех кто наследуется от твоего класса. ты как бы делаешь заготовку, которую они дополняют.
Интерфейсы позволяют отнести класс к какой-то группе или опсиать опредленное умение. Ты можешь их использовать, чтобы твои функции могли работать не с одним классом, а с любым. поддерживающим интерфейс. Урок по теме: https://github.com/codedokode/pasta/blob/master/php/interfaces.md
Сделай index.php, не? Алсо через файл htacess можно.
Вопросы:
Слим самый последний устанавливать? сейчас 3,5 последний, а у тебя ссылка на докумантацию ко второй
Что-бы понять, что делать, нужно прочитать документацию с начала и до конца?
Код Slim'а читать нужно?
Я бы посоветовал начать не с чтения всей документации, а с туториала как писать хелоу ворлд на фреймворке и как на нем реализовать простейший mvc сервис, что бы понять куда какие строчки перегонять и как примерно всё устроено на нем.
Вот же есть в офф документации всё, нагуглил за 5 сек http://www.slimframework.com/docs/tutorial/first-app.html
А далее как начинаешь писать свой сервис, то просто гуглишь возможности фреймворка которые тебе нужны и могут быть в нем реализованы, например:
slim db connection
slim query builder
slim post get
Хотя опять же по документации там пробежаться дело пары часов судя по всему, так как возможностями фреймворк не перегружен.
> Сisco
И чё?
>Переформулирую: я бы лесом обходил компании, требующие для должности PHP-джуна какие-то сертификаты, а не знания и гитхаб.
А где я спрашивал про ТРЕБОВАНИЯ? Вот есть Ерохин с сертификатом уровня CCNA только от PHP. Ему же это будет плюсом? Или например висит у меня на стене RHCSA, я могу из-за него затребовать на собеседовании болшую зарплату. Я повторюсь, знания, опыт и гитхаб у меня есть!
Обьясню тебе и таким как ты. Существуют некодерские конторы, которым нужен просто макак на галеру, чтобы сайтик модерировать. Естественно сайтик не простой, а сайтик болльшой и преуспевающей компании, которая широко известна в своей области. Сидит в такой конторке тётенька мэнэджэр, которая в IT не понимает ничего, зато диплом мэнэджэра есть, и поэтому она там сидит. Вот в такие конторы берут по сертификату. Просто потому-что в один прекрасный момент кто-то начнёт догадываться что сайт немного накрылся нахрен, логины не работаю, новсти отьехали, а стартовая страница - это всё что осталосьот сайта. И вот тогда начинают разбираться кто нанял этого криворукого дауна? А манагер тут как тут со словами "А я хитро прикрою свою жопу фактом наличия у него сертификата!". На этом моменте тень подозрения спадает с манагера и её странной политики найма, и они снова ищут прогроммиста.
Да, добавлю ещё, что платят там таки хорошо. И карьерный рост по фактуотсутствующий, но всё-же есть. Тоесть ты можешь стать из junior даже тим лидом. И зп тебе повысят хоть до 4килобаксов, вот только ты в команда программистов будешь один. Такие дела.
Читай то, что понимаешь. Ну и целиком эту книгу читать не требуется для решения ООП задач, можно делать это параллельно.
А пока оп, с тредом вмете тонули - куча ленивых даунов неспособных пролистать двачи вниз - уже насоздавало новых тредисов.
>При добавлении json столбца
Куда ты его хочешь добавить?
Так, давай по порядку, что именно ты делаешь и зачем?
А пока оп, с тредом вмете тонули - куча ленивых другие неспособных пролистать двачи вниз - уже насоздавало новых тредисов.
Понятно что он тебе нужен. Перефразирую. В конечном результате чего ты ожидаешь?
Что в любую таблицу то? Не понимаю тебя? Что ты делаешь?
Ну при ошибке самое первое что я сделал это попытался добавить в другую таблицу и везде получил такой результат. Чего я ожидаю? Чтобы этой ошибки в пхпмайадмине не было (очевидный ответ #2). Извини, но вопросы у тебя напрашиваются на такие ответы.
Могу еще добавить что ошибка 1 получилась при клике на пик1, а вторая на пик2 (выделил куда жал). Может я чего-то не понимаю, третий день как поставил пхпадмин.
Предположу, что тебя смутило рандомное имя столбца. Там будет fileInfo, массив информации о файле вырезанный getId3 либой.
Что ты пытаешься добавить в таблицу то? Из скриншота ничего непонятно?
Массив информации о файле вырезанный getID3 либой. Так ошибка происходит до добавления чего либо, наверное ее надо решить до этого момента, верно?
>>814593
Давайте я помогу вам гуглить "mysqli unknown type 245"
mysqli (используемая в phpmyadmin) пока не поддерживает тип JSON
https://bugs.php.net/bug.php?id=70384
Там же есть костыль - конвертировать при выборке JSON в CHAR.
Спасибо, анончик. Алсо вопрос опу, какого вида комментарии делать на файлообменник? Как пикрелейтед? Или как вконтакте? В случае пикрелейтеда комментарий "матери" должен пропасть в случае удаления комментария брата?
Как на пикрелейтед, древовидные.
> В случае пикрелейтеда комментарий "матери" должен пропасть
Можно сделать что пропадает, можно заморочиться и вместо родительского писать "комментарий удален", а дочерний оставить. Так будет интереснее.
>пока не поддерживает тип JSON
На кой хуй вообще кому-то засовывать JSON в Mysql? Кто-нибудь дайте мне разумное обьяснение.
Оп посоветовал мне в прошлом треде:
> Тут я думаю проще всего просто в модели и таблице файла предусмотреть поля для информации о картинке и видео. Поскольку видео бывает разных типов с разыми параметрами, то проще всего хранить эти параметры в базе как JSON массив. В коде конечно работать с массивом неизвестной структуры работать неудобно, потому хорошо бы завернуть это в класс, например, с названием FileInfo, с методами для получения списка свойств, значений свойств, конкретного свойства и тд.
>проще всего хранить эти параметры в базе как JSON массив.
Ты уверен что правильно его понял?
Потому-что
>В коде конечно работать с массивом неизвестной структуры работать неудобно, потому хорошо бы завернуть это в класс
Это не неудобно, это работа через такие анусы, что тебе и не снилось.
Ну вот я в эти анусы и попал. Поэтому вопрос. Вот получаю я через FETCH_CLASS из базы свой объект со свойствами, допустим name, size, id и тот самый fileInfo формата json. Как мне его обернуть теперь? Это статический класс должен быть принимающий в свойства целый массив и возвращающий конкретное значение (например длину видео). Или же это класс со свойством fileInfo которое представлено в json формате, а методы делают тоже самое, что и в статическом варианте. В последнем случае желательно чтобы я сразу в объект файла запихивал свойство-класс работы с этим json, т.е. это должно делаться через FETCH_FUNC?
Хотя не, это не главный вопрос. Главный вопрос делать ли мне json_decode на fetch_all | fetch или нет.
Перекати тредис пожалуйста. Я делал это с 60 по 69 треды. Теперь мне лень, а оп пропал. Только закати 4 оп поста и оп пикчи. Тебе в новом тредеответят сразу.
Ну раньше у вас были треды с опом, хотя треды перекатывал не он.
Я научился делать Array
@
ебашу всё через array, даже землю, даже небо, даже 1 стринг через array
А потом вы спрашиваете "Откуда столько быдлокодеров"
У меня есть. Ты в курсе, что вся статика принадлежит классу, а не объекту?
$this и self это не одно и то же. Первое указывает на текущий объект, self указывает на статическое поле класса. Такое поле будет общим для всех классов.
> Такое поле будет общим для всех классов.
Объектов, точнее.
Алсо, если перекатим тред, то в /pr будет 4 живых PHP-треда.
>в /pr будет 4 живых PHP-треда.
Никогда такого не было, и вот опять произошло.
Раньше как всё было медленно - за два года тредов двадцать всего.
https://ru.wikiquote.org/wiki/Виктор_Степанович_Черномырдин
Такое надо знать.
Мы с вами ещё так будем жить, что наши дети и внуки нам завидовать станут!
>>804818
В общем, да, правильно
>>804829
Вот тут есть немного: https://github.com/codedokode/pasta/blob/master/student-list.md#mvc
>>805203
Не знаю, можно ли меня считать "шарящим", но я тут подумал, что надо будет написать урок по MVC. А то действительно, много непонимания.
Там главная суть в отделении модели, хранящей и управляющей данными, от их отображения и от обработчиков действий пользователя. Кроме организации кода, мы получаем возможность например использовать одну модель с разными вью или разными контроллерами.
>>805354
А, что-то я этот пост потерял и не ответил сразу.
> Но тогда всё равно же придётся искать метод который предоставляем наружу. Если мы поменяем внутреннюю логику метода так, что он будет возвращать свершено другой результат, например заместо строки массив, то метод который мы предоставляем наружу, тоже нужно будет поменять, и для этого нужно так же искать где он вызывается.
Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
> Я перечитал твой мануал по инкапсуляции и могу сказать, что она нужно скорее чтобы скрывать внутреннюю логику, а не облегчение её редактирования.
Да, это помогает например понять как использовать класс - тебе достаточно лишь посмотреть на публичные методы, а не изучать весь код класса.
> Так же, мне теперь кажется, что я зря в некоторых сущностях делал свойства закрытыми, ведь при работе с ними нет никакой внутренней логики, мы просто их меняем. И чтобы их не поменяли на неверное значение есть класс валидации.
Ну это пока. На практике логика может появиться в любой момент. Например, при задании одного поля надо менять значение другого поля. И здесь отсутствие инкапсуляции может помешать. В большом и сложном проекте переделать поля на методы будет непросто (если только не использовать магические методы), потому некоторые советуют с самого начала делать все через сеттеры и геттеры. Но так конечно код получается объемнее.
Что касается валидации, то это не совсем то, что нужно. Ведь неверное значение может ставиться в одном месте кода, а валидация - делаться в совсем другом (или вообще не делаться). Валидация - она обычно используется для проверки данных от пользователя.
> Я не могу вспомнить как я научился такому методу. У тебя случайно не было так написано в уроке по DI? Так вообще делают?
Ты вот про это?
> public function setProperty($property, $value) {
Это вообще не очень хорошая вещь. Во-первых, она не проверяет имя поля и позволяет создать поле с любым именем. Во-вторых, она по большому счету нарушает инкапсуляцию. Потому что, если ты добавишь в сеттер setName() какую-то проверку, то она не будет вызвана в setProperty().
Зачем этот метод? Не думаю, что он нужен.
> У них там всё равно всё сделано через роутер, а я даже не знаю откуда они берут эту задачу чтобы делать через него,
Если погуглить по habr mvc php то там есть статья с роутером в ней. наверно оттуда.
> Еще у этого анона есть такие классы как от Request, Response - мне это тоже не понятно зачем они нужны.
Чтобы можно было представить запрос и ответ в виде объектов. Ну например, мы теперь можем сделать функцию, и указать что она принимает аргумент типа Request. Также, мы можем писать например $request->getQuery('x') вместо конструкции isset($_GET)...
Объект ответа Response может использоваться, чтобы получить результат обработки запроса (страницу со всеми заголовками) и что-то с ней сделать.
Это может использоваться например для тестирования (можно создать произвольный объект запроса, можно проанализировать получившийся ответ), а также какими-то промежуточными слоями, которые например берут ответ или запрос и что-то в нем заменяют до/после обработки приложением. Если ты будешь изучать фреймворк Slim , то там есть так назваемые middleware которые могут выполняться до/после обработки запроса.
> Раньше я думал, что контроллер отвечает за логику того или иного действия, а модель это, исходя из названий содержащихся в ней классов, всего лишь вспомогательные методы для него.
Не, не так. Модель отвечает за логику работы приложения, хранение и обработку данных. Вид отображает эти данные. Контроллер принимает запросы от пользователя, меняет данные (через Модель) и отображает результаты (с помощью Вида). Поэтому например мы можем сделать несколько Видов, которые работают с одной моделью и отображают одни и те же данные в разном виде. Или несколько Контроллеров, работающих с одной Моделью.
Ну например: пользователь заходит на страницу редактирования профиля. Контроллер определяет, залогинен ли он, запрашивает у модели информацию о нем и просит Вид отобразить форму с введенными данными.
Условно говоря, модель - это "ядро" приложения, без интерфейса, но со всей нужной внутренней логикой. То есть имея модель, ты всегда можешь в пару строчек получить или изменить какие-то данные в базе. Или проверить данные.
> Ведь как может отвечать за всю логику лишь Помощник?
Ну иногда такие классы называют Сервис, иногда Хелпер.
> Валидатор тоже не может отвечать за всю логику.
Валидатор это как раз часть модели. Он знает как проверять данные.
> Класс с работой с БД - тоже.
Это тоже часть модели, отвечающая за загрузку данных из БД и сохранение в БД.
> Это сбивает с толку. Так почему в Модели, которая отвечает за логику, за внутреннее состояние программы, мы не содержим классы как AuthModel или просто Auth(orization)?
Потому что авторизация реализована полностью в интерфейсе. У нас ведь авторизация делается установкой кук, которые хранятся в браузере пользователя. Модель о браузере и HTTP-запросах (а куки это часть HTTP) ничего не знает.
Вот если бы у тебя хранился например где-то в базе список залогиненных в данный момент пользователей - тогда Модель бы отвечала за него. Но установкой и проверкой кук она не должна заниматься. Это часть интерфейса между приложением и пользователем, а модель не отвечает за интерфейс пользователя. Ну например, когда мы запускаем консольную программу, никаких кук в консоли нет.
Хотя.... при желании тут конечно можно как-то извернуться и объявить Модель ответственной за залогинивание/разлогинивание ... но мне кажется, это будет искажение идеи MVC.
>>Но третья-то зачем?
> Так токен же, для csrf протекции.
> Я тоже сомневался стоит ли её создавать и при регистрации.
Я бы не привязывал защиту CSRF к авторизации. По идее они никак не связаны, ведь формы могут быть доступны и для неавторизованных пользователей. И я не вижу никакой выгоды тут, зачем привязывать генерацию CSRF токена к регистрации, если можно это не делать?
> $spl[$place] вернет NULL. Ты наверно хотел написать $spl[$student] вместо этого?
Да, ошибся.
>>Это значит, что в SplOS можно заносить объекты, не привязывая к ним данные.
> О каких данных здесь может быть речь?
Имеется в виду, что можно писать так:
$s = new SplObjectStorage();
$s[$object] =1; // добавляем элемент с ключом и значением
А можно и так, добавляя только ключ без значения (если нам нужен просто список объектов и не надо к ним привязывать никакие данные):
$s->attach($object);
>>804818
В общем, да, правильно
>>804829
Вот тут есть немного: https://github.com/codedokode/pasta/blob/master/student-list.md#mvc
>>805203
Не знаю, можно ли меня считать "шарящим", но я тут подумал, что надо будет написать урок по MVC. А то действительно, много непонимания.
Там главная суть в отделении модели, хранящей и управляющей данными, от их отображения и от обработчиков действий пользователя. Кроме организации кода, мы получаем возможность например использовать одну модель с разными вью или разными контроллерами.
>>805354
А, что-то я этот пост потерял и не ответил сразу.
> Но тогда всё равно же придётся искать метод который предоставляем наружу. Если мы поменяем внутреннюю логику метода так, что он будет возвращать свершено другой результат, например заместо строки массив, то метод который мы предоставляем наружу, тоже нужно будет поменять, и для этого нужно так же искать где он вызывается.
Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
> Я перечитал твой мануал по инкапсуляции и могу сказать, что она нужно скорее чтобы скрывать внутреннюю логику, а не облегчение её редактирования.
Да, это помогает например понять как использовать класс - тебе достаточно лишь посмотреть на публичные методы, а не изучать весь код класса.
> Так же, мне теперь кажется, что я зря в некоторых сущностях делал свойства закрытыми, ведь при работе с ними нет никакой внутренней логики, мы просто их меняем. И чтобы их не поменяли на неверное значение есть класс валидации.
Ну это пока. На практике логика может появиться в любой момент. Например, при задании одного поля надо менять значение другого поля. И здесь отсутствие инкапсуляции может помешать. В большом и сложном проекте переделать поля на методы будет непросто (если только не использовать магические методы), потому некоторые советуют с самого начала делать все через сеттеры и геттеры. Но так конечно код получается объемнее.
Что касается валидации, то это не совсем то, что нужно. Ведь неверное значение может ставиться в одном месте кода, а валидация - делаться в совсем другом (или вообще не делаться). Валидация - она обычно используется для проверки данных от пользователя.
> Я не могу вспомнить как я научился такому методу. У тебя случайно не было так написано в уроке по DI? Так вообще делают?
Ты вот про это?
> public function setProperty($property, $value) {
Это вообще не очень хорошая вещь. Во-первых, она не проверяет имя поля и позволяет создать поле с любым именем. Во-вторых, она по большому счету нарушает инкапсуляцию. Потому что, если ты добавишь в сеттер setName() какую-то проверку, то она не будет вызвана в setProperty().
Зачем этот метод? Не думаю, что он нужен.
> У них там всё равно всё сделано через роутер, а я даже не знаю откуда они берут эту задачу чтобы делать через него,
Если погуглить по habr mvc php то там есть статья с роутером в ней. наверно оттуда.
> Еще у этого анона есть такие классы как от Request, Response - мне это тоже не понятно зачем они нужны.
Чтобы можно было представить запрос и ответ в виде объектов. Ну например, мы теперь можем сделать функцию, и указать что она принимает аргумент типа Request. Также, мы можем писать например $request->getQuery('x') вместо конструкции isset($_GET)...
Объект ответа Response может использоваться, чтобы получить результат обработки запроса (страницу со всеми заголовками) и что-то с ней сделать.
Это может использоваться например для тестирования (можно создать произвольный объект запроса, можно проанализировать получившийся ответ), а также какими-то промежуточными слоями, которые например берут ответ или запрос и что-то в нем заменяют до/после обработки приложением. Если ты будешь изучать фреймворк Slim , то там есть так назваемые middleware которые могут выполняться до/после обработки запроса.
> Раньше я думал, что контроллер отвечает за логику того или иного действия, а модель это, исходя из названий содержащихся в ней классов, всего лишь вспомогательные методы для него.
Не, не так. Модель отвечает за логику работы приложения, хранение и обработку данных. Вид отображает эти данные. Контроллер принимает запросы от пользователя, меняет данные (через Модель) и отображает результаты (с помощью Вида). Поэтому например мы можем сделать несколько Видов, которые работают с одной моделью и отображают одни и те же данные в разном виде. Или несколько Контроллеров, работающих с одной Моделью.
Ну например: пользователь заходит на страницу редактирования профиля. Контроллер определяет, залогинен ли он, запрашивает у модели информацию о нем и просит Вид отобразить форму с введенными данными.
Условно говоря, модель - это "ядро" приложения, без интерфейса, но со всей нужной внутренней логикой. То есть имея модель, ты всегда можешь в пару строчек получить или изменить какие-то данные в базе. Или проверить данные.
> Ведь как может отвечать за всю логику лишь Помощник?
Ну иногда такие классы называют Сервис, иногда Хелпер.
> Валидатор тоже не может отвечать за всю логику.
Валидатор это как раз часть модели. Он знает как проверять данные.
> Класс с работой с БД - тоже.
Это тоже часть модели, отвечающая за загрузку данных из БД и сохранение в БД.
> Это сбивает с толку. Так почему в Модели, которая отвечает за логику, за внутреннее состояние программы, мы не содержим классы как AuthModel или просто Auth(orization)?
Потому что авторизация реализована полностью в интерфейсе. У нас ведь авторизация делается установкой кук, которые хранятся в браузере пользователя. Модель о браузере и HTTP-запросах (а куки это часть HTTP) ничего не знает.
Вот если бы у тебя хранился например где-то в базе список залогиненных в данный момент пользователей - тогда Модель бы отвечала за него. Но установкой и проверкой кук она не должна заниматься. Это часть интерфейса между приложением и пользователем, а модель не отвечает за интерфейс пользователя. Ну например, когда мы запускаем консольную программу, никаких кук в консоли нет.
Хотя.... при желании тут конечно можно как-то извернуться и объявить Модель ответственной за залогинивание/разлогинивание ... но мне кажется, это будет искажение идеи MVC.
>>Но третья-то зачем?
> Так токен же, для csrf протекции.
> Я тоже сомневался стоит ли её создавать и при регистрации.
Я бы не привязывал защиту CSRF к авторизации. По идее они никак не связаны, ведь формы могут быть доступны и для неавторизованных пользователей. И я не вижу никакой выгоды тут, зачем привязывать генерацию CSRF токена к регистрации, если можно это не делать?
> $spl[$place] вернет NULL. Ты наверно хотел написать $spl[$student] вместо этого?
Да, ошибся.
>>Это значит, что в SplOS можно заносить объекты, не привязывая к ним данные.
> О каких данных здесь может быть речь?
Имеется в виду, что можно писать так:
$s = new SplObjectStorage();
$s[$object] =1; // добавляем элемент с ключом и значением
А можно и так, добавляя только ключ без значения (если нам нужен просто список объектов и не надо к ним привязывать никакие данные):
$s->attach($object);
Либо использовать цикл по массиву папок, либо увлечься ООП и собрать итератор по массиву рекурсивных итераторов из стандартных классов.
>>806205
Отличается тем что другой язык, другие библиотеки, фреймворки итд.
>>806632
Интересная статья. Но надо помнить, что объекты-сущности (состоящие на 90% из геттеров-сеттеров) и сервисы для работы с ними появлились не просто так. Если перенести логику в модели доменной области, то мы получим кучу проблем, например:
- нам придется использовать DI и передавать в конструктор модели другие классы, что часто не совместимо с ORM библиотеками (они обычно требуют пустой конструктор у модели)
- мы може получить что-то напоминающее Active Record, если перенесем операции работы с БД в модель
- мы можем нарушить принцип "единой отвественности" и назначить классу модели много задач
Статья Фаулера, к сожалению, не приводит каких-то примеров c толстыми моделями и тонкими простыми сервисами, координирующими их работу. Может ты, раз тебе так нравится эта статья, можешь придумать пример?
Ну вот возьмем такую простую вещь, как валидацию. Должны ли мы внести код валидации в модели? Должны ли мы сделать Валидатор и инъектировать его в модель через конструктор? Или более сложный процесс регистрации, который например включает в себя валидацию, вставку нескольких сущностей в БД, обновление статистики, отправку письма?
>>806663
В composer.json указывается имя класса и метод. Ты можешь либо сделать класс в общей папке (например с именем Composer\PostInstallHandler) либо сделать отдельную папку scripts и добавить ее в автозагрузку в composer.json. Там ведь можно несколько папок и префиксов указать. И даже отдельные файлы перечислить (хотя это уже не PSR-4 будет).
>>806665
для деплоя то есть выгрузки изменений в коде на сервер. Или для разворачивания проекта после скачивания.
>>806701
- не пиши по 2 команды в одной строке и освой стандарт оформления кода PSR
- давай переменным более понятные имена ($k)
- отучайся от исплоьзования str-функций, не поддерживающих кирилицу
- $i <= strlen($phone)-1; тут лучше использовать знак "меньше" без "равно"
- if (($k > 2) && ($k % 3) == 0) -> if ($k == 3)
- правила форматирования конечно странные. Красивее было бы, если остается 4 цифры, делать 2 блока по 2.
>>806710
> 1) https://ideone.com/4gty5H Приведение номера к единому формату.
Лучше было бы сделать массив номеров и проверять все номера, которые даны в учебнике. На вид, вроде правильно.
> 2) https://ideone.com/tZI7Fp Автозамена слова "Дурак".
Заменяет слово "ааааа", а не должно.
> 3) https://ideone.com/L7JdaE Вывод e-mail'ов.
Не находит 07fiANUSexamplePUNCTUMcoDHvm
> 4) https://ideone.com/qKlxkQ «Grammar Nazi» с автоматическим исправлением.
По этой задаче я вроде где-то выше уже писал, что там "а/но" обрабатываются неточно и дают ошибку в предложении вроде "Хорошо. Но не очень". Также пытается добавлять пробел в самый конец текста.
> 5) https://ideone.com/LoFKwm «Опечаточники»
Не все латинские буквы указаны, и программа считает полностью латинские слова ошибкой, а это не так. Надо искать слова со смешанными алфавитом.
> 1) https://ideone.com/0HTZhW Задачка "Клавиша shift"
слишком сокращаешь названия переменных, $arr - ничего не значит, лучше $sentences. Тут https://ideone.com/6PX5Mp не удаляются лишние пробелы после знаков препинания (или это и не требуется? вроде требуется).
> 2) https://ideone.com/P8euld "Yoda Speak"
> $reverseSent = implode(" ", array_reverse(preg_split("/[ ]/u" , $sent, 0, PREG_SPLIT_NO_EMPTY)));
Длинновато, лучше на 2 команды такое разбивать.
В остальном, верно.
> 3) https://ideone.com/AO9sGB "Калькулятор"
> $number = 0;
Можно наверно не повторять это несколько раз?
решено верно.
Либо использовать цикл по массиву папок, либо увлечься ООП и собрать итератор по массиву рекурсивных итераторов из стандартных классов.
>>806205
Отличается тем что другой язык, другие библиотеки, фреймворки итд.
>>806632
Интересная статья. Но надо помнить, что объекты-сущности (состоящие на 90% из геттеров-сеттеров) и сервисы для работы с ними появлились не просто так. Если перенести логику в модели доменной области, то мы получим кучу проблем, например:
- нам придется использовать DI и передавать в конструктор модели другие классы, что часто не совместимо с ORM библиотеками (они обычно требуют пустой конструктор у модели)
- мы може получить что-то напоминающее Active Record, если перенесем операции работы с БД в модель
- мы можем нарушить принцип "единой отвественности" и назначить классу модели много задач
Статья Фаулера, к сожалению, не приводит каких-то примеров c толстыми моделями и тонкими простыми сервисами, координирующими их работу. Может ты, раз тебе так нравится эта статья, можешь придумать пример?
Ну вот возьмем такую простую вещь, как валидацию. Должны ли мы внести код валидации в модели? Должны ли мы сделать Валидатор и инъектировать его в модель через конструктор? Или более сложный процесс регистрации, который например включает в себя валидацию, вставку нескольких сущностей в БД, обновление статистики, отправку письма?
>>806663
В composer.json указывается имя класса и метод. Ты можешь либо сделать класс в общей папке (например с именем Composer\PostInstallHandler) либо сделать отдельную папку scripts и добавить ее в автозагрузку в composer.json. Там ведь можно несколько папок и префиксов указать. И даже отдельные файлы перечислить (хотя это уже не PSR-4 будет).
>>806665
для деплоя то есть выгрузки изменений в коде на сервер. Или для разворачивания проекта после скачивания.
>>806701
- не пиши по 2 команды в одной строке и освой стандарт оформления кода PSR
- давай переменным более понятные имена ($k)
- отучайся от исплоьзования str-функций, не поддерживающих кирилицу
- $i <= strlen($phone)-1; тут лучше использовать знак "меньше" без "равно"
- if (($k > 2) && ($k % 3) == 0) -> if ($k == 3)
- правила форматирования конечно странные. Красивее было бы, если остается 4 цифры, делать 2 блока по 2.
>>806710
> 1) https://ideone.com/4gty5H Приведение номера к единому формату.
Лучше было бы сделать массив номеров и проверять все номера, которые даны в учебнике. На вид, вроде правильно.
> 2) https://ideone.com/tZI7Fp Автозамена слова "Дурак".
Заменяет слово "ааааа", а не должно.
> 3) https://ideone.com/L7JdaE Вывод e-mail'ов.
Не находит 07fiANUSexamplePUNCTUMcoDHvm
> 4) https://ideone.com/qKlxkQ «Grammar Nazi» с автоматическим исправлением.
По этой задаче я вроде где-то выше уже писал, что там "а/но" обрабатываются неточно и дают ошибку в предложении вроде "Хорошо. Но не очень". Также пытается добавлять пробел в самый конец текста.
> 5) https://ideone.com/LoFKwm «Опечаточники»
Не все латинские буквы указаны, и программа считает полностью латинские слова ошибкой, а это не так. Надо искать слова со смешанными алфавитом.
> 1) https://ideone.com/0HTZhW Задачка "Клавиша shift"
слишком сокращаешь названия переменных, $arr - ничего не значит, лучше $sentences. Тут https://ideone.com/6PX5Mp не удаляются лишние пробелы после знаков препинания (или это и не требуется? вроде требуется).
> 2) https://ideone.com/P8euld "Yoda Speak"
> $reverseSent = implode(" ", array_reverse(preg_split("/[ ]/u" , $sent, 0, PREG_SPLIT_NO_EMPTY)));
Длинновато, лучше на 2 команды такое разбивать.
В остальном, верно.
> 3) https://ideone.com/AO9sGB "Калькулятор"
> $number = 0;
Можно наверно не повторять это несколько раз?
решено верно.
Погугли "задача банкомат", "задача о размене", "задача о рюкзаке". Это частный случай задачи о рюкзаке (ранце).
>>806883
> //Удаляем купюры количество которых равно 0
Это наверно лишнее - алгоритм и с нулями должен по идее нормально работать. Проверку на отутствие денег можно сделать и через array_sum.
> $count = ($preCount < $quantity) ? $preCount : $quantity;
Это лучше записать через min()/max()
Сам алгоритм ("жадный" алгоритм) верный.
>>806913
codedokode (あ) gmail.com - но лучше конечно в треде писать, если этот вопрос интересен и другим анонам
Задачи по HTML
https://jsfiddle.net/czeo0c8n/
Верно
https://jsfiddle.net/9ygm244j/
Перечитай про боксовую модель: https://developer.mozilla.org/ru/docs/Web/CSS/box_model или http://htmlbook.ru/samlayout/blochnaya-verstka/blochnaya-model
Ты забыл что width задает не внешнюю ширину, а внутреннюю.
https://jsfiddle.net/16m3g5ta/1/
Ок, верно.
https://jsfiddle.net/211Le60v/5/
> .container {
> padding: 10px;
> font-size: 0px;
> display:table;
не понял, зачем это? Зачм таблица без table-row или table-cell? Также не понял, зачем ты таблице ставишь паддинг, который есть только у ее ячеек. Это какой-то хак для решения проблемы пробелов? Стоило тогда добавить комментарий, а то совсем неочевидно. Ну и конечно изучи и другие методы борьбы.
А так, верно.
https://jsfiddle.net/h3cez9f7/1/
С желтым ты конечно перестарался - у меня надо еще голову повернуть так, чтобы надпись стала заметной. Но идея в общем верная.
> >Ширина меню навигации 200px
> А это не слишком много? В шаблоне на картинке она в 3 раза меньше бокса с контентом.
Картинка не в масштабе.
https://jsfiddle.net/L5orb28e/3/
А вот тут многовато ошибок:
- li { margin: 5px 0px; } меняет стиль всех элементов списков, а на странице могут быть и другие списки. Надо ставить стили точечно, чтобы это применялось только к меню. То же относится к ul, nav
- ты жестко прописал размеры body. Это не годится. Верстка должна растягиваться под ширину страницы.
- font-family: 'Trebuchet MS'; - надо указывать в конце списка один из встроенных шрифтов (вроде sans-serif)
- h1 должен быть не жирным
- article { width: 230px; } - статья должна занимать всю оставшуюся ширину, а не 230px
- nav:after {} - он тут не нужен. Он применяется к не-float элементам, которые содержат внутри float элементы. А у тебя nav и так float и ему clearfix не нужен.
https://jsfiddle.net/5g31m30j/1/
Высота кнопки и поля ввода не совпадают. Ты учел что кнопки и поля ввода по умолчанию имеют разный box-sizing, для одного задается внутреняя высота, для другого - внешняя. надо либо менять box-sizing либо пересчитывать высоту с учетом этого. Читай подсказки (хотя бы после того как решил).
Ну и на практике стили вроде input {...} будут конфликтовать с другими инпутами на странице - лучше применять стили более точечно.
> А можно подсказку как сделать чтобы примечание не растягивала контейнер в котором оно содержится? У меня пока получилось только так
float не растягивает родительский контейнер (а также position: absolute) так как вырывается из потока.
- body { width: 330px; } - не годится, давай верстать резиново под любую ширину, а не прописывать жестко ширину страницы.
- p { margin-left: auto; max-width: 200px; } - это применяется только к абзацам, а что если в тексте заголовоки, таблицы, списки, картинки? Читай подсказки
- aside {vertical-align: bottom; } - свойство vertical-align работает только для элементов с display: inline-block, inline, table-cell. К блокам оно неприменимо.
Увы, эта задача решена совсем неправильно. Надо переделвать. Добавь в текст заголовки и списки и больше примечаний.
https://jsfiddle.net/kxdx27f1/2/
- Текст не должен затекать под желтый блок слева.
- div {} - будет применяться ко всем дивам на странице, плохо, сломает верстку. Верстать надо так, чтобы твою верстку можно было вставить на любую страницу и не было никаких конфликтов.
> А что это за атрибут такой в <em data-ref="1">?
Это data атрибуты, которые можно использовать для своих целей: https://www.google.ru/search?q=data+атрибуты&newwindow=1&gbv=1&sei=LcqmV8rTPIujsgGvr4TYAw
> Можно подсказку как слева на строке у элемента с этим атрибутом сделать те цифры в квадратных скобках?
Можно: генерируемый контент https://www.google.ru/search?q=генерируемый+контент+css&newwindow=1&gbv=1&sei=asqmV436JYSbsgGpo4_gAw
Например http://htmlbook.ru/css/content
> И можно еще подсказку как сделать <figcaption> внизу картинки? Очевидно, сначала нужно использовать position: absolute, но как сделать чтобы элемент был внизу? Неужели задавать координаты с помощью top, left, ...?
Элементарно: абсолютно позиционировать подпись относительно блока с картинкой, которому назначить относ. позиц. Это как раз пример когда абс. поз. уместно. Почитай про свойства top, left, right, bottom - их можно использовать в разных сочетаниях.
Тут немного сложная часть - как сделать ограничение ширины картинки. Придется повозиться с width/max-width.
https://jsfiddle.net/fp8o0exq/4/
- между кнопками должна быть линия в 1px а не 2 пикселя
- кнопки высоковаты
- body { font-size: 0px; display: table; } - это не позволяет вставить твой блок на произвольную страницу. мы ведь не будем там сбрасывать шрифт на body.
- "inputbox left" - это неудобно, подписывать каждый блок. И что если у нас не 3, а больше кнопок? переписывать CSS? Нужно более универсальное решение. Есть же :first-child например. Погугли "css псевдоклассы"
- для анимации наверно лучше бы подошло более простое правило transition - изучи его. Или нет?
Задачи по HTML
https://jsfiddle.net/czeo0c8n/
Верно
https://jsfiddle.net/9ygm244j/
Перечитай про боксовую модель: https://developer.mozilla.org/ru/docs/Web/CSS/box_model или http://htmlbook.ru/samlayout/blochnaya-verstka/blochnaya-model
Ты забыл что width задает не внешнюю ширину, а внутреннюю.
https://jsfiddle.net/16m3g5ta/1/
Ок, верно.
https://jsfiddle.net/211Le60v/5/
> .container {
> padding: 10px;
> font-size: 0px;
> display:table;
не понял, зачем это? Зачм таблица без table-row или table-cell? Также не понял, зачем ты таблице ставишь паддинг, который есть только у ее ячеек. Это какой-то хак для решения проблемы пробелов? Стоило тогда добавить комментарий, а то совсем неочевидно. Ну и конечно изучи и другие методы борьбы.
А так, верно.
https://jsfiddle.net/h3cez9f7/1/
С желтым ты конечно перестарался - у меня надо еще голову повернуть так, чтобы надпись стала заметной. Но идея в общем верная.
> >Ширина меню навигации 200px
> А это не слишком много? В шаблоне на картинке она в 3 раза меньше бокса с контентом.
Картинка не в масштабе.
https://jsfiddle.net/L5orb28e/3/
А вот тут многовато ошибок:
- li { margin: 5px 0px; } меняет стиль всех элементов списков, а на странице могут быть и другие списки. Надо ставить стили точечно, чтобы это применялось только к меню. То же относится к ul, nav
- ты жестко прописал размеры body. Это не годится. Верстка должна растягиваться под ширину страницы.
- font-family: 'Trebuchet MS'; - надо указывать в конце списка один из встроенных шрифтов (вроде sans-serif)
- h1 должен быть не жирным
- article { width: 230px; } - статья должна занимать всю оставшуюся ширину, а не 230px
- nav:after {} - он тут не нужен. Он применяется к не-float элементам, которые содержат внутри float элементы. А у тебя nav и так float и ему clearfix не нужен.
https://jsfiddle.net/5g31m30j/1/
Высота кнопки и поля ввода не совпадают. Ты учел что кнопки и поля ввода по умолчанию имеют разный box-sizing, для одного задается внутреняя высота, для другого - внешняя. надо либо менять box-sizing либо пересчитывать высоту с учетом этого. Читай подсказки (хотя бы после того как решил).
Ну и на практике стили вроде input {...} будут конфликтовать с другими инпутами на странице - лучше применять стили более точечно.
> А можно подсказку как сделать чтобы примечание не растягивала контейнер в котором оно содержится? У меня пока получилось только так
float не растягивает родительский контейнер (а также position: absolute) так как вырывается из потока.
- body { width: 330px; } - не годится, давай верстать резиново под любую ширину, а не прописывать жестко ширину страницы.
- p { margin-left: auto; max-width: 200px; } - это применяется только к абзацам, а что если в тексте заголовоки, таблицы, списки, картинки? Читай подсказки
- aside {vertical-align: bottom; } - свойство vertical-align работает только для элементов с display: inline-block, inline, table-cell. К блокам оно неприменимо.
Увы, эта задача решена совсем неправильно. Надо переделвать. Добавь в текст заголовки и списки и больше примечаний.
https://jsfiddle.net/kxdx27f1/2/
- Текст не должен затекать под желтый блок слева.
- div {} - будет применяться ко всем дивам на странице, плохо, сломает верстку. Верстать надо так, чтобы твою верстку можно было вставить на любую страницу и не было никаких конфликтов.
> А что это за атрибут такой в <em data-ref="1">?
Это data атрибуты, которые можно использовать для своих целей: https://www.google.ru/search?q=data+атрибуты&newwindow=1&gbv=1&sei=LcqmV8rTPIujsgGvr4TYAw
> Можно подсказку как слева на строке у элемента с этим атрибутом сделать те цифры в квадратных скобках?
Можно: генерируемый контент https://www.google.ru/search?q=генерируемый+контент+css&newwindow=1&gbv=1&sei=asqmV436JYSbsgGpo4_gAw
Например http://htmlbook.ru/css/content
> И можно еще подсказку как сделать <figcaption> внизу картинки? Очевидно, сначала нужно использовать position: absolute, но как сделать чтобы элемент был внизу? Неужели задавать координаты с помощью top, left, ...?
Элементарно: абсолютно позиционировать подпись относительно блока с картинкой, которому назначить относ. позиц. Это как раз пример когда абс. поз. уместно. Почитай про свойства top, left, right, bottom - их можно использовать в разных сочетаниях.
Тут немного сложная часть - как сделать ограничение ширины картинки. Придется повозиться с width/max-width.
https://jsfiddle.net/fp8o0exq/4/
- между кнопками должна быть линия в 1px а не 2 пикселя
- кнопки высоковаты
- body { font-size: 0px; display: table; } - это не позволяет вставить твой блок на произвольную страницу. мы ведь не будем там сбрасывать шрифт на body.
- "inputbox left" - это неудобно, подписывать каждый блок. И что если у нас не 3, а больше кнопок? переписывать CSS? Нужно более универсальное решение. Есть же :first-child например. Погугли "css псевдоклассы"
- для анимации наверно лучше бы подошло более простое правило transition - изучи его. Или нет?
> Как на глаз определить тень и шрифт?
Для начала, надо попробовать определить радиус тени (на котором она плавно переходит в прозрачность). Если присмотреться, то видно что на картинке тень несимметричная: она большая сверху, маленькая снизу и равная по сторонам. Значит, тень смещена вниз, а справа или слева ее ширина. По ней мы подбираем радиус (будет примерно пикселя 3 я думаю). подобрав радиус, подбираем прозрачность черного, чтобы с краев тень совпадала по прозрачности с картинкой.
Ну и напоследок подбираем вертикальное смещение тени, просто на глаз двигая тень вниз.
Если ты не понимаешь некоторые термины, то изучи какие есть параметры у теней. Заметь что для внутренних (inset) теней одним параметром меньше.
Шрифт -какой-то из стандартных. Погугли какие распространенные шрифты есть, по моему тут Arial.
Также, как насчет клавиатурной навигации?
> А почему ты выбрал именно наклонный текст? Лучше же span взять - он не меняет стиля текста.
Короче пишется. Лучше конечно span.
> Я пока не знаю javascript, можно я доделаю это позже? Можно пока подсказку как сделать чтобы в старых браузерах просто выводился набор чекбоксов?
Гм... тут надо использовать в селекторе CSS правила которые не понимают старые браузеры (напрмер какие-то псевдоклассы из CSS3). То есть условно говоря, если старый браузер не понимает n-th-child() то мы можем записать так:
.inputbox { правила для старых браузеров }
.inputbox:n-th-child(...) { переопределяем правило для новых }
Насчет яваскрипта - проблема старых браузеров в том, что они не поддерживают :checked. И потому в них при клике не будет меняться подсветка кнопок. Для решения надо повесить на радиокнопки обработчик событий и при перекоючении добавлять какой-то CSS класс на нажатую кнопку.
Можно пока без яваскрипта. Протестировать можно например тут если это еще бесплатно: http://browsershots.org/ или https://www.browserstack.com/screenshots или https://developer.microsoft.com/en-us/microsoft-edge/tools/screenshots/
> Я забыл про этот пункт пока делал задание, можем мы это опустить? В "боевых" задачах я естественно так не буду делать.
Лучше бы конечно с самого начала учиться делать правильно. Да и вроде у тебя в этой задаче проблем с этим нет, все за классами скрыто.
> Я сначала подумал, что ты ошибся насчет :active, что надо было :checked за место этого. Нужно еще и :active делать? Какой у неё должен стиль? Как у :checked?
:active вроде значит "вжатое" состояие чекбокса в момент нажатия. Это если ты хочешь чтобы в момент нажатия он как-то подсвечивался или был более темным например.
> А можно еще подсказку как и это сделать?
Для начала сделай просто список радиокнопок с подписями но без стилизации и поэкспериментируй с клавиатурой. Потом изучи псевдокласс :focus
Скрыть чекбокс можно и не через display: none, а например: через visibility: hidden, через overflow:hidden c задвижением за край видимой области, через абс. поз. за край видимой области (left: -10000px) - но тут есть свои недостатки. Ты кстати должен знать эти варианты.
> https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
> А нужно прям точь в точь как шаблоне делать стили?
нет. точно так же не нужно. можно по-своему.
>>старайся не использовать id в верстке так как с ними не получится вывести на странице несколько блоков вкладок. Разрешается использовать классы или data-атрибуты для связи вкладок и заголовков.
> Это касается даже при использовании for у лейблов?
Тут надо смотреть, насколько это сложно реализовать. Если без id обойтись очень сложно и будут проблемы - значит, придется их использовать. Если же можно без особых проблем обойтись - то хорошо бы обойтись. То есть надо взвешивать плюсы и минусы.
В твоем случае эти id прописаны в css. Значит, если мы хотим на странице несколько блоков с вкладками, нам нужно каждому дать уникальный id и еще прописать его в css. Это непрактично если у нас страница генерируется динамически и мы не знаем сколько будет блоков на странице.
Хорошо бы хотя бы от id в CSS избавиться, хотя бы через data атрибуты
Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
Вообще, без уникальных id видимо можно обойтись только если верстать в таком подрядке:
- заголовок
- контент
- заголовок
- контент
Этот вариант еще интересен тем, что на старых браузерах (а также на устройствах с узким экраном! адаптивность!) его можно разверстать через теги вроде h3 как текст с подзаголовками. Но тогда мы не сможем переносить заголовки на новую строку если их слишком много (хотя... может флексбокс нам поможет? изучи-ка вопрос). Посмотри, в общем, какие есть варианты и какие у них недостатки.
> Как тогда реализовать переключение вкладок, если вкладывать элементы уже во внутрь лейбла? Не получиться обращаться к соседним или родственным элементам, потому что сначала нужно проверить на :checked у input.
Можно кстати идентифицировать вкладки и не по id, а например по data-атрибутам: <input data-tab="tab1">. Это тоже требует униакльности, но только в рамкх одного блока вкладок.
> #first-tab:checked + .tab-label[for="first-tab"] + #second-tab + .tab-label[for="second-tab"] + #third-tab + .tab-label[for="third-tab"] + #fourth-tab + .tab-label[for="fourth-tab"]
В новых браузерах есть селектор ~. Нагугли и прочитай про все новые псевдоклассы и селекторы из CSS3. В старых браузерах он правда не работает, для них можно наверно просто вкладки вертикально вывести как блоки.
Есть еще такая проблема: активная вкладка при наведении мыши становится серой - мне кажется это неправильно.
Здесь есть статья на англ. по теме: http://alistapart.com/article/radio-controlled-web-design и пример вкладок который поддерживает в том числе работу с клавиатурой: http://codepen.io/artlawry/pen/gbLev/ и такой: https://codepen.io/wallaceerick/pen/ojtal
> Это касается даже при использовании for у лейблов? Как тогда реализовать переключение вкладок, если вкладывать элементы уже во внутрь лейбла?
да, проблема. Но может мы хотя бы можем убрать жестко прописанные id из CSS?
>>сверстай блок так, чтобы блок с вкладками можно было вложить в страницу блока вкладок
> Нужно чтобы можно было скопировать вкладки в контентную страницу? Может лучше чтобы в контентной странице был свой элемент со вкладками?
да, чтобы внутри мог быть свой блок с вкладками и он не конфликтовал с родительским.
> Как на глаз определить тень и шрифт?
Для начала, надо попробовать определить радиус тени (на котором она плавно переходит в прозрачность). Если присмотреться, то видно что на картинке тень несимметричная: она большая сверху, маленькая снизу и равная по сторонам. Значит, тень смещена вниз, а справа или слева ее ширина. По ней мы подбираем радиус (будет примерно пикселя 3 я думаю). подобрав радиус, подбираем прозрачность черного, чтобы с краев тень совпадала по прозрачности с картинкой.
Ну и напоследок подбираем вертикальное смещение тени, просто на глаз двигая тень вниз.
Если ты не понимаешь некоторые термины, то изучи какие есть параметры у теней. Заметь что для внутренних (inset) теней одним параметром меньше.
Шрифт -какой-то из стандартных. Погугли какие распространенные шрифты есть, по моему тут Arial.
Также, как насчет клавиатурной навигации?
> А почему ты выбрал именно наклонный текст? Лучше же span взять - он не меняет стиля текста.
Короче пишется. Лучше конечно span.
> Я пока не знаю javascript, можно я доделаю это позже? Можно пока подсказку как сделать чтобы в старых браузерах просто выводился набор чекбоксов?
Гм... тут надо использовать в селекторе CSS правила которые не понимают старые браузеры (напрмер какие-то псевдоклассы из CSS3). То есть условно говоря, если старый браузер не понимает n-th-child() то мы можем записать так:
.inputbox { правила для старых браузеров }
.inputbox:n-th-child(...) { переопределяем правило для новых }
Насчет яваскрипта - проблема старых браузеров в том, что они не поддерживают :checked. И потому в них при клике не будет меняться подсветка кнопок. Для решения надо повесить на радиокнопки обработчик событий и при перекоючении добавлять какой-то CSS класс на нажатую кнопку.
Можно пока без яваскрипта. Протестировать можно например тут если это еще бесплатно: http://browsershots.org/ или https://www.browserstack.com/screenshots или https://developer.microsoft.com/en-us/microsoft-edge/tools/screenshots/
> Я забыл про этот пункт пока делал задание, можем мы это опустить? В "боевых" задачах я естественно так не буду делать.
Лучше бы конечно с самого начала учиться делать правильно. Да и вроде у тебя в этой задаче проблем с этим нет, все за классами скрыто.
> Я сначала подумал, что ты ошибся насчет :active, что надо было :checked за место этого. Нужно еще и :active делать? Какой у неё должен стиль? Как у :checked?
:active вроде значит "вжатое" состояие чекбокса в момент нажатия. Это если ты хочешь чтобы в момент нажатия он как-то подсвечивался или был более темным например.
> А можно еще подсказку как и это сделать?
Для начала сделай просто список радиокнопок с подписями но без стилизации и поэкспериментируй с клавиатурой. Потом изучи псевдокласс :focus
Скрыть чекбокс можно и не через display: none, а например: через visibility: hidden, через overflow:hidden c задвижением за край видимой области, через абс. поз. за край видимой области (left: -10000px) - но тут есть свои недостатки. Ты кстати должен знать эти варианты.
> https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
> А нужно прям точь в точь как шаблоне делать стили?
нет. точно так же не нужно. можно по-своему.
>>старайся не использовать id в верстке так как с ними не получится вывести на странице несколько блоков вкладок. Разрешается использовать классы или data-атрибуты для связи вкладок и заголовков.
> Это касается даже при использовании for у лейблов?
Тут надо смотреть, насколько это сложно реализовать. Если без id обойтись очень сложно и будут проблемы - значит, придется их использовать. Если же можно без особых проблем обойтись - то хорошо бы обойтись. То есть надо взвешивать плюсы и минусы.
В твоем случае эти id прописаны в css. Значит, если мы хотим на странице несколько блоков с вкладками, нам нужно каждому дать уникальный id и еще прописать его в css. Это непрактично если у нас страница генерируется динамически и мы не знаем сколько будет блоков на странице.
Хорошо бы хотя бы от id в CSS избавиться, хотя бы через data атрибуты
Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
Вообще, без уникальных id видимо можно обойтись только если верстать в таком подрядке:
- заголовок
- контент
- заголовок
- контент
Этот вариант еще интересен тем, что на старых браузерах (а также на устройствах с узким экраном! адаптивность!) его можно разверстать через теги вроде h3 как текст с подзаголовками. Но тогда мы не сможем переносить заголовки на новую строку если их слишком много (хотя... может флексбокс нам поможет? изучи-ка вопрос). Посмотри, в общем, какие есть варианты и какие у них недостатки.
> Как тогда реализовать переключение вкладок, если вкладывать элементы уже во внутрь лейбла? Не получиться обращаться к соседним или родственным элементам, потому что сначала нужно проверить на :checked у input.
Можно кстати идентифицировать вкладки и не по id, а например по data-атрибутам: <input data-tab="tab1">. Это тоже требует униакльности, но только в рамкх одного блока вкладок.
> #first-tab:checked + .tab-label[for="first-tab"] + #second-tab + .tab-label[for="second-tab"] + #third-tab + .tab-label[for="third-tab"] + #fourth-tab + .tab-label[for="fourth-tab"]
В новых браузерах есть селектор ~. Нагугли и прочитай про все новые псевдоклассы и селекторы из CSS3. В старых браузерах он правда не работает, для них можно наверно просто вкладки вертикально вывести как блоки.
Есть еще такая проблема: активная вкладка при наведении мыши становится серой - мне кажется это неправильно.
Здесь есть статья на англ. по теме: http://alistapart.com/article/radio-controlled-web-design и пример вкладок который поддерживает в том числе работу с клавиатурой: http://codepen.io/artlawry/pen/gbLev/ и такой: https://codepen.io/wallaceerick/pen/ojtal
> Это касается даже при использовании for у лейблов? Как тогда реализовать переключение вкладок, если вкладывать элементы уже во внутрь лейбла?
да, проблема. Но может мы хотя бы можем убрать жестко прописанные id из CSS?
>>сверстай блок так, чтобы блок с вкладками можно было вложить в страницу блока вкладок
> Нужно чтобы можно было скопировать вкладки в контентную страницу? Может лучше чтобы в контентной странице был свой элемент со вкладками?
да, чтобы внутри мог быть свой блок с вкладками и он не конфликтовал с родительским.
Давайте перекатываться. Новый тред >>807538 (OP) Если забыл - напомните о себе там.
Не пишите тут больше.
Надо упрощать. Убрать оба контейнера. Убрать spacer так как в CSS есть маргины. Убрать <p>. Оставить только 2 дива.
Цвета ты не подобрал, ладно. Но зачем надобавлял кучу бордеров и сделал серый фон? Это совсем не соответствует картинке.
Далее, у тебя куча ошибок и бессмысленных стилей, которые ничего не делают. В решении задачи не должно быть ничего лишнего. Вот например:
> html {
> box-sizing:box-border;
зачем это?
> .container:after {
зачем это? Элемент :after все равно не отобразится без свойства content
>>811672
Будет плюсом конечно
>>811783
По моему опыту, sprintf все же аккуратнее, особенно когда в строку надо подставить не переменные, а выражения
>>813252
Опять, многовато дивов. Для этой задачи достаточно одного. Ну и надо все же делать ближе к тому, что изображено на картинке. От верстальщика обычно требуется сверстать так, как изображено на макете, а не как ему кажется лучше.
> html {
> box-sizing:box-border;
box-border - неправильное значение. И зачем тут это?
> min-height:200px;
Это в задаче не требовалось
> p1 {
Зачем придумывать свои теги? Как другим людям догадаться, что он значит? Не надо так.
>>813270
Лучше наверно новый Слим брать. Код можно почитать если любопытно или если непонятно как что-то работает.
>>814705
Набор информации о файле содержит самые разные значения и выгоднее их засунуть как JSON чем пытаться уложить в сложную реляционную модель. Выборки и поиск по этим значениям все равно делать не требуется.
>>814708
А что поделать.
Надо упрощать. Убрать оба контейнера. Убрать spacer так как в CSS есть маргины. Убрать <p>. Оставить только 2 дива.
Цвета ты не подобрал, ладно. Но зачем надобавлял кучу бордеров и сделал серый фон? Это совсем не соответствует картинке.
Далее, у тебя куча ошибок и бессмысленных стилей, которые ничего не делают. В решении задачи не должно быть ничего лишнего. Вот например:
> html {
> box-sizing:box-border;
зачем это?
> .container:after {
зачем это? Элемент :after все равно не отобразится без свойства content
>>811672
Будет плюсом конечно
>>811783
По моему опыту, sprintf все же аккуратнее, особенно когда в строку надо подставить не переменные, а выражения
>>813252
Опять, многовато дивов. Для этой задачи достаточно одного. Ну и надо все же делать ближе к тому, что изображено на картинке. От верстальщика обычно требуется сверстать так, как изображено на макете, а не как ему кажется лучше.
> html {
> box-sizing:box-border;
box-border - неправильное значение. И зачем тут это?
> min-height:200px;
Это в задаче не требовалось
> p1 {
Зачем придумывать свои теги? Как другим людям догадаться, что он значит? Не надо так.
>>813270
Лучше наверно новый Слим брать. Код можно почитать если любопытно или если непонятно как что-то работает.
>>814705
Набор информации о файле содержит самые разные значения и выгоднее их засунуть как JSON чем пытаться уложить в сложную реляционную модель. Выборки и поиск по этим значениям все равно делать не требуется.
>>814708
А что поделать.
> Как мне его обернуть теперь? Это статический класс должен быть принимающий в свойства целый массив и возвращающий конкретное значение (например длину видео).
Класс ничего не возвращает же. "Обернуть" это значит что-то врде такого:
$info = new MediaInfo($mediaInfoArray);
Либо
$info = new MediaInfo::fromArray($mediaInfoArray);
Если у тебя конструктор занят под что-то другое.
А уже в классе могут быть (а могут и не быть) например методы:
$info->isAudio();
$info->getLength();
$info->getPropertiesWithDescription();
Ну то есть ты должен подумать, что ты хочешь получить от этого класса, какие данные, в каком виде, и как сделать его удобным в использовании и понятным. Очевидно что без класса нам пришлось бы копаться в массиве, в котором могут отстуствовать любые поля и надо вспоминать где что хранится.
> Или же это класс со свойством fileInfo которое представлено в json формате, а методы делают тоже самое, что и в статическом варианте. В последнем случае желательно чтобы я сразу в объект файла запихивал свойство-класс работы с этим json, т.е. это должно делаться через FETCH_FUNC?
Вряд ли можно через PDO это сделать. Надо вручную выбрать нужное значение, раскодировать его и создать объект.
>>814725
Конечно делать, кто иначе данные раскодирует?
> Как мне его обернуть теперь? Это статический класс должен быть принимающий в свойства целый массив и возвращающий конкретное значение (например длину видео).
Класс ничего не возвращает же. "Обернуть" это значит что-то врде такого:
$info = new MediaInfo($mediaInfoArray);
Либо
$info = new MediaInfo::fromArray($mediaInfoArray);
Если у тебя конструктор занят под что-то другое.
А уже в классе могут быть (а могут и не быть) например методы:
$info->isAudio();
$info->getLength();
$info->getPropertiesWithDescription();
Ну то есть ты должен подумать, что ты хочешь получить от этого класса, какие данные, в каком виде, и как сделать его удобным в использовании и понятным. Очевидно что без класса нам пришлось бы копаться в массиве, в котором могут отстуствовать любые поля и надо вспоминать где что хранится.
> Или же это класс со свойством fileInfo которое представлено в json формате, а методы делают тоже самое, что и в статическом варианте. В последнем случае желательно чтобы я сразу в объект файла запихивал свойство-класс работы с этим json, т.е. это должно делаться через FETCH_FUNC?
Вряд ли можно через PDO это сделать. Надо вручную выбрать нужное значение, раскодировать его и создать объект.
>>814725
Конечно делать, кто иначе данные раскодирует?
Если я кого-то пропустил - напомните о себе в новом треде.
Вывод ссылки решается с помощью регулярных выражений?
Скорее всего нет. Там надо просто правильно исполользовать функцию экранирования из урока про ссылки.
Алсо мы уже в новом треде, лучше там задавать вопрос
>>815058
>Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
>>815058
>> public function setProperty($property, $value) {
>Это вообще не очень хорошая вещь. Во-первых, она не проверяет имя поля и позволяет создать поле с любым именем. Во-вторых, она по большому счету нарушает инкапсуляцию. Потому что, если ты добавишь в сеттер setName() какую-то проверку, то она не будет вызвана в setProperty().
У меня есть похожие методы на этот которые обращаются к полям не через сеттеры. Их тоже следует исправить?
>>815058
>Ну иногда такие классы называют Сервис, иногда Хелпер.
Тогда я бы предпочел иметь Сервисы (классы отвечающие за внутреннюю логику) и Хелперы (классы содержащие вспомогательные методы) в разных директориях. Это не критично если я буду пользоваться таким подходом?
По хорошему, мне, наверно, следует перенести логику из контролеров в сервисы.
https://github.com/someApprentice/Students/blob/master/app/Model/Gateway/StudentGateway.php#L10
Я решил не раздувать код и сделать сортировку или получение определенного количество записей прям в функции getAllStudents(), потому что у неё одинаковый запрос. Следует ли её переименовать в связи тем что она теперь может получать не всех студентов?
>$limit = 2147483647
В мануале по mysql сказано о том что если нужно получить все записи, то нужно указать какое-то большое число
https://dev.mysql.com/doc/refman/5.7/en/select.html
>To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
>SELECT * FROM tbl LIMIT 95,18446744073709551615;
Это действительно так? Бывают ли на практике такие ситуации что нужно получить количество записей большее чем позволяет максимальное значение int?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L22
Для борьбы с sql инъекциями, я решил что удобней будет делать проверку на разрешенные колонки в методе получения запроса, чем в методе выполнения этого запроса. Так ведь тоже можно?
https://github.com/codedokode/pasta/blob/master/security/sql-injection.md#Методы-борьбы
>if (!in_array($sort, $allowed)) {
> $sort = $allowed[0];
>}
А почему $allowed[0] возвращает найденное значение? Я в мануале не нашел чтобы описывался такой синтаксис, и у меня не получилось сделать так же в моем условии https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L35
https://github.com/someApprentice/Students/blob/master/app/Controller/IndexAction.php#L38-L53
https://github.com/someApprentice/Students/blob/master/app/Controller/SearchAction.php#L29-L44
Это ведь тоже копипаста, верно? Я только что подумал что это код можно вынести в отдельный методов родителя контроллеров. Скоро исправлю.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L55
Я помню как ты говорил, что методы можно делать статическими если всегда будут возвращать одно и то же значение и не имеют никаких зависимостей, но в этот метод передается и меняется класс Student. Не является ли это зависимостью?
Если мы инкапсулируем методы то не следует нам их сделать закрытыми?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L61
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L68
Как закрыть эти методы? Если я пытаюсь обратиться к ним в статическом методе через $this, то я получаю ошибку о том что обращаюсь не в контексте объекта.
>>815058
>Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
>>815058
>> public function setProperty($property, $value) {
>Это вообще не очень хорошая вещь. Во-первых, она не проверяет имя поля и позволяет создать поле с любым именем. Во-вторых, она по большому счету нарушает инкапсуляцию. Потому что, если ты добавишь в сеттер setName() какую-то проверку, то она не будет вызвана в setProperty().
У меня есть похожие методы на этот которые обращаются к полям не через сеттеры. Их тоже следует исправить?
>>815058
>Ну иногда такие классы называют Сервис, иногда Хелпер.
Тогда я бы предпочел иметь Сервисы (классы отвечающие за внутреннюю логику) и Хелперы (классы содержащие вспомогательные методы) в разных директориях. Это не критично если я буду пользоваться таким подходом?
По хорошему, мне, наверно, следует перенести логику из контролеров в сервисы.
https://github.com/someApprentice/Students/blob/master/app/Model/Gateway/StudentGateway.php#L10
Я решил не раздувать код и сделать сортировку или получение определенного количество записей прям в функции getAllStudents(), потому что у неё одинаковый запрос. Следует ли её переименовать в связи тем что она теперь может получать не всех студентов?
>$limit = 2147483647
В мануале по mysql сказано о том что если нужно получить все записи, то нужно указать какое-то большое число
https://dev.mysql.com/doc/refman/5.7/en/select.html
>To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
>SELECT * FROM tbl LIMIT 95,18446744073709551615;
Это действительно так? Бывают ли на практике такие ситуации что нужно получить количество записей большее чем позволяет максимальное значение int?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L22
Для борьбы с sql инъекциями, я решил что удобней будет делать проверку на разрешенные колонки в методе получения запроса, чем в методе выполнения этого запроса. Так ведь тоже можно?
https://github.com/codedokode/pasta/blob/master/security/sql-injection.md#Методы-борьбы
>if (!in_array($sort, $allowed)) {
> $sort = $allowed[0];
>}
А почему $allowed[0] возвращает найденное значение? Я в мануале не нашел чтобы описывался такой синтаксис, и у меня не получилось сделать так же в моем условии https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L35
https://github.com/someApprentice/Students/blob/master/app/Controller/IndexAction.php#L38-L53
https://github.com/someApprentice/Students/blob/master/app/Controller/SearchAction.php#L29-L44
Это ведь тоже копипаста, верно? Я только что подумал что это код можно вынести в отдельный методов родителя контроллеров. Скоро исправлю.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L55
Я помню как ты говорил, что методы можно делать статическими если всегда будут возвращать одно и то же значение и не имеют никаких зависимостей, но в этот метод передается и меняется класс Student. Не является ли это зависимостью?
Если мы инкапсулируем методы то не следует нам их сделать закрытыми?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L61
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L68
Как закрыть эти методы? Если я пытаюсь обратиться к ним в статическом методе через $this, то я получаю ошибку о том что обращаюсь не в контексте объекта.
Это копия, сохраненная 18 августа 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.