24 декабря Архивач восстановлен после серьёзной аварии. К сожалению, значительная часть сохранённых изображений и видео была потеряна. Подробности случившегося. Мы призываем всех неравнодушных помочь нам с восстановлением утраченного контента!
Добро пожаловать в наш уютный тред. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме. ОПу ведь все это читать придется.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.
Платиновые вопросы
- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко. - Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета) - Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery - Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/. - Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев - Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm - Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию. - Что самое главное для программиста? Умение аккуратно оформлять код. - ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет. - Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
-------------------
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Вообще, в 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 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
Кто-нибудь изучал PHP по курсам Специалиста (4 уровня)? Я сейчас изучаю. Как думаете, этих знаний хватит, чтоб устроиться в какую-нибудь конторку? Все остальное, что нужно, я изучу на деле. Верстать умею. Когда-то я работал в одной веб-студии (давно), но там PHP никто с меня не спрашивал (только минимум). Делал верстку, потом ставил какую-нибудь Джумлу, натягивал на нее верстку и сижу, настраиваю Виртуэмарт. А сейчас смотрю вакансии - везде знания PHP нужны.
>>958715 (OP) Блядь, что за криворукий рукожоп создал тред? Где ссылка на прошлый? Где 4 пикчи? Где второй и третий посты. Мод, удаляй это, Настоящий оп пересоздаст.
Помогите разобраться с БД. в Lampp создал новый проект (laravel new test). При php artisan migrate получаю
[Illuminate\Database\QueryException] could not find driver (SQL: select * from information_schema.tables where table_schema = testdb and table_name = migrations)
[PDOException] could not find driver
В laracasts он подымает mariadb сервер, но хотелось бы использовать Ксамповский.
>>958797 Я удалил непонятный блок с хуй пойми какими ссылками и не добавил ссылку на предыдущий тред. Остальное оставил как есть. Ну и картинку только одну добавил (они все равно говно), а тот тред ушел на такое днище, что я поначалу подумал, что тут вообще треда про пхп нет (и охуел). Пусть твой "настоящий оп" в следующий раз ушами не хлопает, а следит за своим тредом. Алсо, ты можешь нормальную по твоему мнению шапку или нужную ее часть закинуть сообщением, все равно их пока еще мало. че как маленький?
PHPч, что делать в такой ситуации: Получаю json пакет с массивами массивов (пикрелейтед 1 и 2). декодирую его через json_decode($data, true) и получаю пикрелейтед 3 казалось бы, всё чики пики, но при попытке обращения к массиву [users] выходит уведомление о несуществующем индексе users Notice: Undefined index: users in ... и var_dump(jsonDecoded["users"]) выводит NULL. Хотя, казалось бы, данные вот они есть. Щто делать?
>>958830 Видят, но я например знаю, что если делают перекат, то в старый тред кидают ссылку. Если ссылки нет, значит продолжаем текущий тред. Каталог или нулевую я практически никогда не просматриваю.
Что сделать, чтобы Unicode символы отображались (всякие крестики-нолики отсюда https://unicode-table.com, например)? Некоторые отображаются, а другие нет. Оп говорил, что это из-за отсутствия шрифтов в системе. У меня шиндоус7.
Сап, посоны. В общем нужно сделать на сайте прием платежей и выплаты пользователям. Интересует вопрос относительно выплат. Допустим пользователь делает запрос на вывод какой-то суммы, и деньги переводятся на его счет. Все это автоматически, без моего участия. С помощью чего такое можно сделать? Яндекс Касса? Робокасса?
Теперь напишем Контроллер, который будет выводить список объявлений. Он будет запрашивать этот список у Модели и вызывать Вид, чтобы отобразить его в виде HTML страницы. Не будем использовать здесь функций или классов, а напишем его в виде простого скрипта public/list.php. Мы кладем его в публичную папку, так как именно его мы будем вызывать для просмотра списка:
// Получаем список объявлений $posts = $postService->getAllPosts();
// Вызываем вид, чтобы отобразить их require __DIR__ . '/../view/post-list.phtml';
Почему у нас контроллер "не видит" модель? Нам достаточно того, что уже затребован bootstrap.php, который как раз "видит" модель? Это обязательное требование - не указывать модель в контроллере, а делать вот так опосредованно?
>>959194 Ну вот мы же вызываем в браузере контроллер по http://localhost:8001/list.php? А в контроллере у нас инициализируется $posts = $postService->getAllPosts(); - а это у нас из модели. Получается, контроллер "видит" $postService->getAllPosts() благодаря тому, что bootstrap.php их затребовал? >Что значит "не видит", то что нет require? Ну да, почему именно так, почему нет require __DIR__ . '/../PostService.php'; и require __DIR__ . '/../Post.php'; в самом контроллере? Для чего такой вот буфер, обязательно ли это вообще?
>>959200 Традиционно в bootstrap отправляют всю инициализацию приложения. Т.е. все что придется делать в начале каждого контроллера. В этом случае я полагаю: подключение к базе данных и создание экземпляра PostService. Нужно избегать повторений кода. Если что то нужно писать больше одного раза, то пора думать как это вынести в функцию, класс или вот такой bootstrap. Плюс есть еще автозагрузка классов. Это когда есть функция которая занимается подгрузкой нужных файлов при обращении к классам. Подробнее про автозагрузку: https://github.com/codedokode/pasta/blob/master/php/autoload.md Про базовую структуру есть немного в задаче про список абитуриентов из ОП-поста.
Зовут вот сюда. Что значит базовые знания? Может есть что почитать по пыхопе применительно к практической его части(сайты, например) Или просто процесс разработки проекта с какими-то примерами кода. Реально такие в интернетах найти?
>>959262 >Традиционно в bootstrap отправляют всю инициализацию приложения. Т.е. все что придется делать в начале каждого контроллера. В этом случае я полагаю: подключение к базе данных и создание экземпляра PostService. Нужно избегать повторений кода. Если что то нужно писать больше одного раза, то пора думать как это вынести в функцию, класс или вот такой bootstrap. Спасибо, теперь понятно. >Плюс есть еще автозагрузка классов. Это когда есть функция которая занимается подгрузкой нужных файлов при обращении к классам. Подробнее про автозагрузку: https://github.com/codedokode/pasta/blob/master/php/autoload.md Не вполне понятно, где прописывать функцию автозагрузки и обязательная ли она? Если у меня в проекте, допустим, всё так или иначе явно инициализируется? До задачи про список студентов мне ещё далеко, я туда даже пока и не смотрю
Анончики, воюю с задачей "граммар-наци" из регулярок и дошел до пункта исправления ошибок, и чот не понимаю, как грамотно заделать скобки, или на каждый случай исправления надо свою регулярку писать? В конкретно замкнулся на автоисправлении "чю/щю" https://3v4l.org/67RW6
>>959353 Для задачи про студентов я писал в том же bootstrap.php. Тут тебе решать, если приложение маленькое, то можно и без нее наверно, когда классов становится больше до автозаргузка функций сильно упрощает жизнь. Вообще ее можно написать в учебных целях один раз, т.к. composer (менеджер пакетов для php) предлагает свою функцию. Нужно только разобраться с psr-4 и пространством имен в php. Учись в своем темпе не перегружайся пока.
Сегодня проснулся с очень странным желанием чему-нибудь научится. Подумал что можно попробовать и пограмирование, увидев мой случай в шапке (имел тройку по математике) перешел по ссылке с обучением, но осознав цифры уже во втором задании желание пропало и я решил напиться.
>>959440 Привет! Я сейчас тоже делаю этот урок, но на другой задаче. Может, эту задачу я выполнил неправильно, но по предоставленным ОПом номерам она работает. >Как сделать так чтобы он искал что между цифрами могут быть пробелы скобки и тире? Тут как в математике, тебе надо вынести за скобки ((любое количество скобок-тире-пробелов)(любая цифра)(любое количество скобок-тире-пробелов)) * 10 раз.
>>959685 не за что, сам сражаюсь с регулярками. >>959687 тебе нужен два флага, означающие границу слова - \b. То есть должно быть - граница слова, твоё условие, любое количество любых букв, граница слова.
Если я полностью усвою http://archive-ipq-co.narod.ru смогу ли я делать простенькие задания за отзыв/100-200-300р на фрилансе? Просто поглядел там задания-вроде такое, нужно только функции знать , но это гуглится вроде
Сделал задачу граммар-наци с исправлением ошибок, проверьте пожалуйста http://ideone.com/ssr1bV. И заодно подскажите, как надо настроить регулярку? А то она у меня в предложении: "после таких знаков:восклицательного!И даже" отсутствие пробела в "знаков:восклицательного" вылавливает, а уже в "восклицательного!И" не вылавливает.
>>959734 Могу устно написать пример. Написать скрипт, что бы в будние дни писался один текст, а в выходные-другой( как я понимаю используется функция date() ) . За это дают 500р. Но заказ уже ушел куда то
>>959728 >>959725 А потому что у тебя идет вхождение "знаков:восклицательного", и для следующего вхождения с восклицательным знаком нет начальных буков в регэкспе. Сравни: https://regex101.com/r/XdmE2c/1 Но! Даже здесь не войдет вот такая строка "Что?О!Боги!", так что подумай ещё над условием.
Студентодел репортин. Значит решил я сделать хитрый роутинг, суть такова - объект-роутер не только у меня разбирает урл, но еще и возвращает объект нужного контроллера. Может идея и не оче, но я хочу довести ее до конца. Вот сам метод: public function getController() { if (class_exists($this->controller))return new $this->controller; } Ну вы понел. Проблема в том, что не работает с пространствами имен. Т.е. если сделать класс с нужными названием прямо в файле где сделан объект-роутер, то будет работать. А вот прописать такую хуитку return new Controllers\$this->controller уже нельзя. Как можно решить мою траблу? Или я все таки вообще не туда свернул? Аволоад работет нормально, проверял.
>>959760 >объект-роутер не только у меня разбирает урл, но еще и возвращает объект нужного контроллера Так это же и есть все цели роутера? Или я что-то не так понял?
>>959742 >А потому что у тебя идет вхождение "знаков:восклицательного", и для следующего вхождения с восклицательным знаком нет начальных буков в регэкспе. Если я сделаю регулярку типа /(!|;|\.|,|\?)[^ ]/, тогда я не смогу выполнить первое условие задачи, что мол надо возвращать ошибку с куском текста, поэтому я и хотел брать слова целиком. Какой можно еще вариант придумать, чтобы и ошибку поймать, и кусочек текста вывести с ошибкой?
Я не оп, просто хочу напомнить нулевое, первое, второе и третье правило правило написания своих крипто библиотек - никогда не пиши их, возьми готовую (не для учебных целей, очевидно). Если тебе нужен именно принцип, а не детали (в которых, как известно, дьявол), то тут всё в принципе просто. Мы можем передавать пароль плейнтекстом, сервер сравнит его с хранящимся у себя на сервере плейнтекст паролем. Мы можем передавать пароль плейнтекстом, сервер сделает с ним математическую магию и сравнит с хранящейся у себя математической магией, профит в том, что сервер не знает твой пароль, и не может его слить, минусы в том, что мониторящий трафик злой человек знает твой пароль. Мы можем делать математическую магию на клиенте и отправлять её по сети, проблема в том, что это эквивалент пароля, мониторящий трафик человек знает хеш, он не знает плейнекстом твой пароль, но он может залогиниться в этот сервис, используя этот хеш в любом случае. И вот тут начинаются изъебы, как аутентифицировать себя так, чтоб не передавать пароль или эквивалент пароля. Например, клиент отправляет серверу рандомное число, получает в ответ рандомное число, делает с ними двумя и своим паролем математическую магию, сервер делает с своей копией этих чисел и паролем то же самое, если они совпадают, то ты аутентификацию прошёл. Профит в том, что теперь эти данные одноразовые, так что мониторящий трафик человек не сможет потом залогиниться в сервис, используя то, что он услышал. Новая проблема в том, что зная эти два числа и результат, злой человек сможет попытаться угадать пароль, подставляя свои значения пароля и сравнивая их с результатом. Один из способов побороть эту проблему, это вот твой срп. Как можно проще - есть алгоритм Диффи-Хеллмана, согласно ему, клиент придумывает рандомное число a, сервер придумывает рандомное число b, после вычислений, за которыми на википедию, клиент получает A, сервер получает B, после чего они ими обмениваются и клиент получает ключ из серверного B, используя свой a, сервер получает ключ из клиентского A, используя свой b, в итоге у них получается одно и то же число. Идея состоит в том, что подслушивающий знает A и B, но из них математически невозможно получить a и b, которые необходимы для попыток угадывания, и которые не передаются по сети, как в предыдущем способе. СРП пароль в эту адскую смесь, из-за чего это может считаться механизмом аутентификации. А теперь, почему это всё равно не нужно. Во-первых, все эти механизмы исходят из того, что сервер уже знает что-то, с чем можно сравнить твой пароль. Так что при изначальной регистрации тебе что-то нужно будет туда передать в любом случае, так что если злой мониторящий человек перехватит момент регистрации, у него всё равно будет твой пароль или его эквивалент. Что ты можешь с этим сделать? Надеяться на https. СРП вычисления будут исполняться в твоем браузере яваскриптом. Откуда ты получаешь скрипты? От сервера. Как ты можешь доверять этому скрипту и знать что злой человек по пути не подсунул туда что-то другое? Надеяться на https. Так что если ты хочешь чтоб регистрация на твоем сайте была уровня "ввел логин, ввел пароль, нажал войти", можно сразу надеяться на https и делать как обычно. >>959760 >new Controllers\$this->controller $newClass = '\Controllers\' . $this->controller; return new $newClass; ?
Аноны, как вам идея еженедльно устраивать некие хакатоны на дваче. Составляем список проектов которые нужно реализовать(не совсем простые, а вроде файлообменника что предложен в шапке). Далее голосованием выбираем какой проект нужно реализовать, а аноны все это пилят и выкладывают на гитхаб с определенным тэгом. Так новичик смогут учиться у более опытных товарищей. Алсо, чтобы опытным товарщам не было скучно, то для них можно будет добавить "задачи со звездочкой", в котором нужно будет реазиловать какие-то более сложные функции.
А я потом буду отдавать проекты заказчикам и получать бабло
>>959760 Наркомания какая-то, такого ты хочешь штоле. https://3v4l.org/a86Md Мне не кажется это разумным, роутер должен работать с роутами. Определить какой контроллер отвечает - несомненно, самому его создавать - нахуй надо, просто передать информацию дальше, иначе это лишает тебя возможности, например, ввести систему ивентов в свой фреймворк, где операции "контроллер для роутера определен" и "контроллер создан, метод контроллера вызван" идут отдельно друг от друга и юзер может между ними вставить какую-то свою логику.
>>959843 Я бы даже рад поучаствовать, да со всеми этими заказами, своими проектами и работой я не могу ухватиться за соломинку того времени, когда можно просто пострадать херней.
Катал простыню, но потом испортилось настроение, так что скажу просто: спасибо за подробный ответ, самое главное теперь понял принцип.
>>959829 Хех, а вот это >В тексте найдена ошибка: " а чем отличается от >В тексте найдена ошибка: !И м? Всё у тебя хорошо там, ну можешь отделить показ ошибок в отдельную функцию и там то уж форматировать вывод как хочешь, с пояснениями и скриншотами.
>>959839 >$newClass = '\Controllers\' . $this->controller; Ох блять, спасибо. Интересно, откуда такая логика, что можно сделать $a = new $b, но тоже самое нельзя сделать с неймспейсом? >>959845 Типа того. Може и ты прав, но я уже доведу дело до конца.
http://phpclub.rf.gd/pr/res/945059.html#955671 >Молодец, отличная штука. Ты её сам делаешь, или пулл реквесты принимаешь? У меня есть несколько предложений по улучшению структуры проекта, архитектуры и других вещей. Я могу их подробно описать, потом мы это обсудим в треде или на гитхабе. Как тебе идея? Будет интересный опыт создания чего-то общего нашим уютным тредом. Любая помощь будет полезна. Мне на самом деле пригодился бы кто-нибудь кто мог поддерживать проект пока меня нет.
>>960062 Насчет поддерживать проект не знаю, но возможно смогу предоставить тебе бесплатный хостинг для него (включая хранилище под картинки). Только не сейчас, а в конце апреля - начале мая. По коду я могу отписать проблемы какие заметил, насчет фиксить и дополнять я на самом деле не знаю, работа занимает большинство моего времени, но возможно в следующем месяце у меня будет его побольше. Оставь свою почту, куда тебе можно отписать и обсудить эти вопросы. Структуру проекта я думаю лучше обсуждать на гитхабе или где-нибудь в другом месте, чтобы не засорять тред.
>>960072 Ты либо наглухо отбитый, либо тралишь. За таб вместо 4х пробелов в приличной компании уволить могу за нехуй, это нарушение уровня забивания болта на стандарты.
>>960077 такие петушинные стандарты могут быть только в петушиных конторах, куда нормальный человек устраиваться не будет что примечательно, даже на хабрапомойке, несмотря на лютое засилие быдлокодерских пидерах пробелобляди всегда всасывают во всех холиварах хотя, пробелодебилу нет смысла что-то доказывать, если человек настолько туп что не способен сам особзнать убогость пробелодрисни, с ним не нужно спорить, ему нужно молча ссать в рот
>>960081 А потом какое-то хуйло поудалет по одному пробелу и кое-где будет не 4 пробела а 3, а другое хуйло превращает таб не в 4 пробела а в 2 и энджой ё пробелопомойка.
>>960021 Логика очень проста, ты вызываешь new <стринг>, соответственно неймспейс тоже должен быть частью этого стринга, пхп мозгов не хватает литерал неймспейса с стрингом правильно соединить, ай гесс.
Я не пойму проблему с Табуляцией и Пробелами. Во всех нормальных редакторах, давно табуляция автоматически = 4 пробела. А дальше каждый дрочит как хочет. Какого хуя вы бугуртите-то тут?
>>960021 > Интересно, откуда такая логика, что можно сделать $a = new $b, но тоже самое нельзя сделать с неймспейсом? Можно и с неймспейсами, дело тут не в них, а в приоритетах между операторами new и . (конкатенация): https://secure.php.net/manual/en/language.operators.precedence.php У new самый высокий приоритет. Такой код будет работать:
$className = 'std' . 'Class'; new $className;
А такой нет:
new 'std' . 'Class';
PHP пытается сначала выполнить new 'std', класса 'std' не находит и падает с ошибкой.
>>960112 >>960103 >>960081 >>960069 Зачем вы на толстоту ведётесь, тот неадекват пришёл сюда не за конструктивным диалогом, вы вступили в грязь, а теперь размазываете её по треду.
В статье генерация капчи и хранение md5 от результата в куках. Почему достаточно будет один раз разгадать капчу и использовать это же значение чтобы потом пробиться? Никак не могу понять. В скрипте же постоянно всё заново перегенерируется.
>>960144 Лол, зная лично автора статьи могу сказать, что в 2011 её писал ебаный школьник, так что поискал бы ты что-то получше. А насчет почему - потому что хранится в куках, блеать. Сервер отдает тебе куки с хешем капчи, потом от тебя же этот куки забирает и сравнивает его с кодом, который тоже приходит от тебя. Таким образом у тебя после одного удачного угадывания есть пара из кода и куки с хешем, которые проходят проверку, ты можешь теперь игнорировать новые куки и сабмитить всё ту же пару.
ОП, ты не напутал там, случайно? Как может получиться 25 человек в департаменте закупок, если >Департамент закупок: 9×ме1, 3×ме2, 2×ме3, 2×ма1 + руководитель департамента ме2 >9+3+2+2+1=17 ? Вот так решил просто то, что требовалось: https://3v4l.org/ce8iF Сначала думал сразу сделать так, чтобы антикризисные меры можно было применить (был класс Компания, который создавал департаменты, департаменты создавали работников - в прошлом треде ещё вы подсказывали, за что спасибо), но нет, это для меня пока сложно.
анон, помоги нубу, пожалуйста. Читаю гайды по циклам, и не могу понять в чем ошибка и что я сделал не так. >Всего будет выплачено около 61270 р. за 13 мес. А у меня до этого места просто не доходит. Я не понял изначально где была ошибка, подумал что ошибка в расположении IF. Вот изначальный код с ошибками http://codepad.org/nm9jPcpd
Аноны, а можно сначала изучить какой-нибудь простенький фреймворк и написать на нем что-нибудь, а потом сделать задачу со списком студентов? Или так вся польза от обучения пропадает?
>>960224 >pasted on Sep 14: Што? Ну а так ты прав: ошибка в if ($creditBalance < 0) Там, во-первых, $creditBalance никогда не должен быть меньше нуля, он может быть только равен нулю, сам подумай. А во-вторых, условие там должны быть такое: если $creditBalance с прибавленными 3-мя процентами и тысячей рублей равен нулю. То есть сначала у нас крутится цикл с прибавлением тысячи и трёх процентов, а затем в самом последнем круге выплата с прибавленными процентами и тысячей за обслуживание становится меньше пяти тысяч - анон её выплачивает, после чего цикл останавливается. >$month <= 20 Неверное условие, слишком не по-программистски это! ОП почему-то не исправил до сих пор. Но он хитёр, это может быть такой задумкой, да. Там лучше указать такое условие: пока $creditBalance не выплачен (то есть не равен нулю) - это самое естественное условие.
>>960231 Палю годноту: https://www.youtube.com/watch?v=jmIn0dQJF28&index=1&list=PLa9lO_Eq-vZWucOH1auan_m-POa3n7fV6 Вполне можно, сам так хочу сделать, азаза Конечно, надо где-то увидеть, как это всё функционирует. Программистам в вузиках же показывают всё наглядно, а кто тебе покажет наглядно? И фреймворк посмотришь, и прочее. У ОПа так-то про MVC почитай, про БД, это всё тоже поможет. Я пьян.
>>960235 На самом деле есть простое правило, если начинаешь с 0, то всегда используй < N, если с 1, то <= N, чтоб количество итераций было равно N и ты не путался.
>>960231 Платиновый вопрос. Нет, так делать не стоит. Будешь ходить по кругу без понимания технологий на которых фреймворк работает, максимум научишься повторять как все делается в видосиках. А вот сделаешь студентов, поймешь что такое MVC, разберешься в ООП и прочем - тогда и фреймворки хорошо зайдут.
>>960246 А что там показывать то? Я просто не понимаю зачем поперед батьки в пекло лезть. Для тех же студентов надо считай только MVC знать, все остальное гуглится, можно тут спрашивать. Я пока их делал считай свой мини-фреймворк написал, с роутингом, и контроллерами.
>>960248 Ну вот ты видел, как играют в футбол, даже сам играл, наверное? А представь, как объяснить человеку, который не видел ни мяча, ни бегать не умеет, как играть в футбол. Иногда надо просто увидеть, почувствовать, тогда сам начинаешь ощущать себя увереннее и свободнее. Если он задался целью, то потом всё равно сделает всё как нужно.
>>960233 Да, с него и собирался начать. >>960234 Спасибо за видео, надо посмотреть. >>960245 >Будешь ходить по кругу без понимания технологий на которых фреймворк работает Даже если прочитать и понять исходники фреймворка?
>>960251 >как объяснить человеку, который не видел ни мяча, ни бегать не умеет, как играть в футбол. Надо показать ему мяч и объяснить правила игры в футбол, не? Ну серьезно же. Пускай язык учит, а потом уже экосистему языка.
>>960256 >Даже если прочитать и понять исходники фреймворка? Ебанешься, серьезно. Ну слим еще ладно, может осилишь исходники, но все равно буде куча вопросов "а почему так а не так". Фреймворк так это же готовая архитектура, вот ее и надо понимать.
>>960256 >Да, с него и собирался начать. Вот и правильно, там очень понятная и маленькая документация.
Тем более эти МИКРО фреймворк. Например Модель данных ты можешь разрабатывать полностью сам. В общем там минимум абстракций. Можно легко во всем разобраться и делать как тебе хочется.
>>960256 Если ты такой нуб, как говоришь, то лучше написать свой велосипед и не париться. Код фреймворка читать дело очень полезное, но не на этом этапе. Сейчас у тебя просто каша в голвое окажется, какие-то мелочи, выдранные из контекста.
>>960256 Во-первых, если ты реально способен вот просто сесть почитать исходники и разобраться, то ты и студентов написать способен. Во-вторых, когда человеку показывают, как делать, без понимания того, зачем делать - это хуево, это очень хуево. Может если какая-то серия видосиков, где кто-то будет этот фреймворк разбирать по строчке, и то ньюфаг же тупо не сможет отличить, учат ли его нормальным практикам, или какой-то индусской хуйне. Профит написания своих велосипедов именно в том, чтоб самому прочувствовать, зачем эти компоненты нужны. Типично человек смотрит на незнакомую систему из дохуя компонентов, мозг ему говорит СЛОЖНАБЛЯДЬ, и у него начинаются вопросы "а зачем то, а зачем это, зачем напридумывали тут хуйни, а почему в один файл не засунуть, етц", а вот если он с обратной стороны начнет, засунет всё в один файл и охуеет потом от того, как ему надо будет копипастить код в 15 местах для минимальных изменений, вот этот момент прозрения ничего не заменит.
>>960267 Ни кто же не говорит брать мастхев типо симфони, юи, лару. Микро фреймворки - это элементарщина, все что там есть - роутинг, контроллеры, обработчики http запросов и внедрение зависимостей.
>>960270 Я про микрофреймворки и говорю, послать кого угодно читать исходники симфони это, конечно, экспириенс. Вот эту элементарщину и надо самому писать, роутинг, контроллеры и обработчики, криво, хуево, с хуевым распределением обязанностей, с смешиванием роутера и контроллера в единый организм говно, но своё. Это совершенно не заберет много времени, но предоставит возможность набить все необходимые шишки.
>>960276 А вот мне например кажется, что косяков будет так много, что человек просто будет топтаться на месте большую часть времени. Вед веб разработка просто нереально быстро развивается даже в области бек-энда.
Есть всё разница между - выучить шаблоны "банды четырех" и зубрить шаблоны в книге Мэтта Занстры. Есть некоторые фундаментальные вещи, которые нужно знвть, а есть вещи для, которых есть справочник в который можно всегда подсмотреть. Если не отсеивать лишнюю информацию, можно голову забить до уровня шизы, а толку от этого будет мало, ведь время идет технологии меняются.
>>960279 Если человек будет топтаться на месте при написании примитивнейшнего фронт контроллера, то я боюсь представить, сколько косяков у этого человека будет при использовании более адвансед технологий, может стоит задуматься о другой профессии? >просто нереально быстро развивается Угу, все эти блидинг эдж концепты как хттп запрос и ответ, сессии, мвц, ооп и вытекающие. Просто вчера придумали, к завтрашнему дню устареют.
>>960292 Охуеть абстракции. Начали говорить про методику обучения, внезапно человека понесло в какую-то метафизику. Всё абстракции над машинным кодом, ёпта. Хттп запросы у него уже абстракции, ну приехали теперь. Нахуя их учить, ведь завтра просто возьмет и поменяется. URI больше не будем парсить, хедеры не будем отправлять, POST GET и прочие отменят. Хуякции, блядь.
>>960231 Можно. Мне вот писание своего велосипедного МВЦ ничего ровным счетом не дало. Сейчас даже не вспомню, как его делал, и повторю только с гуглом. А в фреймворках все простенько: в контроллерах роуты, в моделях - работа с бд, во вью хтмл код. хуяк хуяк и готово, в уи даже регистрация и логин сразу из коробки сделаны.
ОП, у меня тоже была проблема с тем, что по ошибке выдали бан и стёрли все посты. Я отписал в /d, с указанием номера бана (обязательно) и причины, и меня разбанили. Попроси ещё, чтобы посты восстановили.
>>960306 >не вспомню, как его делал, и повторю только с гуглом Я не понимаю, как можно было настолько хуево разобраться в такой довольно простой вещи, чтобы быть не в состоянии в любой момент из головы воспроизвести сносное мвс. Если ты не в состоянии, то может ты так ничего и не понял? Нагородил издали похожей хуйни, не вникая, лишь бы работало, и решил что квест комплит?
Алсо оба раза это произошло между попытками запостить комментарии по kubk/students и greenTea242/MinesweeperMVC так что подозреваю, это просто какой-то бан по ключевым словам.
>>960336 Два чаю. Увидел что ОП отвечает в тред, пока мылся всё стерли. При перекате набегают трали, или вообще рандом перекатывает, "Я удалил непонятный блок с хуй пойми какими ссылками". На доброчане хотя бы премодерация есть и треды бесконечные.
>>960334 Проблема в том, что даже если и разбанят, то слова из спам-листа никто не выбросит, то есть можно опять в бан попасть по непонятной причине. Мне в /d так никто и не объяснил, из-за каких именно слов меня забанили. Захожу на сосач только ради PHP-треда, так что я за Доброчан.
>>960320 а может, разумнее сначала проводить все операции с суммой платежа, а потом уже проверять, меньше ли она ежемесечного платежа или нет? Прост я смотрю и как-то у тебя реализовано слишком сложно.
>>960320 >>960424 и да, проверь, твой алгоритм неправильный. Например, если сумма долга будет всего 1000, а не 40 тысяч, то этот долг школьник будет отдавать у тебя 2 месяца. Не очень логично, не находишь?
https://jsfiddle.net/ebaloSnositelXX/wfxtxq59/ jQuery, который Джек не строил #3. Первые две jQuery задачи я исправил по твоим советам и все работает (включая плавный скролл на мозилле), не вижу смысла кидать - время у опа отнимать. Алсо использовал букву "X" вместо unicode символа, так как >>958999 .
Желтый фон, если что для визуализации блока. В решении его быть не должно, поэтому я не использую для него css свойство filter, которым я воспользовался для... > Виджет должен работать с полями ввода любых размеров, цветов (в том числе с белым текстом на черном фоне)
Есть laracasts 5.4 на английском, и перевод или 5.1, или 5.3 (на laravel.ru). Много ли я упущу, если буду делать по старым гайдам приложение на 5.4 версии? Вроде бы сама система не поменялась на первый взгяд, но хотелось бы услышать совет от знающих людей.
Анон, поясни долбоёбу за один момент. Я получаю JSON, декодирую, и выходит массив array ('response' => 1), в котором к элементу с индексом response я обращаюсь как массив->response, хотя логично будет массив["response"]. У меня есть свой массив, в котором к элементу message я обращаюсь массив["message"], но никак не могу массив->message. Знаю, что тупой, но я первый день это дело пердолю и не совсем втыкаю. Походу я совсем тупой. В чём проблема?
>>960447 $zalupa = (object)[ "key" => value] Если массив привести к типу обьекта, то ключи массива можно использовать как открытые свойства класса. $zalupa->key;
Посоны начал учиться php недавно. И вот ошибка уже два часа сижу. При выполнении echo $link; Ошибка "Catchable fatal error: Object of class mysqli could not be converted to string in " Алсо $link = mysqli_connect (HOST, USER, PASS, DB) or die('No connect to Server');
Что нужно с ответом сделать, чтобы можно было использовать $link в mysqli_query($link, $query)? это я в кратце. если нужно всю функцию то она на первом пике
Если без echo, то ошибка Notice: Undefined variable: link in file.php on line 16 Кажется ошибка именно в том как link принимается я хз
>>960455 >echo $link; Ну тебе же пишут, что не может конвертировать объект в строку. >Что нужно с ответом сделать, чтобы можно было использовать $link в mysqli_query($link, $query)? Нужно изучить область видимости переменных в PHP. В твоем случае в функции создается новая переменная с именем $link. Нужно передать линк как пораметр функции или объявить $link глобальной переменной. http://php.net/manual/ru/language.variables.scope.php
>>960457 >Ну тебе же пишут, что не может конвертировать объект в строку. Объект надо разбить в массив?
В функцию добавил global $link;. Проблема Undefined variable: link in ушла. Не уверен, что это как то решило мою проблему. Функций много и для каждой писать не вариант. С $GLOBALS еще не пойму как массив захуячить правильно что бы для всех функций было понятно какое свойство у $link. Пиздец кароче, запутался уже. Не варит башка.
А чем обусловлена необходимость иметь @Id у всех сущностей в Doctrine?
И как перенести данные на 'новую' схему? Для этого нужно использовать Doctrine Migrations? Там есть возможность преобразовать все данные на новый лад? В частности, сгенерировать id для всех записей?
Я мог бы в ручную отредактировать дамп-файл, но будет ли это правильным путем?
>>960475 >А чем обусловлена необходимость иметь @Id у всех сущностей в Doctrine? Это с Doctrine связанно, а с самой СУБД И БД.
>>960475 >И как перенести данные на 'новую' схему? Для этого нужно использовать Doctrine Migrations? Там есть возможность преобразовать все данные на новый лад? В частности, сгенерировать id для всех записей?
Если ты изменил сущность ( поля новые добавил/убрал или поменял), то просто делай doctrine:shceme:update
СУБД тут не причем, просто без id доктрина не сможет искать записи. Когда ты делаешь
$em->remove($entity); $em->flush();
Доктрине как-то надо сгенерировать запрос на удаление, и для этого и нужен id, чтобы получилось
DELETE FROM x WHERE id = ?
или
DELETE FROM x WHERE id1= ? AND id2= ?
Для составных ключей.
Насчет Doctrine migrations: вы оба по моему не поняли, для чего это. В любом нормальном проекте никто не обновляет базу на живую. Генерируются скрипты обновления - миграции - и они уже запускаются. Это позволяет всем разработчикам автоматически обновлять свои копии баз данных.
Но тут я хочу предупредить, что не всегда хорошая идея генерировать схему по описаниям сущностей. Если писать SQL вручную, получается больше возможностей по тонкой настройке таблиц, индексов, ограничений итд. Я думаю, что на практике лучше писать SQL и миграции руками, а автоматическая генерация годится разве что для тех случаев, когда делается по-быстрому какой-то прототип, и никакие подстройки не нужны.
Соответственно doctrine:scheme:update годится разве что для тестирования, так как она не генерирует миграции. Обновлять БД в команде надо через миграции, если человек пишет один то можно конечно и без них, но лучше бы сразу их осваивать.
Самому же удобно, прогнал миграцию на локальном сервере, проверил, если все ок - прогнал на продакшене. А как иначе обновлять несколько баз? руками? руки отвалятся.
>>960478 >Если ты изменил сущность ( поля новые добавил/убрал или поменял), то просто делай doctrine:shceme:update У меня возникали ошибка когда я делал это. Я думал, это потому что нельзя делать апдейт поверх данных, но теперь я погуглил что это за ошибки и исправил их.
>>960491 >СУБД тут не причем, просто без id доктрина не сможет искать записи. Легко было предположить что на этом завязано её устройство. Я ещё предполагал, что есть некоторая договоренность между программистами делать для каждой таблицы колонку с id.
>Обновлять БД в команде надо через миграции, если человек пишет один то можно конечно и без них, но лучше бы сразу их осваивать. Сейчас освою...
Хочу забыдлокодить диванный стартап, очередной никому не нужный сервис. Я правильно выбирают технологию?
Что рассматриваю: 1. быстро и легко кодить, крутые фреймворки 2. низкая стоимость владения. vps не нужен. пойдет копеешный шаред хостинг (этот пункт еще актуален?)
>>960533 >for (;;) Плохой подход. Попробуй заменить на другой тип цикла: foreach или while. >if ($credit<4000) Это вообще никак разумно не объяснить, откуда взялись 4к, откуда взялось это условие? Неверный подход, хотя и считает вроде бы верно, потому что говнокод, который не поддерживается и не имеет смысла. Теперь, когда ты разобрался в работе цикла, мог бы переписать. Но ты не станешь, ведь ты же ленивая задница, ага, да, я тебя знаю.
>>960578 >if ($credit<4000) Это из-за того что, каждый месяц начисляется 1000 рублей комиссии. Если ставить 5000, то он ещё один круг делает. Что-то пока не получается придумать альтернативный вариант. >for (;;) Заменил на while ($credit>0)
>>960566 >Пацаны. php еще жив? Более чем. С седьмой версией очень приятный стал, с тайпхинтингом и быстротой. Дальше они еще JIT компиляцию сделают, если все пойдет хорошо.
>Я правильно выбирают технологию? Зависит от задач. Если ты хочешь сделать что-нибудь в реалтайме (чат, к примеру), то PHP тут вряд ли подойдет. Если у тебя что попроще (обработать запрос пользователя, отдать ему ответ и завершить выполнение) то вполне можешь брать PHP.
>пойдет копеешный шаред хостинг (этот пункт еще актуален?) Тут уже зависит от того насколько нагруженным будет проект и как ты архитектуру построишь.
>>960491 >СУБД тут не причем, просто без id доктрина не сможет искать записи. Когда ты делаешь Это просто фейспалм. Почитай хоть про индексацию и нормализацию данных в бд.
>>960610 Я знаю что есть Ratchet, но никогда не видел чтобы его в продакшене кто-нибудь использовал. Легче взять проверенные временем библиотеки на ноду или пайтон.
>>960613 Нет, просто ты дол>>960612 >никогда не видел чтобы его в продакшене кто-нибудь использовал. Если ты не видел - это не значит, что его никто не использует.
Если понадобится более производительный чат, то перепешу это сервер на Го или Си/C++ на крайняк. Но обмазываться питоном да еще И Н О Д О Й я точно не буду.
>>960587 >Дальше они еще JIT компиляцию сделают, если все пойдет хорошо. Поясните ньюфагу, что это изменит для среднего крокодила? Просто скорость выполнения скриптов увеличится?
>>960626 > скорость выполнения скриптов увеличится Да, но это не точно. + переносимость, не придется таскать с собой все исходники, чтобы что-то запустить.
Они уже делали разок так. И у них ничего не получилось.
>>960585 >Это из-за того что, каждый месяц начисляется 1000 рублей комиссии. Если ставить 5000, то он ещё один круг делает. Ну вот хоть тресни - не пойму, почему 4к, а не 3к, не 2к? Если бы как-то было связано с имеющимися значениями - было бы понятно. Представь, это работающее приложение, а другому программисту что-то надо в нём поменять, - так он же не поймёт этого условия. >Что-то пока не получается придумать альтернативный вариант. Нужно исходить из того, в чём суть действий, это и ставить в условия. 1. Анону нужно выплатить кредит, поэтому цикл должен, поэтому цикл будет продолжаться, пока сумма кредита больше нуля. 2. Когда сумма кредита (с процентами и тысячей за обслуживание!) меньше 5000 - выплачиваем только её и завершаем цикл. Всё, тут больше ничего нет. >>960603 О, вот тут уже всё отлично! >$total=$total+5000; Лучше избегать использования подобных цифр, когда у нас есть переменная для обозначения сути. Это же $payment, так пусть там и будет она. Отлично, братишка, верной дорогой идёшь! Прости за "ленивую задницу", был не прав.
>>958715 (OP) Как быстро вкотиться в конструктор битрикса? Посоветуйте видеокурс или что-то вроде (русский, доступный на шару) Чтоб за пару-тройку часов уже уметь верстать лендинги и прочие несложные страницы? Верстать более-менее умею, там вообще какие-то есть отличия от html/css или других визивиг-редакторов веб-страниц? Может, кто возьмется помочь через скайп/телеграм/етц? Да, я чому-то не вижу на торрентах этого самого битрикса, его где брать, только с офф-сайта качать триал? Оно мне в системе не насрет?
>>960777 >Ну контроллер это я имею ввиду что-то типа books/categ Ну тогда все заебись. Еще в место ?some_param=some_value можно просто парсить значение из URL. /controller/action/some_value
ОП, анон, кто-нибудь... Есть на примете какая-нибудь готовая js галерея, встраиваемая в сайт? Чтобы вот прямоугольник, в нем текущая картинка + они потихоньку сменяют друг друга + стрелочки вперед-назад + каждая картинка является ссылкой на какую-либо страницу эльфы набегают, можно играть за охрану дворца. Ну и все, собственно. Чтоб совсем-совсем минимум кода и он более-менее понятный был, в идеале, я так понимаю, эта хуйня на 50 строк (сам я на жс максимум десятистрочную хуйню писал и очень боюсь эволюционировать), чтобы понять, разобраться и допилить, что захочу?
>>960929 Да, она самая. >>960932 Ну нет, спасибо, анон, но это для меня пока еще чертовщина какая-то, какие-то непонятно вообще как работающие классы-айди... С ходу (если не смотреть в хеад на линки на жс) вообще выглядит как какой-то умный хтмл, лол. Я до бутстрапа пока еще не дорос, мне бы в азах jQuery разобраться сначала...
>>960971 Круто, у меня почти та же фигня, я бы тоже хотел хотя бы одного друга. Но нет желания учить 100500 говнофреймворков на полгода. жКвери, бутстрап - да, в свое время. Ресты, боны, ангуляры - нахуйнахуй, мне не так много платят за это дерьмо. А ближайшие два месяца у меня госы и диплом, вот.
Некого спросить кроме вас. Что у вас спрашивали при первом собеседование по пхп?в понедельник иду на собеседование, немного волнуюсь, поэтому спрошу у вас. Как долго длилось собеседование, что спрашивали? >Английский на уровне чтения технической документации Как они проверять его будут?типа дадут листик и попросят прочитать или как? Стоит ли забивать на универ или как? Специальность разработчик программного обеспечения, она нужна мне или лучше что-то другое выбрать?
>>960989 >Специальность разработчик программного обеспечения, она нужна мне или лучше что-то другое выбрать? Тебе нужно что угодно, что может прокатить за бакалавра в IT (computer sience, computer networking etc) для последующей эмиграции. Т.е. нужно узнать смогли ли выпускники твоего ВУЗа устроится на этом вашем западе. Как узнать? Найти в соц. сецях и спросить "Были ли проблемы с подтверждением диплома при получении разрешения на работу?".
>Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо. ОП, ну зачем это? Понятно, что тут при создании работника надо тупо проверять профессию, чтобы определить кофе, зарплату и страницы. Но не усложнение ли это? Вот тут я сделал без такого: >>960162 Почему бы просто не сделать это всё свойством класса? Смотришь на класс и свойства - видишь кофе, зарплату, страницы, а так надо смотреть в метод addEmployee, чтобы это всё узнать или поменять? Это сделать не проблема же, просто смысл в чём, ведь неудобно же! Захочешь поменять - меняешь в свойстве соответствующего класса, а не в этом методе.
>>961000 Ну вот так сделал, как предлагаешь в подсказках: https://3v4l.org/IC9kb Реально кажется это менее удобным, чем если бы было в свойствах. Я помню, ты всегда говорил, что всё то, что может вычисляться, не надо хранить, но если мы представим, что нам надо создать миллионы экземпляров работников, то это будет большей нагрузкой, чем просто хранить свойства в их классах, разве нет? Загоняюсь, но ведь ты способствуешь этому и это хорошо.
Открыт тут ваши уроки, решил порешать задачки. Про кубики, все написал от руки, всё работает, но в моём браузер не работает перенос строки. Т.е это \n не работает. Всё пишется сплошняком, а в опере вообще траблы с кодировкой. Меня такие мелочи волнуют. https://ideone.com/eIgrnT
>>961189 Да, я сразу же пофиксил, просто ссылку забыл в после поменять. Однако почему не работает перенос строки в брауезере? Файл index.php, запущен openserver.
>>961149 > нормальные значения Ты хочешь, чтобы тесты сразу джойнились с автором? Доктрина по умолчанию не джойнит всё, что возможно, а создаёт прокси-классы: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html Для получения теста с автором можно использовать DQL с джойном, можно указать доктрине подгружать конкретную связь жадно (указав fetch="EAGER" в ManyToOne аннотации), но это наверное не очень гибко.
Ещё у тебя там метод setAuthorId в классе Test, зачем? Доктрина это о том, как работать с объектами, а не с айдишниками из БД.
>>961192 HTML разметка игнорирует переводы строк. Если нужно их сохранить, то можно обернуть вывод echo в тег <pre>
>>961276 Я бы вообще новичкам советовал встроенный в PHP веб-сервер - никакой мороки с установкой + запуск проще некуда + все ошибки сразу в консоль, не нужно искать логи (некоторые новички о них просто не знают). А то люди банально не осиливают установку всего руками и скатываются к васяносборкам.
ОП, анон, кто-нибудь... Есть на примете какая-нибудь готовая js галерея, встраиваемая в сайт? Чтобы вот прямоугольник, в нем текущая картинка + они потихоньку сменяют друг друга + стрелочки вперед-назад + каждая картинка является ссылкой на какую-либо страницу эльфы набегают, можно играть за охрану дворца. Ну и все, собственно. Карусель стандартная по сути. Но чтоб совсем-совсем минимум кода и он более-менее понятный был, в идеале, я так понимаю, эта хуйня на 50 строк (сам я на жс максимум десятистрочную хуйню писал и очень боюсь эволюционировать), чтобы понять, разобраться и допилить, что захочу?
Никак не могу открыть доступ к проекту. Делаю chown -R usarname /opt/lampp/htdocs/projectname/ chmod -R 755 /opt/lampp/htdocs/projectname/ Но доступа нету
2) все лайкабельные сущности в одну таблицу: http://sqlfiddle.com/#!9/989697/3 Плюсы: - вставка сущностей без костылей Недостатки: - Для каждой новой сущности нужно добавлять новый столбец в таблице likes, нужно не забыть добавить уникальный ключ.
>>961553 1, только полиморфные связи осуществляются не только по id, но и по table_name/model_name. В целом фреймворки работу с такими вещами автоматиизируют вполне.
>>961599 Используй силу, люк. Что хочешь, то и пиши, только свич не везде подходит. Есть мнение что то иф, то сфитч медленнее (мнения расходятся), но это такая себе на спичках экономия. Я еще неистово злоупотребляю словарями, что поидее и того и другого медленее, но когда у меня полсотни обработчиков для динамических данных можно ебануться в условия впихивать.
>>961599 Cмотри по ситуации. Обычно switch-case читается проще, чем нагромождение из if-elseif-elseif. Но у switch есть недостатки: - он по умолчанию использует нестрогое сравнение (==) - в if-ах можно делать более хитрые проверки, например if ($a instanceof Foo)
>>961608 Я наверное не совсем правильно выразился. Имел виду, что сохранять данные на диск мне не нужно, мне нужно все распарсить, а потом использовать для создания своей страницы. Все на ходу, без сохранения.
То есть мне нужно создать класс Profile, предусмотреть в нем все необходимые переменные, потом создать объект этого класса и запихнуть туда распарсенные данные. Правильно?
>>961591 Сделай две таблицы, photo_likes и user_likes, которые содержат связи like_id-photo_id или user_id. На них уже можешь внешние ключи ставить. А в твоей таблице тогда только первые 3 колонки останутся.
>>961612 В php есть DOM, в него грузишь твою страницу, потом используешь xquery, чтобы получить данные из нужных узлов. Это не задача класса Profile, он должен уже готовые данные получать через конструктор. Пишешь другой класс HtmlStatsLoader, который весь XML парсит и данные в нужных местах отдает, потом связываешь с Profile через конструктор. Получится что-то вроде $profile = new Profile($loader->getUser(), $loader->getLevel(), $loader->getStats(), $loader->getEquipment()) ну и дальше в таком духе. Дальше чтобы сохранить Profile, пишешь класс XmlProfileSaver, который в конструктор принимает твой объект класса Profile, вытаскивает из него данные и сохраняет в xml через тот же php dom.
>>961635 Не юзал твой phpQuery, судя по описанию просто какая-то тупая надстройка над DOm в стиле jquery. Обычно DOMа и Xquery для всех подобных задач по уши хватает, синтакс там не сложный.
>>961636 Я когда-то пробовал и обосрался с иксквери. Ну вот смотри, что выходит с этой библиотекой. Красиво же по большим кускам сразу разобрал, а потом эти большие куски уже разребу по переменным.
>>961637 В xquery ты точно так же эти куски получить можешь прямыми запросами. Дальше ты просто тот же дом юзаешь, как у тебя на скринах. Не вижу смысла со стороннюю либу мучать, если делает все то же самое, что встроенные в php средства.
>>961639 Ну фиг знает, я купился еще на то, что в какой-то статье говорилось о сравнении скорости работы, и эта штука работала "в 8 раз быстрее, чем встроенные в пхп методы".
Пикрилейтед моя предыдущая попытка, я там обосрался и мне надоело гуглить, так что можешь не пояснять в чем была проблема.
>>961640 По скорости - первая ссылка в гугле говорит, что phpquery твой парсит заново документ на каждой итерации, т.е. при каждом запросе селектора. Так что уже тормознее будет. Если скорость важна, вообще лучше через expat parser в php читать, он просто один раз проходит по всем нодам и кидает тебе эвенты, весь dom даже не нужно в память грузить.
https://ideone.com/VHVCW8 Я верно посчитал? Меня лишь смутил ввод новой переменной ради единовременной выплаты за открытие счета в последнем банке, кажется это лишнее и нужно как-то покрасивее это сделать. Третий банк не наебал. Юзаю <br>, потому что код проверю в браузере, а он не переносит строку с помощью /n.
>>961705 Нет, задача решена неверно. Второй банк нужен для того, чтобы после задачи про Айфон проверить правильность работы скрипта. Во втором банке должно было получиться 61270, ты что, про Айфон не решал задачу? Также у тебя не определена переменная $sum перед циклом как пустая, как ноль или подобное. Функции должны работать с известными им переменными, которые или в аргументах туда идут (в скобках), или внутри самой функции определяются.
>>961729 https://ideone.com/zSuvX5 Теперь верно, но я пока не догоняю почему так. Я всего лишь вынес вычисление остатка по кредиту за условие, в начало цикла.
>>961740 Скрин. Избавляйся, иначе в большом приложении вообще не будет работать, это Идеоне такой лояльный. Также лучше разделять пробелами выражения, а то сложно читается в таком виде: >$value+$comiss+($value*$persent/100); >Я всего лишь вынес вычисление остатка по кредиту за условие, в начало цикла. Так и должно быть - сначала сумма кредита увеличивается на проценты и тысячу за обслуживание, а потом подпадает под действия условий в if...else.
Раньше для форм в Laravel я использовал Illuminate\Html, но в 5.4 Collective\Html. В контроллере использовал use Illuminate\Http\Request; и use Request; Далее public function store { $input = Request::all(); return $input; }
Но как сделать такое же с Collective\Html? Request:all уже не работает.
>>962002 PDO ships with PHP 5.1, and is available as a PECL extension for PHP 5.0; PDO requires the new OO features in the core of PHP 5, and so will not run with earlier versions of PHP.
Не столько ПХП, сколько его настроек вопрос. У меня есть годовалый сайтик для 50 человек, где я внезапно обнаружил уже ~900к файлов сессий, из них >850к пустых, гостевых. Как так и что делать? И да, удалять сессии по лайфтайму не хочу. Хочу реюзать сессии четче и не создавать их для гостей.
Зачем мне читать про нормализацию, если я писал про нее уроки?
Каким образом "индексация" (и что это такое, кстати? Это ты так пишешь слово "индекс"?) требует наличия первичного ключа? Не надо сбивать людей с толку.
В MySQL можно создавать таблицы без первичных ключей. И можно делать составные первичные ключи.
Я зеленый новичок, которому нужно за 2 месяца вкатиться и написать небольшой сайтец (хотя бы сайт-визитку), используя полноценные фреймы и т.д. Советы из ОП-поста подойдут в такой ситуации?
>>962147 >Как можно писать что-то на ноде или питоне если там даже тайп-хинтов нет? Но ведь TypeScript в котором более развиты тайпхинты чем сейчас в PHP
>>962133 Как бы да, но надо уточнить, проверяется ли хэш на "истинность" на стороне сервера по ip. Так-то айпишник используется в генерации хэша. Подозреваю, что всем на все пох - спер куку, перенес на другую машину и привет, хоть обзапрещайся. Если бы я параноил, то, наверное, сделал бы лайфтайм для сессии или большую кнопку ВЫХОД. Белые люди, кстати, еще делают педаль "выйти из всех сессий".
Далее, на доброчане в /s/ в PHP треде (ссылку на всякий случай давать не буду, а то у нас тут свободное общение) я проверил некоторые другие задачи, почитайте ответы к ним:
>>962173 >Сайт-визитку можно за несколько дней сделать по уроку Хотя, уже не советую. Только что вспомнил, что в последней версии ларавела есть отличия от информации из урока. Без некоторых знаний можно не въехать даже прочитав советы в комментариях.
Я еще и вагрант неделю пердолил, пока разобрался. Теперь понимаю, почему многие программисты так высокомерно к новичкам относятся - очень быстро забываешь, как пердолился с чем-то одним неделями.
В базе есть таблица Categories c полями ('id', 'user_id', 'category_name') return App\Category::all(); возвращает мне всё как надо в JSON, но я хочу сделать API без 'user_id'. Куда копать?
Хочется также пожелать чего-нибудь плохого криворукому инвалиду, которому было лень прокрутить пару страниц и найти тред, и который создал новый тред с кривой шапкой, потеряв часть ссылок и советы по оформлению кода.
Он не может найти драйвер для соединения с БД. одно из двух: либо в конфиге ларавеля у тебя выбран неправильный, либо у тебя не установлено какое-то расширение PHP (pdo, pdo_mysql и тд).
Судя по интернету, php-fpm ставится только пакетом php5-fpm, соответственно ты его наверно выбрал. Проблем никаких нет, ты легко можешь отключить сервис php-fpm с помощью systemctl disable, погугли статьи про systemd вроде такой: http://vladimir-stupin.blogspot.ru/2013/02/systemd-1.html
Но я не уверен, что это надо делать. Если ты используешь их на сайте, твои пользователи вряд ли будут что-то менять в настройках и устанавливать. Тебе лучше всего подключить на страницу веб-шрифт (font-face), в котором они есть, чтобы они 100% отображались.
У меня например кандзи отображаются, а многие юникодные символы - тоже нет.
Объект модели создается в bootstrap.php, и сохраняется в переменную $postsService . Контроллер просто обращается к этой переменной. Так как переменная глобальная (создана не внутри функции), то она видна везде.
Если ты изучал Си, то в PHP include/require это совсем другая вещь. require просто выполняет код из указанного файла. То есть достаточно где-то один раз сделать require для класса, этот класс будет описан в файле, PHP его запомнит, и второй раз делать require уже не надо.
Так как приложение маленькое то проще всего вызвать файлы с описанием классов в bootstrap, создать все нужные объекты и потом не мучаться. В большом приложении используем PSR-4 и автозагрузку классов, и DI container.
Думаю, это то, что описано в моем учебнике + на всякий случай перечитать мануал PHP.
По созданию сайтов можешь посмотреть наше задание про студентов в шапке либо код популярной CMS вроде Wordpress (сложно, лучше сначала сделать студентов).
Логично автозагрузку сделать в bootstrap-файле, так как он отвечает за подготовку приложения к работе, и в том числе настройку автозагрузки. Ведь она понадобится в любом случае, и куда еще ее поместить?
Использовать автозагрузку не обязательно, можно просто руками зареквайрить все классы в bootstrap, если их мало.
Для чю/щю хватит одной регулярки. Просто надо в выражении для замены использовать $0, $1, $2 ... - это выражение берет кусок строки, захваченный соответствующими скобками в регулярке или всей регуляркой для $0. Подробнее в мануале по preg_replace.
Так мы можем поставить букву (ч/щ), которая была в исходном тексте.
Было бы полезно еще усвоить основы HTML/CSS/JS, основы SQL, какую-нибудь простую CMS. Ну и имей в виду, что на простые задачи конкурс большой, сам понимаешь, чем больше способных справиться, тем ниже цена.
Если хочешь побыстрее, можно начать с верстки, но там конкуренция выше.
Вместо твоих магических цифр лучше передавать в checking() фразу для замены.
А еще можно сделать массив вида [ регулярка => замена ] и циклом его обойти.
Выражение /\bз(д[а-яё]+ заменит "здание" на "сдание".
> ([^,;.])( )(а|но) Это выражение ошибется если идет запятая, за ней 2 пробела и за ними слово.
> if ($error == true){ Можно просто if (count($matches[0]) > 0)
Сама идея решения верная, надо регулярки доработать.
> И заодно подскажите, как надо настроить регулярку? А то она у меня в предложении: > "после таких знаков:восклицательного!И даже" > отсутствие пробела в "знаков:восклицательного" вылавливает, а уже в "восклицательного!И" не вылавливает
Это потому, что твоя регулярка при совпадении захватывает идущие за символами буквы, и поиск нового совпадения начинается после них. Надо либо не захватывать все слово после знака препинания, либо использовать утверждения при поиске (http://php.net/manual/ru/regexp.reference.assertions.php )
То есть для поиска символов перед "но" можно попробовать использовать утверждение (?<) но там есть свои ограничения.
Также, еще один вариант - просто применять регулярку в цикле, пока есть что заменять.
Надеюсь, сам общий принцип (клиент доказывает серверу, что знает пароль, а сервер - клиенту, при этом сам пароль не передается) тебе понятен и нужны пояснения только по математике?
Это довольно важное свойство, так как значит, что если злоумышленник захватит или подменит сервер, он все равно не получит пароль от клиента. В ssh для защиты от подмены сервера используют уникальные ключи у каждого сервера, но если сервер не подменен, а взломан, то тут они не помогут.
Вот от каких атак защищает алгоритм:
- перехват переданных по сети данных - взлом сервера и попытка восстановить пароль из базы данных на диске - взлом сервера, с целью дождаться соединения пользователя, и вычислить или выманить его пароль. Злоумышленник сможет перехватить в этом случае зашифрованные данные после расшифровки, но сам пароль - нет.
Также, там упомянуто, что на сервере не хранится сам пароль, а хранится "cryptographic verifier derived from the password", то есть это даже не хеш от пароля, а число, полученное из хеша.
Рассмотрим сам алгоритм.
> q and N = 2q + 1 are chosen such that both are prime (which makes q a Sophie Germain prime and N a safe prime). N must be large enough so that computing discrete logarithms modulo N is infeasible. Это пока понятно.
> g is a generator of the multiplicative group. Вот это уже сложнее. Это уже пошла сложная математика, попробуем разобраться:
В криптографии часто используется арифметика с использованием модуля (остатка от деления) на какое-то число N. Это усложняет выполнение обратных операций. Одно дело, если мы возвели число в квадрат - мы всегда можем взять корень и получить исходное число, а другое дело, если мы например взяли от результата только 3 последние цифры (остаток от деления на 1000) - тут уже корень взять становится труднее, мы будет вынуждены использовать перебор (возводим числа от 1 до N в квадрат и сравниваем последние цифры), что сильно замедлит нам нахождение исходного числа. Может и есть какие-то пути ускорить этот перебор, но в любом случае, выполнение обратной операции получается дольше, чем исходной (возведение в квадрат).
При операциях с модулем N числа a - 2N, a - N, a, a + N, a + 2N сравнимы, так как дают тот же остаток от деления на N. Более того, некоторые математические операции с ними дадут сравнимый результат (то есть одинаковый остаток).
Например, a в квадрате и (a + N) в квадрате дадут сравнимый результат (если взять остаток от деления на N). Проверь.
Набор таких сравнимых чисел называют "классом вычетов числа a по модулю N" (congruence class or residue class). Таких классов будет ровно N и вместе они называются "полная система вычетов по модулю N" (complete residue system modulo n). "вычет" - видимо значит "остаток от деления".
Систему "вычетов" можно рассматривать как ограниченное множество чисел (от 0 до N-1), и можно определить, какие есть свойства у этих "чисел", что получается при выполнении разных операций над ними (все операции с учетом модуля N). Это подробно расписано в первой статье.
Далее, мы можем из этих чисел еще убрать те, которые имеют общие делители с N (ну например, если N = 14, то число 6 мы убираем, так как 6 и 14 оба делятся на 2, убираем 7 и 8, а 9 оставляем так как оно взаимно простое с 14). Если мы оставим только взаимно простые с N числа, то получается "Приведённая система вычетов по модулю N" (reduced residue system modulo n).
Особенности таких "систем вычетов" описываются во второй статье, "Мультипликативная группа кольца вычетов". "Мультипликативная" - это от слова "умножение" по-латински, "группа" - это какой-то математический термин, "кольцо" - тоже. Можешь сам поискать определения.
"Группы", "поля" и "кольца" появились, когда математики начали абстрагировать операции вроде сложения и умножения, и применять их не только к числам, но к "классам вычетов", каким-то функциям, многочленам и т.д, и выяснять, как эти операции работают над множествами этих объектов. Можешь поискать их определения, если хочешь.
Возвращаясь к генератору, что же такое генератор? Я погуглил, и нашел это:
Генератор (или primitive root, или первообразный корень группы), это такое число, которое мы берем из этой группы, возводим в степени от 1 до x и получаем все другие числа в этой группе (с учетом остатка от деления разумеется). Тут важно понимать, что как только мы получим в результате возведения сам генератор, то круг замкнется, числа начнут повторяться, и если мы не успели получить все числа в группе к этому моменту, то уже никогда их не получим.
Вот там приводили пример для N = 9, и группы из чисел {1, 2, 4, 5, 7, 8}. Если мы берем в качестве генератора 2, и возводим его в разные степени, то получаем:
и далее снова будут получаться те же числа. Число 2 при возведении дает все остальные числа из группы. Потому число 2 может служить генератором для этой группы.
А если мы попробуем взять число 4:
4 ^ 1 ~ 4 4 ^ 2 ~ 7 4 ^ 3 ~ 1 4 ^ 4 ~ 4
Оно дает нам только числа 4, 7, 1 и не даст остальные числа из группы. 4 не является генератором группы N = 9.
Число 2 хорошо тем, что если его возводить в разные степени, получаются все возможные числа из группы. Число 4 плохо тем, что получаются не все числа. Зачем это нужно?
Она будет использована в алгоритме для того, чтобы защитить секретные числа при передаче.
Ты бы мог заметить, что хеш-функция тоже труднообратима, чем она хуже? У возведения в степень есть интересная особенность, которой нет у хеш-функции:
(g ^ a) ^ b = g ^ (ab) = (g ^ b) ^ a
Допустим Иван знает число a, а Петр знает b. Иван вычисляет A = g ^ a, Петр вычисляет B = g ^ b, они ими обмениваются в открытую. Затем Иван вычисляет S = B ^ a = (g^b) ^ a = g ^ (ab), а Петр вычисляет A ^ b и получает то же число S. Теперь они оба знают общий секрет S, а злоумышленник, хоть и видит A и B, не может из них получить a и b и вычислить S. На этом свойстве и основам алгоритм обмена. У хеш-функции такой особенности нет, она тут не подходит. Кстати, это я описал протокол Диффи-Хеллмана, если ты с ним знаком (советую прочесть):
> Хотя сама показательная функция вычисляется достаточно эффективно, даже самые современные алгоритмы вычисления дискретного логарифма имеют очень высокую сложность, которая сравнима со сложностью наиболее быстрых алгоритмов разложения чисел на множители.
Важно, чтобы g было именно генератором группы. Генератор при возведении в степень дает любое число из группы. Если это не так, то при возведении в степень будет получаться не любое число, а только часть чисел из группы, и будет проще подобрать число, которое при возведении в степень даст такое же W.
..... далее ниже
Интересный вопрос про SRP, часть 2Аноним28/03/17 Втр 04:33:54#313№962220
В нашем алгоритме, к счастью, вычислять генератор не требуется. В нем и q, и g выбираются заранее, например, берутся из какого-нибудь справочника, спецификации. Также, их можно сгенерировать командой openssl dhparam, указав требуемую сложность в битах. Вот тут пример: https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
Вот пример команды: openssl dhparam -text 1024
Она сгенерирует и выведет простое число q и генератор g для N = 2^q + 1.
У меня это вывело длинное простое число q, закодированоое в 16-чном виде и генератор, равный 2.
То есть мы закладываем q, N, g на этапе написания кода.
Также заранее мы вычисляем число k по формуле k = H(N, g), где H - хеш-функция (например, md5, sha1 и тд). Мы как-то смешиваем N и g (например, разделив их двоеточием) и берем хеш. Тут при вычислении хеша лучше числа кодировать не цифрами вроде "123", а в двоичном виде, и брать хеш от двоичной строки.
Теперь вернемся к описанию алгоритма. Для начала, нам надо на сервере из пароля получить что-то менее подбираемое, чтобы злоумышленник не мог, захватив базу, восстановить пароль:
> x = H(s, p) (s is chosen randomly) Мы генерируем случайную соль, получаем хеш пароля с солью (простейший пример: $hash = md5("$salt:$pass")). Для надежности советуют в хеш еще и логин, и имя хоста добавить (чтобы они были разные даже при одинаковых паролях у 2 пользователей).
> v = g^x (computes password verifier) Затем получаем password verifier путем возведения в степень (разумеется по модулю N). Этот v мы и сохраняем на сервере, вместе с логином пользователя I и солью s (тройку I, s, v). Как я понимаю, восстановить по нему исходный пароль можно разве что перебором.
Заметь, что пароль обработан дважды: сначала хеш-функцией, затем возведением. Это усиливает защиту на тот случай, если в одном из двух алгоритмов найдется слабость. Соль нужна, чтобы для одинаковых паролей у 2 пользователей хеши получались разные и нельзя было понять, что пароли одинаковые.
Теперь посмотрим, как происходит обмен данными:
> User -> Host: I, A = g^a (identifies self, a = random number) Пользователь генерирует случайное (большое) число a и вычисляет из него A. Он отправляет на сервер логин и это число A.
Число a - это что-то вроде секрета, который знает только пользователь. Получить a из A очень трудно и долго.
> Host -> User: s, B = kv + g^b (sends salt, b = random number) Сервер в ответ генерирует случайное число b, вычисляет из него B и шлет пользователю пару (s, B). b - это секрет сервера. Число B составлено смешиванием v и случайного числа b, так что восстановить из него v нельзя, не зная b, а b знает только сервер.
a и b стоит хранить в памяти (не сохранять на диск) и очищать ее после разрыва соединения. Как только a и b уничтожены, восстановить что-то по перехваченным данным становится очень сложно.
Оба они затем вычисляют параметр u:
> Both: u = H(A, B)
Опять же, тут мы смешиваем числа A, В, например, разделив их двоеточием, и берем хеш. Хеш наверно нужен для повышения стойкости?
Пользователь далее вычисляет сессионный ключ K:
> User: x = H(s, p) (user enters password) > User: S = (B - kg^x) ^ (a + ux)
Здесь мы видим, что пользователь по сути вычисляет то же самое число v (g^x), что хранится на сервере, затем по формуле B - kg^x вычисляет g^b и возводит его в степень (a + ux). Попробуем немного преобразовать выражение для S:
(B - kg^x) = g^b (смотри выше формулу для B)
S = (g^b) ^ (a + ux) = g ^ (b *(a + ux)) = g ^ (ba + bux) = g ^ ba * g ^ (bux) = g ^ ba * (g ^ x) ^ (bu)
Тут надо вспомнить что g ^ x = v, подставим это в выражение.
S = g ^ ba * v ^ (bu)
Ну и далее из S мы зачем-то вычисляем хеш и получаем сессионный ключ:
> User: K = H(S)
Теперь посмотрим, что делает сервер:
> Host: S = (Av^u) ^ b (computes session key) Преобразуем формулу для S:
A = g^a S = (Av^u) ^ b = ((g ^ a) * v ^ u) ^ b = (g ^ a) ^ b * (v ^ u) ^ b = g^(ab) * v ^ (ub).
да это тот же самый ключ, что посчитал пользователь! То есть получается так:
- пользователь отправляет на сервер логин и число A, вычисленное из случайного секретного числа a - сервер отправляет пользователю соль s и B, вычисленное из секретного случайного b и числа, полученного из пароля v - они делают вычисления и получают одинаковый сессионный ключ S. Берут от него хеш K.
При этом важно, что сторонний наблюдатель, перехвативший A, B, s, не способен из них получить S. Тут используется факт необратимости хеш-функции, и то, что для операции g ^ a по модулю трудно произвести обратную операцию.
Имея K, сервер и клиент проверяют, что они получили одинаковое число (чтобы проверить, что они оба - те, за кого себя выдают). Затем этим K шифруются данные с помощью симметричного шифрования.
Также там есть несколько проверок на нулевые значения, так как умножение на ноль дает тоже ноль и видимо что-то ломает в формулах выше.
Разберем принципы устройства алгоритма:
- стойкость алгоритма основана на 2 принципах: сложности обратимости хеша и сложности обращения возведения в степень по модулю. Это сделано для защиты при обнаружении слабости в одном из алгоритмов. - случайные (криптографически случайные) числа a, b нужны, чтобы сессионный ключ был непредсказуем, не вычислен из каких-то известных значений. b еще используется для защиты v при передаче числа B. - v используется при вычислении S, чтобы сессионный ключ еще зависел от пароля и без знания пароля его было не получить. - v является общим секретом, который знают и пользователь, и сервер - злоумышленник не знает ни a, ни b, ни v - g выбирается по определенным правилам, чтобы оно было генератором, чтобы при возведении его в степень мы могли получить любое другое число из группы (а не часть этих чисел, что может упростить перебор).
Важно еще то, что K вычисляется из случайный чисел a, b, хранящихся только в памяти и уничтожающихся после генерации K. После закрытия соединения K тоже уничтожается.
Ну вот теперь у тебя достаточно знаний, чтобы попробовать реализовать это в программе.
Вообще, это не задача роутера, создавать контроллер. Обычно он просто получает на вход УРЛ и возвращает имя контроллера, действия и дополнительные параметры.
Иногда роутер объединяют с фронт-контроллером и он еще и создает и вызывает контроллер.
Случаи бывают разные, может мы заносим пароли в сервер, а потом несем его в дата-центр и после этого подключаемся удаленно. Также, при регистрации мы можем использовать еще какое-то шифрование, того же Диффи-Хеллмана.
Этот алгоритм отличается от Диффи-Хеллмана парой особенностей: он проводит аутентификацию, как клиента сервером, так и сервера клиентом. Это важно, если злоумышленник перерезал наш канал и воткнул туда свой сервер - Диффи-Хеллман тут никак не спасет, он только шифрует данные от перехвата.
Ну просто для сравнения, в случае ssh, если злоумышленник внедрился в процесс sshd, он получит пароль. А в SRP - нет, хоть и получит передаваемые по каналу данные.
Плюс, он хорошо защищает хранящиеся на сервере верификаторы пароля от восстановления.
> СРП вычисления будут исполняться в твоем браузере яваскриптом. А если программа-клиент?
Антикризисные меры я бы сделал так: делаем класс АнтикризисныйКомитет и у него 3 метода в стиле применитьМеруN(компания). Метод принимает на вход компанию и что-то в ней меняет, например, увольняет людей. Ну или если тебе хочется заморочиться, можно как-то сделать 3 класса, каждый для своей меры, но не вижу смысла.
У твоего наследования есть один недостаток: нельзя никак догадаться, что при наследовании мы обязаны определить значения вроде $coffee. Лучше сделать в базовом классе абстрактный метод getBasicSalary(), а в наследниках - его реализации. Тогда забыть его реализовать точно не получится.
> public function addEmployee($profession, $number, $rank = 1, $boss = false) { > for ($i = 0; $i < $number; $i++) { > $this->employees[] = new $profession($rank, $boss); Это не очень правильно, что департамент сам создает работников. Лучше сделать метод, в который передается уже созданный employee. А так у тебя нельзя создать отдельно работника и назначить его в департамент.
Да и ты закладываешь ограничение, что у любого работника ровно 2 аргумента в конструкторе. А что если завтра напишут новый класс профессии, где 3 аргумента (например добавится опыт в годах)?
> getTheValues Лучше printValues
> foreach ($departments as $key => $value) { Названия плохие. Надо так: foreach ($departments as $department)
Не надо сюда эту идеологию работника на конвейере вбрасывать. У нас нет цели учить людей переписывать примеры кода из видеоурока. У нас есть цель объяснить что и зачем нужно.
- число 5000 повторяется много раз, его надо вынести в переменную - лучше не писать длинные выражения в шапке цикла, плохо читается, лучше писать их в теле цикла - выражение ($credit+($credit*0.03+1000)); повторяется, надо избавиться от повторов
> if ($credit+$service<5000) Это условие неправильное, так как оно не учитывает проценты, а только комиссию.
Можно сделать так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!) - если остаток маленький, выплачиваем сколько осталось и уходим - иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Немного не по теме задачи, но почему table? Это же флоатами или на худой конец display: table верстается прекрасно. Если что, у нас есть задачи по HTML/CSS.
> var btn = $($("#template-clear-btn").html()); Тут наверно было выгоднее вписать код строчкой, например $('<span...>'), чтобы плагин было проще подключить к странице. Хотя конечно вопрос, что делать, если код более сложный? Простого ответа тут нет. Кто-то в строки вписывает, кто-то в отдельный шаблон и потом как-то собирает в единый файл.
> if (methods.isChromeOrMacClient() && > methods.isSearchType(input)) Здесь, к сожалению, есть проблема, что это довольно ненадежный подход:
- где гарантия, что ты перечислил все браузеры, в которых есть крестик? - где гарантия, что ты не указал тот браузер, где крестика нет? - что если что-то поменяется в определенной версии браузера?
Как например насчет яндекс-браузера и прочей армии хромоколонов?
Сложно найти какое-то оптимальное решение, я бы наверно попробовал перечислить старые браузеры, в которых крестика точно нет (и которых меньше). Лучше всего конечно просто избегать ситуаций, где надо проверять userAgent, vendor, лучше стараться тестировать фичи, если возможно. Или например выводить крестик снаружи инпута, чтобы точно ни с чем не совпал. Или запретить использовать плагин с полями типа search.
Вот тут человек пытается по нестандартным CSS-селекторам обнаружить наличие крестика:
> if (html.attr("dir") == "rtl") Тут есть важный момент. Ты читаешь атрибут dir, если он задан на html. Но во-первых, dir логично читать на инпуте или его обертке, он может быть разный. Во-вторых, там есть значение auto, когда браузер определяет его сам по содержимому. Что с ним делать?
Я тут поэкспериментировал, и увидел что в Хроме вычисление
Также, есть CSS-правила вроде html[dir=...] .xyz, но они наверно не помогут прочитать dir с инпута.
Насчет позиционирования крестика, обычно просто оборачивают инпут в враппер (инлайн-блок например без указания размеров), и позиционируются относительно враппера. Это имеет те преимущества, что например при растяжении/анимации инпута крестик поедет за ним. Но имеет и недостатки, что добавление враппера может сломать верстку. То есть универсального решения тут нет.
> if (!target.closest(".outer-clear-btn")) { Это никогда не вернет false так как возвращается объект jQUery. Надо проверять closest().length
Кстати, обнаружил интересную особенность события input при вводе в японской раскладке. Там сначала печатается латинская буква, а когда их набирается несколько, они превращаются в иероглиф. При этом генерируются события keydown/keyup/input, а keypress не генерируется. Оно генерируется только для ввода в латинской или русской раскладке. С другой стороны, совсем древние браузеры input не генерируют.
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
Заодно указание кодировки исправит проблемы с отображением букв. А то как браузер узнает, в какой кодировке страница? Либо заголовок, либо meta charset нужен.
header можно использовать только до вывода текста, даже один пробел нельзя перед ним вывести. Если ты сохранил файл в utf-8 c BOM то этот символ BOM в начале файла уже все портит. Сохраняй без него
То его надо поставить в начало документа. Хотя тут речь о выводе текста с переводами строк, а не HTML. Кодировку так же можно задать тегом meta в HTML.
>>962236 > Кодировку так же можно задать тегом meta в HTML. Я так и сделал. Хтмл я ещё не забыл, а пхп начал с нуля, ну и засунул php-код в html, что бы мог кодировку в этом html-е указать. Щас снёс всё, оставил только php и header заработал.
Хоть убейте но не могу понять как написать функцию делающую первую букву предложении заглавной. Вроде тема регулярных выражений описана достаточно понятно, но как заменить первый символ в строке - это просто за гранью моего понимания. Хочется засунуть строку в одномерный массив, выдрать первый элемент, условием проверить является ли она заглавная, затем засунуть нужную букву назад. блядь.
>>962215 >Если ты изучал Си, то в PHP include/require это совсем другая вещь. require просто выполняет код из указанного файла. То есть достаточно где-то один раз сделать require для класса, этот класс будет описан в файле, PHP его запомнит, и второй раз делать require уже не надо. Спасибо! Я не изучал программирование до РНР, иду практически с нуля.
>>962228 >Может, еще стоит сделать класс Компания? Я не могу представить, как должно выглядеть следующее: Компания создаёт Департамент, который создаёт Работников. Как, например, в этом случае потом отдельно создавать работников и включать их в компанию? Не могу осмыслить... >Антикризисные меры я бы сделал так: делаем класс АнтикризисныйКомитет и у него 3 метода в стиле применитьМеруN(компания). Метод принимает на вход компанию и что-то в ней меняет, например, увольняет людей. Ну или если тебе хочется заморочиться, можно как-то сделать 3 класса, каждый для своей меры, но не вижу смысла. Сложнота для меня, но если разберусь с классом Компания, то и тут пойму, наверное. >У твоего наследования есть один недостаток: нельзя никак догадаться, что при наследовании мы обязаны определить значения вроде $coffee. Лучше сделать в базовом классе абстрактный метод getBasicSalary(), а в наследниках - его реализации. Тогда забыть его реализовать точно не получится. О, я дальше сделал так, как ты советовал в подсказках, - до этого я делал без чтения подсказок. Вот тут: >>961014 Действительно, теперь если появится дополнительный параметр (потребление воды из кулера, использование мыла или выкуривание сигарет - для примера), достаточно его прописать в методе addEmployee(), в соответствии с профессией. >> public function addEmployee($profession, $number, $rank = 1, $boss = false) { >> for ($i = 0; $i < $number; $i++) { >> $this->employees[] = new $profession($rank, $boss); >Это не очень правильно, что департамент сам создает работников. Лучше сделать метод, в который передается уже созданный employee. А так у тебя нельзя создать отдельно работника и назначить его в департамент. То есть я вообще неверно понимал, что Компания должна создавать Департаменты, Департамент должен создавать Работника... Получается, этим всем могут заниматься простые функции, а методы в этих классах работают только с подсчётом всего по компании или департаменту? >Да и ты закладываешь ограничение, что у любого работника ровно 2 аргумента в конструкторе. А что если завтра напишут новый класс профессии, где 3 аргумента (например добавится опыт в годах)? Ну, тогда можно ведь в конструктор добавить $this->experience = $experience;, а в аргументах поставить по умолчанию $experience = false, чтобы уже имеющииеся работники у нас создавались нормально? Горожу что-то непонятное, конечно. >> getTheValues >Лучше printValues Хм, да, действительно. >> foreach ($departments as $key => $value) { >Названия плохие. Надо так: foreach ($departments as $department) Точно, спасибо, это я машинально записал, а потом не подчистил.
Спасибо за такой подробный разбор! Постараюсь разобраться - задача интересная.
>>962325 Ну вот сделал с нормальным foreach: https://3v4l.org/mHNMJ Признаться, что-то и не сразу вышло вообще - структура почему-то неочевидной оказалась.
Алсо поясните, как правильно данные передавать в сессии? Делаю редирект после регистрации. Сохраняю сначала урл в сессию допустим такой /?sort=name&page=6 А на странице регистрации он уже так выглядит /?sort=name&amp;page=6¬ify=registered ЧЯДНТ?
И снова выхожу на связь с ларавелом: При сохранении файла делаю $file->move($path, $file->getClientOriginalName()); Как мне вместо getClientOriginalName дать собственное имя файлу?
>>962365 Не верно. В уроке есть ответ. $xBal нужно перед условием объявить и обнулить. php намекает PHP Notice: Undefined variable: xBal in /home/vKdGL9/prog.php on line 20 PHP Notice: Undefined variable: xBal in /home/vKdGL9/prog.php on line 21
Поясните, а как делать разделение на контроллеры в случае с о слимом? Ну точнее даже не знаю как сказаь, но вот в студентах у меня парсилась ссылка и в зависимости от урла возвращается объект с контроллером. Регистрация и отображение списка студентов разграничены в итоге разными контроллерами, так код не разрастается до неприличия и в целом удобно. Но в слиме я не могу понять как такое сделать - уже документация наталкивает на мысль о том, что надо ебашить все экшены в одном файле. Да, для задачки с файлообменников оно нормас, а что делать в случае крупных приложений? Как это правильно делается то?
Делаю задачи на строки. Ideone ругается на mb_internal_encoding('utf-8'), мол неизвестная функция. вот текст ошибки:
PHP Fatal error: Uncaught Error: Call to undefined function mb_internal_encoding() in /home/tkDcLc/prog.php:4 Stack trace: #0 {main} thrown in /home/tkDcLc/prog.php on line 4
В гайде написано, что как раз там это все должно работать. Может я что-то не так делаю?
>>962400 Проблема со строками на Идеоне уже давно, перекатывайся на https://3v4l.org Базарю, поцене 38 рублей, намного удобнее и лучше Идеоне. Это что-то вроде контроля версий - в браузере при каждом запуске скрипта будет сохраняться его копия, код не потеряешь, можно в истории просмотров вернуться к нужному варианту и т.п.
>>962434 А, понел. Но все равно какая-то хуйня выходит, надо же опять же определять вот это: $app->get('/', \HomeController::class . ':home'); $app->get('/contact', \HomeController::class . ':contact');
Сап! В универ надо сделать один сайт, использовать Symfony и MySql. Все бы ничего, но я в вебе вообще нулячий. Накатил симфони, поднял xampp, вроде норм, потратил на запуск кучу времени. Но вот что дальше? Читаю гайды и нихуя не понимаю. Как прикрутить бутстрап, создать простую страницу? И еще, стоит ли тратить время на Doctrine?
>>962689 Мне нужна работа за миску еды хотя бы что бы не сдохнуть с голоду. Я бы не против yii освоить, но без работы мне сейчас не вариант Всё очень утрированно но суть ты понял
>>962680 Быстрее всего открыть вакансии по своему городу и расписать требования, количество работ и зарплаты в excel таблицу. Сразу и понятно станет, что учить.
Нужна помощь по задачке. Условия задачи: "W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?" Задача по циклам, остановился на составлении цикла. Код: "<?php error_reporting(-1);
>>962689 Я к примеру пошел на работу опенкарт ковырять. В свободное время изучил второй язык js (не на уровне манипуляции с дом -поработал с нодой, в частности с sails, с Cordova ). Сделал с десяток тасков на этом. Потом плотно занялся MySQL так вы процессе работы с нагруженными e-commerce нужно много оптимизировать. Сейчас в свободное время взялся за slim, потом планирую в laravel/symphony. А мог бы дальше у мамки на шее сидеть и учить фреймворки.
>>962732 А я тоже на работу быстро выкатился, подучил там mysql, пару фреймворков, js и юнит тесты, бабла на год безработной жизни подкопил, щас думаю работу кидануть и на фрилансы попробовать вкатиться. На работе вообще все быстрее учится, дома как-то медленно слишком шло.
>>962732 Ты и сейчас сидишь на шее у мамки, просто выучил пару модных слов с уроков на ютубе, которые ты не смог осилить. Прекращай уже заниматься хуйней, иди на завод, ты нужен стране.
>>962745 Почему? На работе сидеть заебывает, душный офис, куча народу в комнате 5х5 метров, все галдят и невозможно сосредоточиться, линейки с докладами каждое утро по часу и злобный начальник, у которого все должно быть сделано вчера. На фрилансе сидишь дома в уюте и пишешь код как король.
Может кто-то помнит ответы на задачу про айпад с функциями? Вроде в тело функции рабочий код с первой задачи пришил, к Клубнике банку 7777 р. добавил, но мучают сомнения. В ОПовском учебнике на выводе видно что у Клубники банка на "конце" 08. Хуй знает.
Вот я охуел от задачки считалка, в общей сложности 3 часа просидел. Оп вообще не через массивы решал, но я без понятия как вообще это сделать. https://3v4l.org/LB3b5
>>962807 У меня в третьем случае вышло >Кредит от банка StrawberryBank, обойдётся в 53560, выплаты составят - 11 месяцев
Я функции добавил новую вводную переменную "единоверменная выплата", двух других банков она была равна 0, у третьего 7777, собственно в формуле подсчёта эта переменная участвует.
>>962827 >>962821 Все, пофиксил, теперь сходятся. Код у тебя компактный, не то что моя гора текста. Но буду оправдываться тем что пользовался технологиями которые в учебники ранее давались, из читерского только While прикрутил.
Господа, поясните за кеширование динамических страниц при хайлоаде? Гугл говорит, что нужно сохранять контент в текстовый файл и погружать оттуда? Т.е. Пр обновлении данных новые данные пишутся и в текстовый файл и в бд? Таким образом в файле всегда будет лежать свежая инфа?
Задача из "ОПП...", тут как бы и так довольно сложно вникать в это, но масла в огонь добавляет отсутствие вменяемых условий для задачи. В Родительском классе задано одно поле: text; в котором задаётся текст вопроса. Всё, а поле которое мы должны проверять где? Куда? В Классах-предках есть поля: $options; // варианты ответа на вопрос $correntOption; // правильный вариант на вопрос
$answer; // ответ $deviation; // допустмая погрешность
Среди них есть с чем сравнивать - правильные ответы и два других. Но с чем сравнивать? Пользователь ввёл ответы - где эта переменная? Как писать функцию function checkAnswer($answer) если НЕ С ЧЕМ СРАВНИВАТЬ? Ответов пользователя НЕТ.
Условий для решения задач нет, а самому додумывать, а потом ебаться с тем, что выполнить поставленную задачу невозможно с уровнем знаний - нет спасибо.
>>962878 >Господа, поясните за кеширование динамических страниц при хайлоаде? Ночью запускается скрипт (кроном) и он создаёт много-много файлов с расширением .php Они потом прогоняются через интерпретатор. IRL от высоких нагрузок это не спасает, гугли MySQL, таблицы в памяти, плоские таблицы с одним ключом.
Объект Question хранит только информацию о вопросе. Ответ в нем естественно не хранится, а хранится в отдельной переменной или массиве (так как ответов много).
Там же есть пример в уроке: функция function checkAnswers($questions, $answers)
Она получает на вход отдельно массив объектов-вопросов и отдельно массив ответов. В цикле обходим вопросы и берем соответствующий вопросу ответ из другого массива.
Да ебена мать, помогите разобраться. Все никак не могу прикрутить bootstrap к симфони. Добавляю бутстрап: bower_components/bootstrap/dist/css/bootstrap.css Создаю бандл, там есть такое: src/Blogger/BlogBundle/Resources/views/Default/index.html.twig. Сюда я пытаюсь вкорячить хтмл-код, также дописываю <link rel="stylesheet" href="{{ asset('bower_components/bootstrap/dist/css/bootstrap.css') }}"> И нихуя не работает. Просто обычная страница без css.
>>963032 У тебя публичная директория web, а файлы бутстрапа совсем в другом месте. Руками копировать не всегда хорошо, так как при установке твоего приложения на другую машину, сисадмину нужно будет делать то же самое, а без подробной инструкции очень сложно догадаться что именно нужно скопировать, куда и откуда. Легче и проще один раз написать скрипт который это все делает, а потом если ты к примеру решишь поменять структуру файлов в публичной папке, ты сможешь сделать это в скрипте, при этом тебе не придется писать новуб инструкцию при установке.
>>962970 >ладно, скипну. Я те блять щас скипну, пииииидр!!1 Это самое важное в учебнике, всё, что было до этого - это подготовка к ООП. Все фреймворки на нём, всё вменяемое программирование - на нём. А ты - "скипну". А на давай быстро вопросы задавай!
>>963052 Для начала ты можешь открыть инструменты разработчика в браузере и посмотреть откуда он пытается загрузить стили. Эта информация поможет тебе определить источник проблемы. И в следующий раз пользуйся гуглом, решение тво ей проблемы можно найти за минуту.
Есть ли тут те, кто вкатился в PHP после нескольких лет кодинга на Java, C# или других нормальных языках? Как унять блевотные призывы и приучить себя к любви к сладкому хлебушку? Ведь на жабе нет фриланса/удаленки.
>>963062 Честно, по всем гайдам пытался, и в composer.json вписывал зависимости, и в config.yml всякие asertic, никак. А стили пытается грузить откуда я и указал, но Failed to load resource.
>>963096 >Зачем эти сложные :: С этим все очень просто, лол. Два двоеточия и стрелка используется от того, что точка уже используется для конкатенации, лол.
Для начала посмотри в исходном коде страницы, какие теги вставляются в HTML-код. Посмотри на вкладке network в отладчике, куда идут запросы. И посмотри, нет ли чего в логах.
Так эта намного проще. Собери куски кода для проверки ответов из урока, и подправь там то, что требуется в задании. Там большая часть кода уже написана автором урока. Надо только чуть подправить.
Надо разбираться в том, что происходит, а не делать что-то наугад. Если ты используешь assetic - разберись как он работает, и что происходит в твоем случае.
В файлы невыгодно так как создается лишняя нагрузка на диск, а его пропускная способность не резиновая. Часто кешируют в память, например в мемкеш или редис. Ну и тут не все так однозначно, в большинстве случаев, кроме самых простых, страницы кешировать целиком просто невозможно, так как они для всех разные или постоянно меняются.
Надо не слепо следовать рекомендациям неграмотных людей, а разобраться: что мы экономим, что мы теряем, что выигрываем, что на что меняем.
Если ты не понимаешь, что описано в презентации, то рановато тебе кешированием заниматься, задавай уточняющие вопросы.
Если хочешь, можем еще какую-нибудь практическую задачу решить - например прикрутить кеширование к блогу на вордпрессе который без этого весьма тормозной.
В твоем случае про текстовый файлы - 100% бред так как база данных сама хранит данные в файлы. Какой смысл пытаться дублировать то, что она делает, при этом делать это хуже? База данных например умеет кешировать результаты запросов в памяти, умеет кешировать прочитанные с диска данные в памяти, ты предлагаешь все это выбросить и использовать более медленный способ?
В каком случае писать йоба функции/методы со всякими необязательными параметрами задействовав которые можно сильно поменять возвращаемый результат? Вот как в нативном php много функций с такими паратреами. Вот здесь я захотел вернуть секцию со слимКонфигом и инициализировать им слимовское приложение, но на тот момент уже был написан метод getValue, который возвращает только конкретное значение. Создавать второй метод?
>>963255 Я не про перегрузку. Ты меня не понял. Приведу пример. parse_ini_file("/path/to") - возвращает массив со всеми ключами-значениями. Но если мы добавим во второй необязательный параметр true - будут еще секции.
>>963258 Добавление необязательных параметров, которые слишком сильно меняют поведение метода это bad practice. В ядре пыхи подобные функции есть, но это не повод на них равняться, в пыхе много чего есть - наследие времен, когда php был юн и наивен. Создавай метод с необязательными параметрами если: 1 - поведение метода остается очевидным и предсказуемым 2 - дополнительные параметры либо лишь уточняют поведение метода, либо меняют лишь способ достижения того же результата, либо каким-либо косметическим образом влияют на возвращаемое значения 3 - это необходимо для сохранения обратной совместимости при рефакторинге или изменении метода, если остальной код, который эту функцию вызывает отрефакторить не получается по каким-либо уважительным причинам 4 - когда этот необязательный параметр просто присваивает параметру значение по-умолчанию из множества возможных для этого параметра значений
Если метод при наличии необязательного параметра ведет себя совсем по-другому, возвращает другой тип результата, включает слишком массивный кусок кода, который обычно не задействован или совершает еще какие-либо странные действия, то значит лучше разделить такой метод на несколько других.
В случае parse_ini_file необязательные параметры лишь декорируют результат и привносят в него дополнительные сведение, но контекстное поведение функции никак не меняется - это по прежнему парсинг ini файла.
>>963258 Думаю, в твоем случае поведение метода уже завязано на имени getValue, т.е. получить значение. Если при вызове getValue ты получаешь целую секцию, то это уже слишком большое изменение результата. Я ожидал конкретно значение из секции, а получил всю секцию. Лучше создай метод getSection.
>>963203 > Смотри, что выводится в HTML-коде, что пишется в логи Симфони и лог ошибок PHP. Ну бля. Я вижу, что он не может подгрузить css, и все. https://pastebin.com/3xkPYVQP
>>963258 И еще один совет чисто по стилистике от меня. Если вызов функции без указания необязательного параметра, подразумевает, что этот параметр должен быть просто проигнорирован, то не присваивай ему false, а лучше присвой null. Т.к. "возможность" присвоить аргументу false, означает, что ему также можно присвоить и true, что будет странным, если наличие значение у аргумента при вызове не подразумевает bool значение.
Не могу найти инфу по сути работы конструкции с if...else логического или какого-то там типа: public function getImage() { return ($this->image) ? '/uploads/' . $this->image : '/no-image.png'; }
это ? аргумент : аргумент - или я хз, что-то такое было даже у ОПа в учебнике, помогите найти
Именно! Потихоньку пишу такую на (клиент: js + nwjs) <=> (сервер: rest api на php + mysql).
Конечно, ломать меня никто не будет, но тема зацепила, и из всех вариантов SRP тут подходит замечательно: бесплатно и можно реализовать своими силами (и черт возьми, как же интересна оказалась простая математика).
Алсо, иногда вижу в тредах про программирование "нахуй матан в пхп лол ты че нуб?". Абсолютный пиздеж, очень нужна в любом языке. Жалею, что в школе и в универе на матишу забивал болт, это блин чудо-наука.
>>963357 Судя по описанию, стандартная шарага, где учат на примитивном уровне как на видеокурсах с ютуба. Про трудоустройство ясно пиздеж, или в шараги какие устраивают с никакими перспективами (хотя после курсов с ютуба и так пойдет). Сертификаты пригодятся конечно, но вангую за них с тебя отдельно баблосы обдерут, т.е. ты эти сертификаты и без них так же получить можешь, записавшись и сдав экзамен помимо их шараги.
Нужно делать отдельную функцию. Неудобно, когда функция может возвращать разные типы данных. Получить параметр конфига - одна функция, получить весь конфиг - другая.
В PHP есть ошибки проектирования и не стоит их повторять.
И проверяй, все ли сделано как надо. Правильно ли указан путь к файлу, относительно нужной ли папки?
Если ты используешь assetic, то там 2 варианта:
- либо по этому пути должен располагаться файл/ссылка на файл (ну например если ты запустил скрипт и он скопировал нужные файлы - это для продакшена) - либо этот путь должен обрабатываться контроллером, который сгенерирует и отдаст нужное содержимое. Это обычно используется в среде разработки (чтобы не надо было руками запускать скрипты обновления файлов)
Сделал все, что там написано? Бандл добавил? Конфиг прописал?
Если не используешь assetic то стоит для начала научиться правильно функцию asset использовать.
assetic кстати как раз умеет отдавать или копировать файлы в нужные папки, если его настроить.
И надо читать документацию, а не повторять то, что делают в видеоуроках, особенно если там используется другая версия Симфони. Нужно понимать, что значит каждая строчка кода в твоем приложении, а не слепо их копировать откуда-то.
>>963203 Что-то еще больше вопросов стало. Есть серверное, а есть клиентское кэширование (http)? В общем, как мне кэшировать страничку динамическую, если пользователь ввел данные на эту страницу и они обновились в бд и при перезагрузке ему нужно вывести эту же страницу только с новыми данными (а они берутся из старого кэша, а не из бд)? Как обновлять кэш при POST запросе? Для этого нужно использовать редис, nginx или memcashed? Почитал англоязычный ресурс, там написано, что кэш удаляется при пост запросе, т.е. при удаленном кэше данные подргужаются из бд, а потом опять кэшируются? Я запутался. Нет ли где-нибудь ссылки на гитхаб с реализацией подобного кэширования дин. страницы? В докладе что-то про сокеты говорится, но разрабы с моей работы говорили, что создавать на каждое соединение по сокету при хайлоаде - не эффективно.
Взялся за задание "Вектор", ебался 6 часов, не понял главного - как здесь использовать методы, у меня из-за них одни проблемы, почему не понаписать просто функций? Я поместил объекты(сотрудников) в массив, но методы не вызываются так как функции, им нужен объект или ещё нашёл такой способ Employees::CalculateTheSalary($employees); Где $employess - массив внутри которого объекты. Так на кой, черт, делать метод, когда лучше сделать функцию? Откройте мне глаза, зачем, нужны, методы? Может быть, возможно, что бы сократить сплошной текст и соотнести метод к определенному классу и что бы этим методом мог воспользоваться только объекты класса, но в моём случае нет объектов к которым я мог это применить, у меня, блядь, массив с объектами. Так же я нахуярил методов в суперклассе, но вызывать мне их совсем не хочется, потому что, блядь, массив. Можно заюзать форич в теле программы, что бы по одному дёргать объекты из массива засовывать его в функции, отличное блядь, решение, но как оказалось я проебал ещё пол часа, что бы понять, что каждый раз вызывая метод - я стираю все переменные внутри, и мой блядь, счетчик зарплат обнулялся.
Объясните, как и с какой целью в этой программе использовать методы.
>>963535 Чем тебе методы не функции? У тебя Employees и Department. По логике очень схожие сущности. Может ты хотел сделать Employee (один наемный рабочий), у которого свои свойства и методы, соответственно у Department будет свойство employees в котором будет массив экземпляров класса Employee. Если у Employee будет метод ::getSalary(); то к примеру в Department может быть метод ::getTotalSalary() который бы обходил в цикле всех своих сотрудников и у каждого вызывал бы getSalary() и доплюсовывал в какой нибудь $total который бы потом этот метод возвращал
>>963535 И ещё вопрос, почему Employees наследуется от Department, по логике Department более узкое понятие, специфическое понятие, а Employees более широкое, если абстрагироваться от кода внутри них на скрине, то по логике Department должен наследоваться от Employees (К примеру: Политический митинг extends Группа людей)
>>963542 >Если у Employee будет метод ::getSalary(); то к примеру в Department может быть метод ::getTotalSalary() который бы обходил в цикле всех своих сотрудников и у каждого вызывал бы getSalary() и доплюсовывал в какой нибудь $total который бы потом этот метод возвращал Зачем вообще создавать два метода? Почему не одну функцию? Предлагаешь на любое действие -- создавать пару методов? >getPage >totalGetPage >getCofe >totalGetCofe
>>963551 >Зачем вообще создавать два метода? Почему не одну функцию? Потому что Employee это общее понятие, у тебя может быть "Архитектор" или "Уборщик", разные условия оплаты, значит у них метод подсчета зарплаты может отличаться. >Предлагаешь на любое действие -- создавать пару методов? Может оп лучше объяснит, каждый метод должен описывать какое-то целостное действие.
>>963556 > у тебя может быть "Архитектор" или "Уборщик", разные условия оплаты, значит у них метод подсчета зарплаты может отличаться. В условиях задачи написано, что з/п может различаться только из-за ранга и статуса "начальник", что учтено в методе.
>>963562 Т.е вот эта конструкция $totalSalary=Employees::CalculateTheSalary($employees); Является нормой? Метод CalculateTheSalary считает зарплату каждого и возвращает $totalSalary.
>>963563 Вот тот switch не нужен, это должно быть внутри метода Employee - он должен вернуть уже посчитанный для конкретного employee конечную цифру зарплаты, Департамент вообще не должен знать о том, как считать зарплаты своим сотрудникам.
>>963565 >>963562 Если у тебя добавится ещё с десяток rank'ов сотрудников - у тебя свич станет головной болью, придется заводить константы потому что на каком то этапе ты перестанешь понимать кто такой rank = 1, а кто такой rank= 15
>>963568 Проблема свитча тут в том, что ты делаешь комментарии для того, чтобы не перестать понимать свою хуйню, вместо того, чтобы завести какой-нибудь массив или словарь, в котором компактно будет описано, сколько и чего нужно создать. Это как минимум.
>>963568 Вместо свича при подсчете - сделай в методе getSalary() у Employee подсчет конечной цифры зарплаты, которая бы больше никак не изменялась, она должна отражать зарплату работника всецело, департамент не должен ничего с ней делать, департамент вообще ничего не должен знать о её пересчете или подсчете. в итоге у тебя останется простенький цикл вида пикрелейтед
>>963573 Вот хоть убей, я не вижу способа в getSalary подсчитать зарплату без свича или условий. Поделись секретом, чего я не вижу. Напоминаю работники в массиве $employees, у работника есть свойсва rank и baseSalary. Открой мне глаза.
>>963578 ... Я думал ты пытаешься заставить меня убрать свич, что у тебя есть гениальное решение без условий. ... В департаменте вообще ничего не считается, пока. Ты же видел скрин, я и зарплату по сотрудникам и тотал по зарплате посчитал в одном методе, метод этот принадлежит Empolyees, никакого отношения к депортаменту он не имеет. Ты хочешь разнести эти действия по разным методам...
>>963584 > https://2ch.hk/pr/src/958715/14908686745960.jpg Employees в принципе существовать не должен, департамент состоять должен из массива в котором единицей является "1 работник", а не из массива "группа работников"
>>963590 >>963591 Я не понимаю, чего в итоге ты хочешь. Департамент ничего не считает. В массиве в 1 ячейке лежит 1 работник, у которого есть поля, по полям можно понять к какой профессии он относится, хоть это и не важно.
>>963556 >Может оп лучше объяснит, каждый метод должен описывать какое-то целостное действие. Он ещё говорил мне, что это нужно для удобства. Видишь класс Работник - вот тут все действия для работы с ним: нанять, уволить, посчитать зарплату, исходя из ранга и профессии - и т.п. То есть у объекта Работник должны быть все методы работы с ним. >>963562 >В условиях задачи написано, что з/п может различаться только из-за ранга и статуса "начальник", что учтено в методе. Код должен быть гибким. Например, может понадобиться внести подсчёт выкуренных сигарет, выпитой воды, туалетной бумаги и т.п. бреда, который там и так был про кофе и страницы. Вот методы у суперкласса Работник должны позволять легко и компактно это всё вносить.
Мимо выше решал первую часть Вектора до антикризисных мер
>>963568 Говнокод тут в том плане, что ты мог сделать создание работников - методом класса Работник, у которого в аргументах стояло бы: профессия, количество работников, которых нужно создать, ранг, боссы или нет. И в этом методе уже был бы цикл for, который создавал экземпляры класса, при этом по профессии ещё наделял их кофе и страницами (для этого профессии должны быть классами, унаследованными от Работника). Вот ещё тебе плюс в пользу использования методов.
>>963654 Считает верно, но объясни вот это условие: >if ($creditBalance < 4000) Что оно означает, почему никак не привязано к имеющимся значениям? Было выше такое решение у анона, это неверное решение в том плане, что поддержке не поддаётся: какие 4000 тысячи, что это за условие - не понять.
>>963658 Да, но в данном случае и обозримом будущем параметр "профессия" не играет роли, так зачем плодить классы для деления работников на эти самые профессии?
>>963673 Ну не обязательно создавать классы под профессии, действительно, однако метод для создания работника в классе Работник тогда просто должен содержать то, что ты наговнокодил, чтобы было чётко и понятно, чтобы всё делал этот метод, а не циклы громоздкие при создании.
>>963668 Ты сам не понимаешь, о чём говоришь. Куда прибавляется тысяча, если у тебя if ($creditBalance < 4000)? Это тут без этой тысячи, но с процентами? С какой такой стати? Что это за условие вообще? Также условие для работы цикла for непонятное и не универсальное - если меньше 20 месяцев. С какой такой стати? А если сумма кредита будет 80 тысяч, то там больше 20 месяцев будет выплачиваться - всё сломается. Поэтому там лучше условие вот такое: если сумма кредита не ровна нулю.
>>963674 Вот уже понятнее, просто я сразу не дошёл до того, зачем нужны методы(и сейчас смутно представляю дальнейшие действия). я вчера только статью про ООП прочитал.
>>963675 Этого поддержу, не могу въехать откуда эти 4 тысячи вылезли. А за условие в цикле не ругай, так ОП накодил.
Делаю файлообменник и встал вопрос с контейнером. Короче делаю такой то контейнер $container = $app->getContainer(); $container['twig'] = function(){ $loader = new \Twig_Loader_Filesystem('../app/Templates/'); $twig = new Twig_Environment($loader); return $twig; }; И все работает, проблема в том, что с таким подходом не работает автодополнение кода для объектов в контейнере. Его можно как-то подрубить туда?
>>963742 Обычно делают так: / @var Twig_Environment $twig */ $twig = $container['twig'];
>>963068 Признайся, что у тебя просто низкая квалификация и ты пришёл сюда поныть. Среди одногруппников 4 человека пишут код за деньги, двое из них как раз на C#.
>>963068 PHP не виноват, что ты просто дно. Если после нескольких лет кодинга на джаве и шарпе ты не можешь себе доширак обеспечить, то мкарьера офис-менеджера ждет тебя.
>>962219 Оказалось, что PHP на моем компьютере не поддерживает целые числа больше 2147483647. Поэтому при вычислении $v = pow(2, $x) % $N получаю 0 или число 2 ^ n , что есть абсурд, ибо как я понял, оно должно получаться довольно длинным. Эпик фэйл. Придется использовать библиотеки, позволяющие работать с большими числами?
@var позволяет указать тип переменной и пишется на предыдущей строке, до переменной. Но недостаток тут в том, что тип надо будет указывать каждый раз, как ты берешь что-то из контейнера. Решения проблемы - описать именно сервисы в самом контейнере:
1) сделать свой класс поверх контейнера (либо унаследовать, либо использовать делегирование), где на каждый сервис будет метод вида
public function getTwig() { return $this->container['twig']; }
Перед методом мы пишем phpdoc @return SomeClass и теперь IDE будет распознавать тип значения при вызове $x = $container->getSomething();
Это максимально совместимо с разными IDE, но требует создания лишнего класса.
2) Использовать плагин для IDE, который умеет читать конфиги конкретного DI контейнера. Применимо к фреймворкам вроде Симфони, где сервисы описываются в конфигах.
Методы - это действия, которые можно делать с одним конкретным объектом. Они могут считать и возвращать какую-то информацию об объекте или что-то в нем менять. Ну для объекта Работник могут быть такие методы:
- получить текущую зарплату - повысить ранг - сделать боссом
Для Департамента - посчитать суммарную зарплату, посчитать число сотрудников, уволить всех, поменять босса, найти сотрудников определенного типа и тд
То есть подумай, какие действия ты хочешь делать с объектом и какие методы понадобятся.
Одна из идей ООП в том, что объект содержит как информацию о какой-то сущности (поля), так и действия, которые с ней можно сделать (методы).
> А за условие в цикле не ругай, так ОП накодил. Можно поменять, если не нравится.
Разные классы нужны, если одно и то же действие для разных профессий делается по-разному. Ну например, подсчет зарплаты идет по разным формулам для инженера и для менеджера (например у менеджера зарплата зависит от опыта, а у инженера от ранга). Вообще, варианта тут два:
- сделать профессию свойством класса Работник. Это работает, если у всех профессий все считается одинаково. Минус - для добавления новой профессии надо править класс - сделать каждый класс отдельной профессией. можно менять методы расчета для разных профессий, минус - нельзя так просто поменять человеку профессию (так как надо будет создавать новый объект и везде во всей программе заменять старый на новый, что часто невозможно).
Считать зарплату можно тоже по-разному, можно сделать метод у Работника, можно попробовать сделать сторонний объект-калькулятор зарплаты (выгода от второго варианта - можно разом поменять базовую ставку всем, так как она хранится в калькуляторе).
Ты не учел проценты, там еще проценты есть, не только комиссия. И что если мы поменяем сумму комиссии или месячную выплату - твое число 4000 тоже само поменяется?
Тогда метод логично сделать статическим. Или вообще отдельной функцией. Ибо неправильно создавать одного Работника, только чтобы он создал еще нескольких.
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!) - если остаток маленький, выплачиваем сколько осталось и уходим - иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
> То есть у объекта Работник должны быть все методы работы с ним.
В этом и идея ООП, что вместе собраны данные (поля) и методы для выполнения действий с ними. Ну условно говоря, представь себе например класс Лифт. "текущий этаж", "открыты ли двери" - это состояние , а "поехать на N-й этаж", "открыть двери" - это методы, меняющие состояние лифта.
Было бы неправильно сделать например класс Лифт только со свойствами, а действия выше в виде отдельных функций.
Да, с группами будет неудобно если тебе надо повысить зарплату одному работнику из группы - код переразбиения групп сложный будет. Проще с отдельными объектами, пусть даже так уйдет чуть больше памяти, но у нас там не миллион работников, чтобы о ней беспокоиться.
Ты бы код дал ссылкой, а не скриншотом, как его читать?
По коду:
"A наследуется от B" значит, что A является разновидностью B (по английски получается короче: A is B). Например, Банк - это Организация, с дополнительными особенностями (наличие банковской лицензии) потому класс Банк можно наследовать от класса Организация, добавив поле с номером лицензии и методы вроде "внести вклад".
Также, при наследовании мы должны соблюдать совместимость. Мы всегда можем передать объект класса B в код, который рассчитан на объект класса A, и этот код должен работать корректно (принцип замещения Барбары Лисков). В примере выше, если у нас есть функция, которая считает сумму налога на Организацию, в эту функцию можно передать Банк и она должна работать правильно. Так как Банк это разновидность Организации.
В твоем случае "Работники" - это не разновидность Департамента. Наследование применено неверно.
Важно понять этот принцип, а не наследовать все от всего.
Классы называются в единственном числе, не Employees, а EmployeeGroup. Но я бы советовал так не делать, а делать 1 объект = 1 сотрудник, иначе трудно будет например повысить ранг только одному человеку в группе - надо будет переразбивать группу, сложно.
Имена методов пишутся с маленькой буквы, начинаются с глагола: сделайЧтоТо(). Артикль the не используется.
Если у тебя у ГруппыРаботников есть метод вроде посчитатьСуммарнуюЗарплату(), то ему не надо ничего передавать - ведь в объекте и так есть информация об этих работниках. Обычно метод предназначен для выполнения каких-то действий с объектом, с его полями.
> не понял главного - как здесь использовать методы, у меня из-за них одни проблемы, почему не понаписать просто функций?
В этом и идея ООП, что в объекте вместе собраны данные (поля) и методы для выполнения действий с ними. Ну условно говоря, представь себе например класс Лифт. "текущий этаж", "открыты ли двери" - это состояние , а "поехать на N-й этаж", "посчитать высоту", "открыть двери" - это методы, работающие с состоянием лифта.
Было бы неправильно сделать например класс Лифт только со свойствами, а действия выше в виде отдельных функций.
В этой задаче тебе надо правильно определить, какие у тебя будут объекты, какие с ними можно делать действия.
> Я поместил объекты(сотрудников) в массив, но методы не вызываются так как функции, им нужен объект Да, потому что метод - это часть объекта. Ты же не можешь прочитать поле объекта, не имея самого объекта.
> Откройте мне глаза, зачем, нужны, методы? Чтобы сразу было видно, какой метод к какому объекту относится. В случае с функциями, это не понять, особенно если программа большая и у тебя тысячи функций, они просто свалены в кучу. А в ООП все методы аккуратно разложены по разным классам. Каждый класс имеет свою зону отвественности и решает свою задачу.
Также, методы позволяют нам использовать инкапсуляцию. Это когда мы делаем поля приватными и доступ к ним можно получить только через методы. Таким образом мы можем к примеру запретить ставить сотруднику ранг больше 3, а если бы у нас было публичное поле, то мы такое ограничение поставить не могли бы.
----
Суть инкапсуляции в том, что класс скрывает (инкапслирует) в себе логику работы с данными и сами данные, а наружу выставляет методы. Пользователю этих методов не важно, как класс устроен внутри, как он хранит данные, ему достаточно вызвать нужный метод чтобы получить результат.
Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему). Также, это упрощает изменение кода: если какое-то свойство имеет уровень private то доступ к нему возможен только из того же класса и тебе не надо бегать по всему коду и смотреть что там с этим свойством делается, тебе достаточно просмотреть один файл с этим классом.
Инкапсуляция это хорошо. Так как весь код, который занимается одной задачей, оказывается заключен внутри одного класса. Противоположный случай это когда код (или знание о его внутреннем устройстве) вылезает из класса и размазывается по всей программе.
Если проводить аналогии, то можно представить кофе-машину. Ты нажимаешь кнопку (=вызываешь публичный метод) и получаешь кофе (=результат вызова этого метода), при этом ты не видишь что происходит внутри нее и тебе не надо в этом разбираться.
----
> но в моём случае нет объектов к которым я мог это применить, у меня, блядь, массив с объектами. Это значит, что ты не смог пока придумать решение задачи, соответствующее идеям ООП, и разбить код на отдельные классы, а пытаешься по старой привычке писать все вперемешку.
> что каждый раз вызывая метод - я стираю все переменные внутри, и мой блядь, счетчик зарплат обнулялся. Это и с функциями так, локальные переменные создаются при входе в функцию и уничтожаются при выходе из нее, ты разве не знал? Так и надо, они предназначены для хранения каких-то временных данных, которые нужны только внутри функции. Условно говоря, ты что-то на листоке посчитал, запомнил результат, а листочек выбросил.
И посмотри, ниже я дал ссылки на статьи с описанием видов отношений между классами.
Так может быть удобнее, одна функция считает зарплату одного конкретного работника, другая - сумму по департаменту. Зачем все писать в одну огромную функцию?
И эти 2 метода он предлагает сделать в разных классах.
По коду: не ставь пробелы вокруг стрелки, ставь их вокруг математических операций. для switch всегда стоит написать блок default на случай если ты по ошибке поставишь неправильный ранг, чтобы сразу это заметить.
Копипасту в switch стоит убрать, лучше там задавать только коэффициент.
Нет, не норма. Если у тебя есть объект, представляющий группу работников, то для расчета зарплаты в метод не надо ничего передавать - эта информация уже есть в объекте.
Ты пытаешься писать код не в ООП-стиле, а как обычный процедурный код из отдельных функций.
А ты решал предыдущие задачи на ООП, про тесты и вопросы и тд?
> Есть серверное, а есть клиентское кэширование (http)? Да. У браузера есть кеш, когда ты переходишь с одной страницы сайта на другую, браузер может не скачивать повторно CSS-файл, а взять из кеша. Или взять из кеша и спросить сервер, не изменился ли он за это время? Управляется это кеширование HTTP заголовками, которые отдает сервер.
Аналогично, если ты второй раз заходишь в тред на сайте, в котором уже был, браузер может взять страницу из кеша, если сервер это разрешил.
Разумеется, кеш важно настроить так, чтобы при изменении файла на сервере браузер не пытался бы использовать устаревшую версию из кеша.
Такое кеширование хорошо подходит для статических файлов, но не всегда работает ддя динамических страниц, так как они генерируются каждый раз заново.
И разумеется это кеширование не работает если пользователь впервые зашел на сайт или давно (несколько часов/дней) на нем не был и файлы в кеше оказались вытеснены файлами других сайтов.
Серверный кеш - это другое, это когда приложение сохраняет данные в кеш, чтобы в слудующий раз сэкономить время на их получение, или когда нагрузка на сайт очень высокая (вряд ли это твой случай) и хочется разгрузить базу данных. Надо помнить, что кеш это скорее костыль, которым не от хорошей жизни пользуются, если можно без него обойтись, то хорошо.
На сервере кеширование делать можно на разных уровнях: можно кешировать какие-то промежуточные данные, можно куски HTML разметки, можно целую страницу. Чем больше ты кешируешь, тем сложнее отследить, когда надо сбросить/обновить кеш.
Для начала тебе надо понимать, что, где ты будешь кешировать, как отслеживать изменения исходных данных. От этого зависит, как он будет реализован.
Стандартного решения, которое подходит всем, нет. В каждом проекте надо делать по-своему. Кеш это не программа, которую можно установить и все само заработает. Надо править код приложения скорее всего.
> В общем, как мне кэшировать страничку динамическую, если пользователь ввел данные на эту страницу и они обновились в бд и при перезагрузке ему нужно вывести эту же страницу только с новыми данными (а они берутся из старого кэша, а не из бд)? Первое, о чем тебе стоит подумать - это можно ли обойтись без кеша (тем более что судя по твоим вопросам, ты вообще пока плохо понимаешь, как он работает и какие есть подводные камни). Ведь данные на странице могут измениться, ну представь, что выводится список последних комментариев, и где-то на другой странице добавлен комментарий, надо обновить этот список. Или представь, что в углу страницы выводится город пользователя - тогда целиком страницу кешировать нельзя, так как для разных пользователей город разный.
> Как обновлять кэш при POST запросе? Очистить либо обновить содержимое ячейки кеша. Как именно зависит от того, какой ты кеш используешь.
> Для этого нужно использовать редис, nginx или memcashed? Ты все смешал вместе. Редис - это хранилище, нгинкс - это веб-сервер. Хотя их можно использовать вместе.
> Почитал англоязычный ресурс, там написано, что кэш удаляется при пост запросе, Бред. Это наверно какой-то частный случай, то есть на каком-то одном сайте сделано так, что при POST запросе удаляется какой-то элемент кеша. Это не рецепт, который подходит всем.
> В докладе что-то про сокеты говорится, но разрабы с моей работы говорили, что создавать на каждое соединение по сокету при хайлоаде - не эффективно. Если ты не понимаешь о чем речь в докладе, то надо сначала с ним разобраться, прежде чем браться за кеширование.
В README хорошо бы кратко еще написать, как развернуть проект (залить дамп в БД, прописать пароли в конфиге, запустить композер и тд)
Папки vendor в репозитории не должно быть, убери ее, закоммить, добавь ее в гитигнор, закоммить снова, верни на место. Тот, кто скачает твой код, сделает composer install и нужные версии зависимостей, прописанные в composer.lock, установятся. Нет никакого смысла копировать сторонние библиотеки в твой репозиторий (и еще в тысячу других), надо стремиться чтобы там был только твой код.
> "dir" => "/var/www/fileshare.home/files" Это неудобно, лучше сделать автоматическое определение текущей папки.
> 'driver' => 'mysql', Хорошо бы в конфиге писать только те настройки, что пользователь может поменять. Ведь если мы тут пропишем другой тип БД, все перестанет работать, так как твои запросы написаны под mysql?
И зачем там final? Есть какие-то веские причины почему тут запрещено наследование?
https://github.com/Si0n/fileshare-project/blob/master/system/dependencies.php#L26 > $container['App\Controller\File'] = function ($c) use ($app) { По умолчанию контейнер при повторном обращении не создает новый экземпляр класса, а возвращает старый. Для контроллера это нелогично, так как удобнее, когда один контроллер обрабатывает один запрос и выкидывается, а не используется для обработки нескольких запросов. Лучше сделать, чтобы каждый раз создавался новый.
> (str_ireplace('index.php', '', $container['request']->getUri()->getBasePath()) Это коряво. А что, если папка называется index.php? Удалить имя файла из пути удобнее через dirname().
Насчет логгера - хорошо бы для продакшена логгировать поменьше, чтобы не копились мегабайты ненужных логов. А логгировать на продакшене только важные вещи.
https://github.com/Si0n/fileshare-project/blob/master/system/controller.php#L19 > public function __get($var) { Я не советую тут использовать магию, так как при опечатке в имени свойства ошибка не будет замечена. Также непонятно почему это публичный метод. В задачи контроллера входит предоставлять другим классам сервисы? Я думал, это задача контейнера.
> public function setModel($model) { Непонимание MVC. Между контроллерами и моделями нет соответствия один-к-одному. Плюс твой метод подразумевает, что одному контроллеру можно давать разные модели, и он в любом случае будет корректно работать. Не думаю , что у тебя это так.
> abstract public function index($request, $response, $args); Название неудачное, лучше handleRequest(). И тайп-хинты проставить.
> use App\Local\File as LocalFile; Этого лучше избегать, синонимы запутывают чтение кода, человек не робот, чтобы в уме их преобразовывать в имена классов.
> require '../vendor/autoload.php'; > require '../config/config.php'; Это логично перенести в бутстрап.
> $capsule = new Illuminate\Database\Capsule\Manager; И это тоже.
Вот тебе кстати дополнительная задачка для лучшего понимния архитектуры: сделай скрипты, которые позволяют из командной строки загружать или удалять файлы в файлообменник. Например так:
> $uploaded_files = $this->{'App\Controller\File'}->upload($request); Это неправильное использование контроллера. Контроллер это не сервис, чтобы его так можно было вызывать. Контроллер обычно получает на вход запрос и выдет на выходе HTTP ответ, например HTML страницу.
> $app->get('/files/{file_id}', function ($request, $response, $args) use ($app) { > //Need to check file owner > $this->{'App\Controller\File'}->files($request, $args); тут почему-то не используется $response
> "document" => ["title" => "Home page", > "styles" => ["/css/bootstrap.min.css", "/css/style.css"]] Зачем эти многоэтажные массивы? Лучше либо отдельные переменные, либо объект с полями и методами. Ну и передавать одни и те же стили для каждой страницы не очень удобно, может стоит как-то их по умолчанию задать?
Кстати, добавлять скрипты к странице (а также переопределять title) можно через наследование шаблонов в твиге, если оставить в head зону для их добавления.
> "upload" => "/upload" Неудачное название, трудно понять, что это? URL для формы? Тогда лучше его там же и прописать либо получать какой-нибудь функцией.
> Весь функционал приложения содержится в модели. Контроллер и вью предоставляют лишь возможность пользователю взаимодействовать с моделью и отображать данные из нее. К примеру, если мы делаем сайт объявлений, с такими функциями, как "добавить объявление", "удалить объявление", "найти объявления по критериям", то для каждого действия где-то в модели должна быть функция, которую можно вызвать. Если выкинуть все контроллеры и вью, то мы все равно можем добавлять объявления, вызывая методы модели.
https://github.com/Si0n/fileshare-project/blob/master/model/file.model.php > public function setFile(FileController $file) { Здесь что-то очень неправильное. Контроллер это не модель, чтобы хранить информацию о файле и иметь методы вроде getDescription(). У контроллера могут быть только методы вроде handleRequest(). А методы вроде getDescription() должны быть как раз у модели. Перечитай урок по MVC.
> Я не могу представить, как должно выглядеть следующее: Компания создаёт Департамент, который создаёт Работников. Как, например, в этом случае потом отдельно создавать работников и включать их в компанию? Не могу осмыслить...
компания = создать Компанию; департамент = создать Департамент; компания->добавитьДепартамент(депармамент); сотрудник = создать Сотрудника(); депарматент->добавитьСотрудника(сотрудник);
И так далее.
> То есть я вообще неверно понимал, что Компания должна создавать Департаменты, Департамент должен создавать Работника... Получается, этим всем могут заниматься простые функции, а методы в этих классах работают только с подсчётом всего по компании или департаменту?
Департамент может создавать Сотрудников, но это делает наш код менее гибким, так как может быть мы хотим создать его как-то по своему, как-то его настроить. А в твоем случае получается вообще без компании нельзя создать отдельно сотрудника. То есть это лишние ограничения, и не очень понятно, ради чего.
И там еще есть один момент. В твоем варианте, чтобы добавить новую профессию, надо править существующий код. В моем - просто добавить новый класс, не трогая старый код. Гибче. А у тебя нало программу в нескольких местах править (свитч как минимум). А представь, когда она огромная, и надо еще эти места все найти.
Ну и бывают случаи, когда код править нельзя - если это например сторонняя библиотека с классами.
Такое имело бы смысл, если бы сотрудник не мог существовать без Компании. Но в теории, он может - он может уволиться из одной компании и перейти в другую например. Или поменять депарматент.
Такое можно было бы применить например для Департамента - если он не может существовать вне Компании, то можно сделать в компании метод создатьДепартамент(название), но опять же я тут особой выгоды не вижу, мне кажется удобнее, когда мы создаем Департамент любым способом и добавляем в Компанию.
> Ну, тогда можно ведь в конструктор добавить $this->experience = $experience;, а в аргументах поставить по умолчанию $experience = false, чтобы уже имеющииеся работники у нас создавались нормально? Горожу что-то непонятное, конечно.
Ну так это надо в нескольких местах править. А в моем варианте - только в классе с профессией. Идея ООП в том, что то, что относится только к одной профессии, желательно поместить в ее класс, чтобы у каждого класса была своя зона ответственности. А ты пытаешься особенности профессии размазать по всей программе, вместо того, чтобы собрать в одном классе.
Вот у тебя например зарплата Инженера хранится не в его классе, а в Департаменте. Тут конечно есть своя логика (компания ведь назначает зарплату), но может быть удобнее было бы это хранить именно в классе Инженера.
> class Manager extends Employee { > public $rank = 1; > public $boss = false; Это писать не надо, при наследовании все свойства наследуются из родительского класса.
> нельзя делать апдейт поверх данных, Если речь о добавлении, переименовании таблиц и колонок, то можно. Если изменение типа колонки - то надо чтобы при конвертации ничего не потерялось. Но вообще БД по максимуму пытается сохранить данные. Более подробно можно почитать в мануале на англ: https://dev.mysql.com/doc/refman/5.7/en/alter-table.html
Или там постгрес? Самостоятельно тогда найти мануал постгрес по ALTER TABLE, он есть и на англ, и в хорошем переводе.
> Я ещё предполагал, что есть некоторая договоренность между программистами делать для каждой таблицы колонку с id. На практие они почти везде нужны, так как например для удаления или обновления надо указать, какую именно запись мы хотим обновить. Но первичный ключ можно делать и составным.
> for ($credit=40000; $credit>0; $credit=($credit$persent+$service)-$payment) Слишком много кода в шапке цикла, тяжело читать, надо перенести формулу в тело.
> if ($credit+$service<5000) Не учтен процент
> $credit=($credit+($credit0.03+1000)); Формула повторяется второй раз.
> Почему бы просто не сделать это всё свойством класса? > Смотришь на класс и свойства - видишь кофе, зарплату, страницы, а так надо смотреть в метод addEmployee, чтобы это всё узнать или поменять?
Так там есть условно говоря 2 зарплаты:
- базовая ставка для данной профессии - реальная зарплата с учетом ранга и статуса босса
Первое может быть свойством. Второе - не стоит делать свойством, так как оно вычисляется из базовой ставки, ранга, статуса босса и при изменении любого из них должно автоматически пересчитываться. Это сложно, проще сделать метод, который считает реальную зарплату каждый раз заново.
Ну вот в итоге так и сделано, как я и хотел. Только в switch надо добавить default на случай, если мы ошиблись и поставили неправильный ранг, чтобы прервать программу.
> Я помню, ты всегда говорил, что всё то, что может вычисляться, не надо хранить, но если мы представим, что нам надо создать миллионы экземпляров работников, то это будет большей нагрузкой, чем просто хранить свойства в их классах, разве нет?
Не факт. Ведь нам все равно эту зарплату миллион раз считать придется, только в другом месте кода. И для хранения свойств ведь больше памяти пондобится. Это надо мерять и проверять. И у нас нет миллиона работников в задаче.
Но главное тут не производительность, а то, что нам надо будет автоматически при изменении ранга как-то пересчитвать и зарплату, если она хранится в свойстве. замучаешься это писать.
> $regexp = '/ + /u'; Тут можно обойтись без дублирования пробелов, например так: {2,}
> //проверяем, чтобы первый символ был не пробелом{ Тут может trim() проще использовать?
> $other = mb_substr($text, $second); > $first = mb_strtoupper($first); > $text = $first . $other; Это можно записать в одну строку без лишних переменных.
Так в общем верно, но закомментированиые куски кода стоит убрать.
Доктрина использует прокси-классы для ленивой загрузки. Ну допустим у тебя в классе Тест есть поле Автор. По идее, когда ты загружаешь из БД один Тест, доктрина должна загрузить и создать объект Автора. Если у Автора есть другие связи, она и их должна заполнить. Так мы скоро придем к тому, что надо половину базы данных в память загрузить.
А не загрузить - нельзя, так как иначе непонятно, как получить автора теста.
Потому Доктрина использует прокси-классы. Прокси-класс наследуется от сущности (чтобы проходить все тайп-хинты) и генерируется автоматически. Для каждого метода в исходном классе генерируется метод-обертка. Эти классы кладутся по моему во временную папку, которая задается в конфиге Доктрины.
Вместо реального Автора доктрина вставляет объект-прокси. У этого объектавсе поля пустые, кроме id, и при вызове любого метода, кроме getId() (например getName()), сначала запускается загрузка данных из базы, эти данные загружаются в поля объекта, и только после этого вызывается исходный метод. И таким образом, получается "ленивая" загрузка, прозрачно для твоего кода.
Это объясняет ограничения, которые доктрина накладывает на классы - например, запрет использовать публичные поля, так как обращение к ним невозможно перехватить в классе-наследнике.
Можешь попробовать сам написать пример прокси-класса, чтобы лучше понять.
Аналогично прокси-классы делаются и для коллекций.
Я еще напомню, что Доктрина это Data Mapper - она пытается создавать видимость, что все твои классы находятся в памяти и скрывает факт, что на самом деле данные загружаются и объект создаются по мере надобности. И что она не требует твои классы знать о ней и о базе данных - ты можешь вообще убрать БД, создавать объекты руками и твой код с ними будет так же работать, как с загруженными из БД.
Для полей еще надо прописывать nullable=true/false. Если есть значения по умолчани, их надо прописать тоже.
> Если я использую Pimple и PSR-4 могу я загрузить этот класс через них? Да, если ты ставил доктрину через композер, то скорее всего ее автозагрузчик уже подключен где-то в vendor/autoload.php, а код в статье для тех, кто хочет подключить его вручную.
Сама по себе программа управления миграциями сделана как набор команд с использованием Symfony Console, потому надо настроить компонент Symfony Console Application (который скорее всего устанавливается вместе с доктриной).
То есть ты создаешь файл, например cli/migration.php, и в нем подключаешь свой бутстрап, настраиваешь Symfony Console Application, добавляешь в него классы-команды доктрины, настраиваешь доступ доктрине к БД. И когда все настроено, запускаешь этот Symfony Console Application, он анализирует командную строку и парамтеры и вызывает нужную команду.
> $application = new Application(); > // ... register commands > $application->run(); Вот его и надо поместить в твой файл.
Не перепутай компонент Symfony Console (который не зависит от фреймворка Симфони) и бандл FrameworkBundle, который является частью Симфони.
Также еще есть вариант просто использовать готовый phar файл, но думаю, написать и настроить файл самому будет интереснее.
> $container['Migrations'] = function () { > return new Migrations(); Это не нужно делать, я думаю.
Также, вполне возможно что эти команды миграции уже подключены в скрипт доктрины bin/doctrine и можно просто вызывать его, возможно, что нет. Можно проверить, запустив bin/doctrine и выведя список доступных команд.
> -configuration это опция чего? Через doctrine:migrations -configuration ошибка о несуществующей команде. Это опция, указываемая, при вызове какой-либо из команд миграции. Если ты изучишь Symfony Console, то увидишь что там есть опции для вывода списка доступных команд, а также вывод списка опций для любой команды.
> Class 'DOMDocument' not found наверно расширение dom не установлено для PHP.
Сделай stat /opt/lampp/... и посмотри владельцев и права доступа. Затем сделай id и посмотри свой id пользователя. Учти что веб-сервер как правило работает от отдельного пользователя вроде www-data.
> Долго ломал голову и исписал не один лист в длинющих таблицах из декартовых произведений. Зато теперь наверно гораздо лучше умеешь делать джойны. Теперь решение более-менее оптимальное.
По поводу задачи про лайки - это строго говоря случай наследования таблиц, и тут есть 3 паттерна, которые легко гуглятся:
Concrete Table Inheritable Class Table Inheritance Single Table Inheritance
Вот из них и стоит выбирать.
Идея с entity_type/entity_id - на мой взгляд плохая, так как не позволяет ставить внешние ключи. Хотя тоже в каких-то случаях имеет право на жизнь.
> с использованием таблицы 'всё_что_можно_лайкнуть'
Промежуточная таблица выглядит как лишнее звено. Например, где гарантия что пользователь и фото не будут ссылаться на один и тот же likeable id? Наверно, тогда проще было сделать likeable_id первичным ключом в таблицах пользователей, фоток и тд.
Ты пытаешься унаследовать от общего предка таблицы пользователей, фото (у которых ничего общего), но есть другой вариант - наследовать таблицы лайков, сделав разные виды лайков. И к ним применить по очереди 3 паттерна выше.
> все лайкабельные сущности в одну таблицу: Ну вот это как раз получилось применение паттерна Single TI к таблицам лайков.
> - Для каждой новой сущности нужно добавлять новый столбец в таблице likes, нужно не забыть добавить уникальный ключ. Это как раз не проблема, проблема в том что можно по ошибке один лайк отнести к 2 сущностям. В БД вроде Postgres от этого можно защититься, добавив на таблицу ограничение CHECK:
ALTE TABLE ADD CONSTRAINT only_one_reference CHECK (like_to_user IS NOT NULL) + (like_to_photo IS NOT NULL) + ... = 1
Их удаляют кроном раз в полчаса по дате модификации обычно. Можешь конечно попробовать не сохранять пустые сессии, в PHP можно сделать свой обработчик сессий, но может лучше использовать нормальное хранилище вроде БД?
>>964060 Спасибо, понял насчет контейнера. Наверное остановлюсь на первом, так выглядит проще всего. Не пойму только одного, я вот загуглил PSR-11 - так вот, раз он ест и в фреймворках реализован, почему разработчики IDE не сделают эти фишки автоматическими? Ну что бы они понимали интерфейс и без лишней мороки дополняли код.
>>964139 Ну так а почему бы не дополнить его по принципу как я описал? Алсо, собираюсь тогда уже сделать обертку для контейнера с методами типа getTwig(), как его следует назвать? ContainerWrapper сойдет?
>>964063 >А ты решал предыдущие задачи на ООП, про тесты и вопросы и тд? Одну решил, во второй там с уловиями проблемы, пришлось скипнуть меня уже отругали, сразу взялся на вектор, в итоге убил 8 часов, но задачу не решил.
>>964070 Доработал цикл, с учётом твоих замечаний, и сделал задачку по подсчету кредита в нескольких банках. ОП или просто шарящий анон, посмотрите решение и дайте советов мудрых. Спасибо. http://ideone.com/4iXPBW
>>964270 $creditSum=39999; //сумма кредита $payment=5000; //ежемесячная выплата $mon=0; // кол-во месяцев (по умолчанию - 0) $homoCreditDownPayment=0; //первый взнос в HomоCredit $softBankDownPayment=0; //первый взнос в SoftBank $strawberryBankDownPayment=7777; //первый взнос в StrawberryBank $homoCreditPersent=1.04; //процент в HomоCredit $softBankPersent=1.03; //процент в SoftBank $strawberryBankPersent=1.02; //процент в StrawBerry bank $homoCreditService=500; // плата за сервис в HomoCredit $softBankService=1000; // плата за сервис в SoftBank $strawberryBankService=0; // плата за сервис в StrawberryBank //Пиздец. Я - индус. $homoCreditTotal=countCredit($creditSum, $homoCreditPersent, $homoCreditService, $payment, $homoCreditDownPayment, $mon, $bankName="HomoCredit"); $softBankTotal=countCredit($creditSum, $softBankPersent, $softBankService, $payment, $softBankDownPayment, $mon, $bankName="SoftBank"); $strawBankTotal=countCredit($creditSum, $strawberryBankPersent, $strawberryBankService, $payment, $strawberryBankDownPayment, $mon, $bankName="StrawbrerryBank"); I LOLED Короче, суть скобок у функций, в которые передаются аргументы, в том, чтобы вот так не инициализировать разные переменные - достаточно прямо в скобках у функции на месте заявленных при создании самой функции элементов указать значения. НЕ >$homoCreditTotal=countCredit($creditSum, $homoCreditPersent, $homoCreditService, $payment, $homoCreditDownPayment, $mon, $bankName="HomoCredit"); А >$homoCreditTotal=countCredit($creditSum, 1.03, 500, $payment, 0, $mon, $bankName="HomoCredit"); Тогда инициализировать ничего не придётся, городить лишнего. А так всё верно у тебя считает.
>>964328 >$bankName="HomoCredit" *просто "HomoCredit" Те, которые повторяются, можно ставить переменными, а индивидуальные значения лучше прямо значениями и вставлять.
Туплю походу, сделал как сказали, в итоге выводит только результат в случае если число в диапазоне 50-60, а в остальных пишет просто успешно. Что не так ?
>>964331 Ещё прочитай своё второе условие: "если x меньше 50 и x больше 60". Ты можешь сказать, что это за число, которое меньше 50 и больше 60?
>>964148 > Ну так а почему бы не дополнить его по принципу как я описал? Ты предлагаешь добавить в PSR-11 интерфейс метод getTwig? PSR-11 нужен для того, чтобы привести разные DI-контейнеры (например Pimple, PHP-DI) к единому интерфейсу: get(), has(). Чтобы не было такого, что где-то getService, а где-то register(). Это позволяет проекту, использующему PSR-11 контейнер, не зависеть от какой-то конкретной реализации. Автодополнение в IDE здесь вообще не при делах.
Сап. Как в Ларавел переписать {{ Form::select('category', $categories_list) }} на html форму? $categories_list = Category::pluck('category_name', 'id');
>>964454 Накидал сам, но не знаю будет ли правильно <select name="category"> @foreach <option value="{{$categories_list->'id'"{{ $categories_list->'category_name'"</option> @endforeach
>>964068 >тут бы ENUM подошел лучше Не люблю использовать ENUM, он не гибкий, тем более если у меня изначально уже не планируется статус 0 и 1, а сразу идет как минимум 3 статуса - нет гарантии, что в процессе не появится 4 или 5 статусов сверху. То-есть я исходил из логики - если я не могу наперед просчитать все подводные камни - то зачем сразу себе ограничения создавать на будущее.
Почему? По логике весь функционал должен выполняться в контроллере, а модель должна отвечать только за работу с базой данных. > maximum-scale=1.0, minimum-scale=1.0"> > Зачем так делать? Ты издеваешься над пользователями что ли? Я воспользовался стандартным кодом HTML-страницы из phpstorm emmet'a по !!+tab >Это неудобно, лучше сделать автоматическое определение текущей папки. Почему не удобно? Практически во всех CMS используются предопределенные константы текущего местоположения проекта. > автоматическое определение текущей папки. Я указал путь не на папку проекта, а на корневой каталог для файлов загруженных пользователями. >Есть какие-то веские причины почему тут запрещено наследование? Что может унаследоваться от класса который работает со структурой директорий? Не хочу чтобы плодились унаследованные классы, DIR вполне может выполнять любую работу с папками. >Между контроллерами и моделями нет соответствия один-к-одному. Плюс твой метод подразумевает Во многих CMS можно в один контроллер подключить сколько угодно моделей, в опенкарте как правило контроллеру соответствует модель >Непонимание MVC Скорее извращенное понимание после долгой работы с CMS'ками сомнительного качества. Я поэтому и снова тут, надоело ковыряться в CMS'ках.
Спасибо ОП, что посмотрел. Надеюсь за выходные успею всё поправил и допилить функционал На HTML-CSS не обращай внимания, только на twig, если не трудно, так как не работал ранее с шаблонизаторами
Простая задачка для анонов, изучивших массивы и функции:
Дан массив с числами, например: $numbers = [1, 3, 4, 2, 7, 12];
Напишите функцию isNumberAfter($numbers, $first, $second), которая возвращает true, если в массиве есть число $second правее числа $first, и false в противном случае.
>>964341 >Ты предлагаешь добавить в PSR-11 интерфейс метод getTwig? Я выразился хуево. Скорее имел ввиду, почему разработчики IDE не запилят такую хуйню, мол если класс с интерфейсом PSR-11 возвращает из массива объект то делать автодополнение.
Чтобы делать автодополнение, надо как-то узнать имена сервисов и соответствующие им классы. В разных контейнерах это делается по разному,в Pimple вообще это так просто не определить, так как это явно не описано нигде. Там ведь функция, она может вернуть что угодно, пока не запустишь - не поймешь.
Да, такое и в ZF2 я видел раньше, тут есть подвох: теории у тебя может быть несколько сервисов одного класса, но с разными настройками. Распознается ли это?
И еще интереснее ситуация, ты сделал внедрение через тайп-хинты, а завтра кто-то добавил второй сервис твига.
Возможно, там очень много данных выводится. Сделай свою функцию для дампа сущностей, которая например пишет класс и основные свойства вроде id, name, ну или поищи, может в симфони есть готовый дампер. Там было что-то такое.
>>964745 Скорее наоборот. Например actionIndex - метод который собирает данные и передает их во вьху. А сервисы - это разные классы которые делают операции над данными, ну там типа валидации, пагинации и т.п. Ну я это так понимаю по крайней мере.
>>964748 В середине Getting Started (!) написано не использовать var_dump для сущностей: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html > Lazy load proxies always contain an instance of Doctrine’s EntityManager and all its dependencies. Therefore a var_dump() will possibly dump a very large recursive structure which is impossible to render and read. И далее авторы предлагают использовать специальный Dump из доктрины.
Пробовал, <exec executable="php bin/console doctrine:database:create"/> тоже не работает. Просто виснет и никакого вывода в консоль. Руками все естественно работает.
>>965012 А можешь в конструктор передать сразу контейнер, а у же в самом классе вызывать экземпляры контейнера, вместо того, чтобы все эти экземпляры по отдельности тащить.
>>964999 Ты явно не туда свернул. Я аналогично исползую DI: $container = new ContainerWrapper($config); $container['twig'] = function() { $loader = new \Twig_Loader_Filesystem('../app/Templates/'); $twig = new Twig_Environment($loader); return $twig; }; $app = new \Slim\App($container); $app->get('/', \Controllers\IndexController::class . ':index'); Только там у меня еще обертка для контейнера, ну что бы phpdoc использовать.
>>958715 (OP) Помогите разобраться почему не работает скрипт с кириллицей. mb_internal_encoding("utf-8"); в начале прописал и функции нужные для кириллицы использовал. С английским текстом работает как нужно. http://ideone.com/fork/g8wDBZ
9 строка, ничего не понимаю, почему, что бы получить сумму выплат, нужно прибавить переменную в которой заложен 0 ? Как то вообще с циклами не понятно и примеров очень мало
Допустим нету т.к. она действительно не работает, тогда нужно написать свою функцию mySuper(). Как ей привязать this в контексте объекта в котором она была вызвана не передавая ей никаких знаний об этом объекте?
С остальными подвохами нужно разобраться после этого...
>> if (size == Hamburger.SIZE_SMALL || size == Hamburger.SIZE_LARGE) { >> } else if (size === undefined) { >> } else if (size != Hamburger.SIZE_SMALL || size != Hamburger.SIZE_LARGE) { >В третьем случае лучше просто написать else. Также, можно убрать второй случай. >Также, может быть стоит хранить где-то список допустимых значений отдельно, чтобы было легко его править. Добавил список допустимых значений и исправил условие: https://jsfiddle.net/y28h2o2b/6/
>> определил this.menu >Странно, я в коде не вижу this.menu = {}; Наверно это было в другой версии кода. Да, я нечаянно скинул не ту. Это было в 4 версии. Сейчас всё на месте.
>> А почему ЛЭП не может спросить сколько энергии нужно? >Она может, но получается как минимум 2 проблемы:
>- ЛЭП надо будет дать ссылку на Сеть, в то время как c другими элементами у нас односторонняя связь: у Сети есть ссылка на Элемент, а у Элемента на Сеть - нет. Такая односторонняя связь удобнее, ее проще поддерживать и лучше видно кто кем управляет >- будет запутанная цепочка вызовов: Сеть опрашивает Элементы, сколько они генерируют, а ЛЭП в свою очередь опрашивает Сеть, какой получился баланс (а ей для этого надо опять опрашивать Элементы). Запутанное отношение, и тут легко даже сделать бесконечную рекурсию.
>Потому удобнее сделать расчет, сколько мы закупаем/продаем энергии, в Сети, а ЛЭП эти цифры не давать, зачем они ей. Если что, я не согласен с вашим замечанием - потому что мне не нужно было давать ссылку на Сеть, только передать уже посчитанный баланс. Можно было считать Сеть за контроллер, а ЛЭП за модель которая содержит вспомогательные методы расчета. А теперь в эти методы нужно передавать ссылку на ЛЭП. Мне из-за этого кажется что я понял и сделал всё ещё более худшим образом.
>>> PowerLine.prototype.countPower = function(power) { >>> var thispower = this.power; >>> >>> for (var i = 0; i < thispower; thispower--) { >>> if (power == 0) { >>> break; >>> } >>> >>> power += power / -Math.abs(power); >>>что-то я не могу толком понять, что тут происходит. Зачем мы power делим саму на себя? Получится ведь либо 1, либо -1. Тут явно ошибка. >>Наверно я сбил столку неправильно назвав функцию - эта функция считает сколько энергии останется после передачи\получения её через конкретную ЛЭП. >>power мы делим саму на себя чтобы узнать прибавлять или отнимать энергию каждый раз, чтобы достичь баланса, т.е. узнать обратный знак своего значения. То есть, мы каждый раз либо прибавляем или отнимаем по одному, до тех пор пока значение не станет нулём. >Вместо вычитания в цикле надо использовать деление или умножение и функции min()/max(). Как определение максимального или минимального значения поможет определить сколько энергии останется после передачи её через ЛЭП? И определение максимального\минимального значения чего нужно сделать?
>> price += powerlines.countPrice(balance); >> balance = powerlines.countPower(balance); >Здесь идея правильная, но код не очень логчный. Мы сначала спрашиваем сколько стоит передача энергии, а только потом - сколько можно передать. Логичнее сделать наоборот, узнать, сколько можно передать, а потом - сколько это стоит. А здесь считается не сколько можно передать а сколько останется энергии после передачи через конкретную ЛЭП. То есть сначала мы считаем цену за то количество которое мы может передать а затем высчитываем оставшиеся количество энергии.
>Ну и функции стоило назвать логичнее. Не countPower(), а например getTransferredPower() Переименовал функцию для наглядности
> хотя мне кажется что сделать тут min(balance, line.getThroughput()) было бы нагляднее. А я не сразу догадался что это делает. Можно было и так сделать, но у меня уже сделано по своему. Можно я не буду эту менять? Придётся заново переосмысливать мою программу.
Ещё был совет сделать хэш за место свича, но для Array-like пришлось бы делать сложное условие внутри этого хэша. Чем плох свич, если его функционал подходит для этой задачи?
>>>Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы. >> А других встроенных объектов это замечание касается? >Да, если надо копировать встроенные объекты, то для каждого придется писать свою логику. Один способ для Regexp, другой для Function, и так далее. Встроенных объектов довольно много. Мне действительно следует прям для каждого-каждого объекта писать логику? Включая примитивные значения, которые на самом деле тоже объекты?
>Встроенные объекты могут иметь скрытые свойства и просто циклом их копировать нельзя. А как узнать про эти свойства? У меня не получилось ничего найти про них.
>>964071 >> Class 'DOMDocument' not found >наверно расширение dom не установлено для PHP. У меня возникала та же самая ошибка после установки этого расширения. Оказалось нужно ещё php-xml было.
>>965111 Так переменная сначала только ровна нулю. При первой итерации она становится равна $p, при второй она становится равна $v + $p - и так далее до конца. Завязывай с такими пидорскими названиями у переменных - непонятно же ни черта. Пиши так, чтобы можно было посмотреть на любое условие и сразу понять, что означают переменные. А то я твои А и Б труба шатал!!1
Оп, короче по вектору я честно пытался. https://3v4l.org/Brc10 Но нихуя не вышло. Наследовать Работников от Департамента в корне не верно. Не посчитано: >Число страниц документов и отчетов, которые производят все департаменты в сумме. >Средний расход тугриков на одну страницу Ну и с выводом не стал ебаться.
>>965246 Браток, у тебя неверный подход. На правах новичка, ковыряющегося с этим несколько недель и сделавшего "Вектор" до антикризисных мер, говорю. Что это такое - класс Департамент и класс ГруппаРаботников? Это вообще ни к чему. Какие у нас есть сущности, какие у них есть атрибуты и методы, давай выделим? 1. Работник, у которого есть профессия, есть ранг, на основе которых выявляются потребление кофе и выработка страниц, а также - является или нет боссом, что также влияет на зарплату. 2. Департамент, у которого есть определённое количество работников, нужно иметь возможность считать общую зарплату по департаменту, потребление кофе, выработку страниц. 3. Компания, в которой находятся все департаменты. (С этим я и сам пока не совладал, азаза.) Чтобы просто всё посчитать хотя бы и не по ООП, нам надо иметь как минимум класс Работник. Дальше ты получишь всех работников по департаментам и можешь всё получить. Попробуй хотя бы так, дальше лучше поймёшь.
>>965290 Будь моя воля - я бы вообще всё в одной функции посчитал, но мне уже удалили по рукам и сказали под каждое действие пилить свой метод, что вылилось в тонну кривых методов. В условиях был толстый намёк, что должно быть два класса, - Департамент и Работники, после сказали работников заменить на ГруппаРаботников, что и было сделано. Собственно с этим и работал. Про сущности я так и не понял нихуя. Про наследования стало немного доходить, но тут Группуработников нельзя унаследовать от Департамента.
>>965298 Ты не шаришь. Не работники, а работник. От этого работника можно наследовать как хочешь, скакой угодно зряплатой и вообще любой должностью. А работники будут собираться у тебя уже в департаменте.
>>965298 >после сказали работников заменить на ГруппаРаботников Какой педераст это сказал? Да вырвут ему его гнусный язык! Наверное, ты не так понял, потому что кому надо советовать ерунду. >Про сущности я так и не понял нихуя. Сущность - это краеугольный камень системы. У нас это Работник. У работника есть свойства - профессия, потребление кофе, выработка страниц, ранг, босс-нет, зарплата. Некоторые свойства вычисляются из других (по профессии - кофе и страницы, по рангу и боссу - зарплата). У работника должны быть методы - подсчёт зарплаты исходя из ранга и босс-нет, подсчёт кофе исходя из босс-нет, подсчёт страниц исходя из босс-нет. Ну а дальше создавай экземпляры и считай в цикле. Делай!
>>965337 Но ты же ничего не объяснил. Ты посмотри на мой код, там почти тоже самое, что ты щас сказал, только называется класс по другому, имеет те же свойства, те же методы.
>>965346 Херась, не объяснил! С какого перепугу тогда у тебя класс Работник называется ГруппаРаботников? Я же не говорю тебе, что у тебя код неправильный целиком, я говорю тебе, что подход у тебя неверный. Ты же ни хера не понял сути, если назвал класс ГруппаРаботников. Какая группа, если у тебя там отдельные работники создаются? У тебя многое есть, просто нужно понять суть. Судя по всему, ты часть кода скопировал из чьего-то решения, поэтому сути и не догнал.
>>965298 >Департамент и Работники, после сказали работников заменить на ГруппаРаботников, что и было сделано >>963590 Да ты охуел, тебе сказали, чтобы Employees поменял на Employee. Ты английского не знаешь? Мне кажется в этом проблема, может задумка была и правильно, но название неправильное и вводит посторонних в заблуждение
>>965416 Вы зациклены на названии. Проблема не в нём. Вот Оп пояснял, что нужно переименовать. >Классы называются в единственном числе, не Employees, а EmployeeGroup. Но я бы советовал так не делать, а делать 1 объект = 1 сотрудник, иначе трудно будет например повысить ранг только одному человеку в группе - надо будет переразбивать группу, сложно. >>964062
Когда было Employees, это скорее упущение, чем грубая, фатальная ошибка из-за которой мой код пошёл по пизде.
Английский тут совершенно не при чём. В общем я жду официального комментария от ОПа, а то некоторые тут уже мудаком обзывают, а просто задаю вопросы, может они тупые и нелепые, но я в первую очередь пишу ОПу, потому что ему не похуй. на самом деле похуй.
>>965428 Так он комментил намного выше: >Да, с группами будет неудобно если тебе надо повысить зарплату одному работнику из группы - код переразбиения групп сложный будет. Проще с отдельными объектами, пусть даже так уйдет чуть больше памяти, но у нас там не миллион работников, чтобы о ней беспокоиться.
>>965428 >Классы называются в единственном числе, не Employees, а EmployeeGroup Ох лол, так он ведь просто пример привёл, ну что же ты так всё буквально понимаешь... Я так тебе и объяснял: не нужен класс ГруппаРаботников, нужен класс Работник. От этого у тебя и идёт общее непонимание - ты никак не въедешь в тот момент, что оперировать надо отдельными экземплярами-работниками, собирать их в департамент, там всё считать. От этого весь сумбур у тебя.
>>965428 >Вы зациклены на названии. Проблема не в нём. Проблема в том, что ты никак не въедешь, что не может быть класса Департаменты, не может быть класса Работники. Ты это понимаешь? Класс - это сущность, она единична. У неё есть свойства и методы. А у тебя - ГруппаРаботников, у которых сумбур в свойствах и методах, всё свалено в кучу, когда должно быть всё отделено и чётко.
>>964573 В общем, если > User: S = (B - kg^x) ^ (a + ux) степень получается нечетным числом, то токены S получаются разные. Если степень четная - всё работает.
Можно ли как-то в слиме получить доступ к контейнеру внутри роута, не через $this->get() или $this['service'], а как-то типа $this->container->методыКонтейнера?
>>965506 Всё работает! Было очень весело разбираться в этой теме, хочется теперь ещё чего-нибудь копнуть математическое.
Замечания: 1) серверная половина (PHP) работает заметно медленно (с использованием BC.Math).
2) JavaScript, похоже, не имеет встроенных функций для работы с большими числами, пришлось использовать стороннюю библиотеку (минус), да еще и для шифрования библиотеку (минус), зато обрабатывает почти моментально (плюс). Потыкать бы где сервер с Node.js
3) Python-версия с википедии тоже обрабатывает моментально (говорят, на питоне тоже пишут сайты, но мой хостер дает только PHP).
4) Очень помогли пасты ОП-а про ООП. Нихуя не работало, пока не расчленил код на микрообъекты с методами, только тогда нашел свою ошибку.
>>965599 > а как-то типа $this->container->методыКонтейнера? Как раз при вызове $this->get() ты и вызываешь метод контейнера. Slim привязывает this обработчика роута к контейнеру, поэтому когда ты вызываешь $this->get('service') на самом деле вызывается $container->get('service'). Так что попробуй $this->методКонтейнера, должно заработать. Про привязку контекста написано тут: http://php.net/manual/en/closure.bindto.php , вот пример попроще: https://ideone.com/mTHisT
>>964999 Правильно понимаешь, передача контейнера в качестве аргумента - это Service Locator. То, что ты хочешь, называется Controller as Service. Обычно в этом нет смысла, есть идеи почему?
> $credit=$absoluteCredit-$payment Это лучше унести из шапки в тело цикла так как переменная absoluteCredit создается ниже и выглядит нелогично, надо при чтении вверх/вних прыгать чтобы разобраться.
> $total+=$absoluteCredit; > $total+=$payment; Это бы тоже хорошо объединить в одну строку, например так:
если (кредит большой) { выплата = ...; } иначе { выплата = ...; }
> $homoCreditDownPayment=0; //первый взнос в HomоCredit > $softBankDownPayment=0; //первый взнос в SoftBank > $strawberryBankDownPayment=7777; //первый взнос в StrawberryBank > $homoCreditPersent=1.04; //процент в HomоCredit > $softBankPersent=1.03; //процент в SoftBank > $strawberryBankPersent=1.02; //проц Так можно писать, но проще было это просто числами при вызове функции указать - смысл этих чисел понятен из названий аргументов функции.
> $bankName="HomoCredit") Вот так переменную создавать не надо, создание переменной это однодействие, вызов функции - другое, и не надо их в одну строку втискивать. Тут лучше вообще было без переменной обойтись.
Это PHP при обращении к несуществующей переменной хоть и выводит ошибку, но не прекращает выполнение программы, а вместо значения переменной возвращает null. Неправильно, кстати, придумано.
> Не люблю использовать ENUM, он не гибкий, Можно потом добавлять новые статусы через ALTER TABLE.
> То-есть я исходил из логики - если я не могу наперед просчитать все подводные камни - то зачем сразу себе ограничения создавать на будущее. Чтобы защититься от записи неправильных значений. Ну и слова чуть читабельнее чем числа.
> ENUM is evil Ну так твое решение ничуть не лучше, там предлагается ENUM не на число заменять, а сделать отдельную таблицу статусов и ставить внешний ключ на нее.
> Я воспользовался стандартным кодом HTML-страницы из phpstorm emmet'a по !!+tab Значит это плохой код. Это запрещает изменение масштаба в мобильной версии. зачем? Они его откуда-то бездумно скопировали, а исходный код скорее всего написал тот, кому лень было отлаживать верстку и он просто запретил масштабирование. На хабре сделано так же, как неудобно.
>>Это неудобно, лучше сделать автоматическое определение текущей папки. > Почему не удобно? Практически во всех CMS используются предопределенные константы текущего местоположения проекта. Потому что это можно определять автоматически. Зачем заставлять пользователя что-то вводить? Позор разработчикам таких CMS.
> Я указал путь не на папку проекта, а на корневой каталог для файлов загруженных пользователями. Тогда можно сделать по умолчанию определение автоматически, а при необходимости переопределение в конфиге. Но если ты меняешь папку, скорее всего поменяется и URL, под которым она видна, ты это учел?
>>Есть какие-то веские причины почему тут запрещено наследование? > Что может унаследоваться от класса который работает со структурой директорий? Не хочу чтобы плодились унаследованные классы, DIR вполне может выполнять любую работу с папками. В этом и суть наследования, что ты заранее не знаешь, как твой класс будет унаследован. Вдруг кто-то например захочет логгировать все действия с папками или какие-нибудь проверки добавить. Для добавления final должна быть веская причина, например, какой-то критичный код, изменение которого сломает программу. И его тогда лучше на метод ставить, а не на весь класс.
Обычно нигде final не ставят, потому когда ты его ставишь, появляется вопрос, а зачем, и каких-то веских причин запрещать наследование я пока не вижу.
Если что, еще есть принцип что классы должны быть открыты для расширения, но закрыты для модификации (open/closed principle).
>>Между контроллерами и моделями нет соответствия один-к-одному. Плюс твой метод подразумевает > Во многих CMS можно в один контроллер подключить сколько угодно моделей, в опенкарте как правило контроллеру соответствует модель Это не стоит копировать. Это какая-то ошибка в опенкарте. Или это не совсем модель, а какой-то помощник для контроллера.
Еще совет: не спеши строить какие-то сложные структуры классов, если нет уверенности что это нужно. Лучше делать все проще. Вот статья по теме: https://habrahabr.ru/post/153225/
> function bchexdec($hex) { Она никак не проверяет наличие двоеточий. И может давать неверный результат. Надо ее доработать.
Также, я бы ее оптимизировал. Вот что можно улучшить:
- вырезать двоеточия - убрать неэффективную рекурсию, заменить на цикл - там на каждый шаг создается новая строка, неэффективно, лучше просто циклом идти по строке с конца к началу и брать N-й символ через substr. - она берет по 1 символу за раз, но dechex работает минимум с 32-битными числами, это 8 16-чных, для надежности можно брать по 6 цифр за раз.
Ты разобрался, как она работает? Она просто берет по 1 цифре с конца, домножает число на 16 и прибавляет эту цифру.
И надо протестировать эту функцию, на каком-нибудь известном числе. Например:
Также, может быть библиотека gmp будет эффективнее, так как она хранит числа не в виде строк, а в виде объектов и может там как-то эффективнее это сделано. Ну и для импорта чисел там есть gmp_import, тебе надо только твое число преобразовать в бинарную строку из байтов сначала.
> # соль Имей в виду что mt_rand генерирует лишь 32-битное число и использует генератор (вихрь Мерсена), у которого генерируемые числа зависят от предыдущих (не криптографически надежный). Если ты генерируешь большое число несколькими вызовами mt_rand, там все равно будет только 32 или меньше бит случайности, остальные биты зависят от предыдущих. Более того, ты искуственно ограничиваешь диапазон, что уменьшает число возможных вариантов. У тебя вариантов числа a совсем немного получилось, на уровне 24 бит может быть.
Ну чтобы тебе было понятнее, представь что у тебя используется всего 3 бита энтропии: mt_rand(0, 7). Получается всего 8 вариантов, и их легко перебрать. Алгоритм же основан на том, что a и b трудно подобрать и для этого они должны быть в очень большом диапазоне (но больше простого числа q их делать смысла нет, так как при операциях по модулю результат не может быть больше этого модуля).
Сколько бы ты не вызывал rand(), и какое бы длинное число не делал, больше 32 бит энтропии (4 млрд вариантов) ты не получишь. И у тебя получается 32-битный ключ, что смешно по нынешним меркам. NSA его за 3 секунды вскроет.
Чтобы получить большое случайное число, надо использовать специальные функции:
- на линуксе - прочитать N байт из /dev/random Скорость генерации чисел может быть ограничена. Если нужны числа в очень больших количествах, придется раскошелиться на аппаратный генератор. - в PHP7 сделали функцию http://php.net/manual/ru/function.random-bytes.php - другие методы можно найти в исходниках библиотеки https://github.com/paragonie/random_compat , я их не буду тут приводить.
> foreach($args as $argument) { > $string .= $argument . ':'; implode лучше использовать.
> Алсо, комп очень долго думает над этим всем, нагревается и жужжит, мне его жалко Асимметричная криптография требует тяжелых вычислений, потому обычно с ее помощью только вырабатывают общий ключ и далее шифруют данные симметричным шифрованием с этим ключом.
Кстати, sha256 дает более длинный хеш, чем md5, с md5 мы получаем только 128 бит (то есть пароль какой бы сложный не был, останется только 128 бит от него). sha256 можно попробовать сгенерировать функцией http://php.net/manual/ru/function.hash.php
Еще алгоритм gost генерирует 256-битные хеши, если ты предпочитаешь отечественные разработки.
Попробуй еще gmp, может быстрее будет. Ну и можешь еще посчитать время, какая строка сколько времени требует.
В лог который у тебя там указан, что-то пишется? У phing наверно есть отладочный режим, где он пишет подробно выполняемые команды, попробуй его включить:
Ты используешь синтаксис при определении роута, который говорит Слиму самому создать объект класса. Надо использовать синтаксис, указывающий что класс надо взять из контейнера.
Также при определении контроллера как сервиса надо указать что он каждый раз должен создаваться заново.
Чтобы понять, как Слим отличает имя класса от имени сервиса в контейнере, лучше всего глянуть код Слима:
Вот кстати аноны, которые не хотят решать задачи по ООП из моего учебника, просто интересно, как вы код Слима собрались читать не понимая ни ООП ни DI?
Думаю, что ты путаешь. В DI как раз применяется принцип IoC в том смысле, что не класс ищет зависимости, а их в него инжектируют. Мне само понятие IoC не нравится так как при желании под него можно подвести что угодно.
У тебя для контроллера внедряется контейнер и получается ServiceLocator. так часто делают, это нормально, но анон хочет чтобы контроллер был сервисом с DI.
> То, что ты хочешь, называется Controller as Service. Обычно в этом нет смысла, есть идеи почему? Некоторые используют этот подход. А почему нет смысла?
Оп, так я правильно хочу сделать, передав таким образом объекты в контроллер? А то меня выше обругали и посоветовали контейнер кидать и из него брать нужное (это ServiceLocator, я так понимаю).
Анон, будь добр поясни, вопрос будет по php framework'ам Есть всякие halpers, processors, handlers, makers и другая хуета. ну вот как я вижу: - halpers - это например дату подогнать для вывовода, или подготовить данные для вывода(ну если нужно перечитать или отправть) За остальных вообще не ебу, анон памаги! Дай совет, название книги, пинок под зад - возьму всё.
За опп неочень знаю, так как пилял сайтики визиточки и мимоговномагазы.
Там у нас был вопрос про то, что в одном месте можно обойтись без цикла.
Давай я приведу пример, чтобы пояснить свою мысль. Допустим у нас есть money рублей и мы хотим купить на них как можно больше пирожков, при этом каждый стоит price и всего их в наличии stock. Надо узнать, сколько пирожков мы в итоге купили. Можно конечно решить задачу так:
var money = 100; var price = 10; var stock = 4; var result = 0; // ответ
Но что-то мне подсказывает, что число купленных пирожков можно найти и без использования цикла, по простой формуле. То же самое касается и расчета закупленной энергии в функции countPowerLinePrice(), где можно обойтись без цикла. Нужна подсказка, как?
var amount = this.countEnergyTransfer(powerlines, balance); // объем купленной/проданной энергии balance += amount; price += amount * powerlines.getPricePerMegawatt();
Так как у тебя там сейчас две почти одинаковых функции (countPowerLinePrice, countRemainingPowerAfterPass). Ну или можно сделать из них одну функцию, которая возвращает сразу и объем, и стоимость энергии.
> function someTypeOfSolarPanel() { > SolarPanele.apply(this, arguments); Вот это неправильно, так как у нас у конструкторов разные наборы аргументов, сравни:
function someTypeOfSolarPanel() function SolarPanele(power)
Раз у них разный набор аргументов, то нельзя передавать аргументы, предназначенные для одной функции, другой. Вместо этого надо делать так:
var power = 100500; SolarPanele.call(this, power);
В классе Electrostation лучше было сделать так:
function Electrostation(power) { if (power неправильный) { выбросить ошибку; }
NetworkElement.call(this, power, power); }
То есть мы вызываем конструктор предка и передаем ему нужные значения. Если позже в конструктор NetworkElement допишут еще какой-то код, то он сработает, а в твоем варианте - конструктор предка не вызывается. И не очень понятно, ради чего ты отказываешься его вызывать. По моему, логичнее вызвать уже написанный конструктор предка (NetworkElement), если он сделает то, что нам нужно.
> Math.pow(10, 3); Я тут вспомнил, в программировании есть "научный" формат записи чисел, и можно писать так: 1e3 - это значит 1 умножить на 10 в 3 степени: https://learn.javascript.ru/number а например 2.5e3 = 2500.
Кстати "научный" формат есть и в PHP, и в куче других языков, точно в таком же виде.
> Если что, я не согласен с вашим замечанием - потому что мне не нужно было давать ссылку на Сеть, только передать уже посчитанный баланс. Можно было считать Сеть за контроллер, а ЛЭП за модель которая содержит вспомогательные методы расчета. А теперь в эти методы нужно передавать ссылку на ЛЭП. Мне из-за этого кажется что я понял и сделал всё ещё более худшим образом.
Я уже не очень понимаю, о чем речь. Тот метод, что используется сейчас, вполне подходит. Если хочется обсудить другой вариант, то хорошо бы увидеть хотя бы кусочек кода.
> Можно я не буду эту менять? Придётся заново переосмысливать мою программу. По идее, ты должен стараться писать программу так, что в ней было легко разобраться. И соответственно небольшие изменения не должны вызывать сложностей и ради них не требуется всю программу переделывать, а только небольшую часть. А если все оставить как есть - может ты и дальше будешь писать цикл там, где он не требуется.
Определение типа переменной
> Чем плох свич, если его функционал подходит для этой задачи? Ничем не плох, если подходит, то пусть будет. Просто мне кажется, с хешем строк бы получилось меньше, так как каждый блок в свитче это минимум 3 строки. Можно было сначала искать в хеше, а если там нет нужного значения, уже применять дополнительные условия.
> if (variable == undefined) { тут сравнение неточное, через == может получиться что например 0 равен undefined. И неправильно сделана проверка, чтобы проверить, есть ли в объекте ключ, надо использовать
key in object
А твой код не отличит отстуствия поля от поля, в котором записано значение undefined.
> Встроенных объектов довольно много. Мне действительно следует прям для каждого-каждого объекта писать логику? По условиям задачи - только для Date и массивов (остальное либо примитивные значения либо оыбчные объекты).
Примитивные значения - это не объекты, но если пытаться их использовать как объекты (обращаться к свойствам или методам), для них автоматически создается временный объект, в который заворачивается примитивное значение.
Напиши функцию неглубокого копирования объектов и массивов
> clone.setFullYear(object.getFullYear()); > clone.setMonth(object.getMonth()); Вообще, там есть способ проще, можно из исходной даты получить ее в виде числа и создать новую на основе этого числа.
> var clone = object.bind(clone); Тут ошибка. Во-первых, клонировать функции не требуется (да и это невозможно наверно), во-вторых, если уж клонировать, то непонятно почему надо привязывать this к пустому на тот момент значению clone. Что делает этот bind?
В общем, я думаю, надо убрать клонирование функций, Error, Regexp, так как непонятно, корректно оно делается или нет.
>>Встроенные объекты могут иметь скрытые свойства и просто циклом их копировать нельзя. > А как узнать про эти свойства? У меня не получилось ничего найти про них. Узнать про них можно разве что читая исходный код браузеров, так как они не стандартизованы и каждый их реализует как хочет. Более того, эти свойства могут быть не JS-свойствами, а например, доступны только в объекты даты в языке C++, на котором обычно пишут интепретаторы Яваскрипта.
То есть встроенные объекты не обязаны соответствовать правилам языка JS и могут делать то, что ты в своем коде повторить не сможешь. Ты должен использовать только те их возможности, которые описаны в стандарте или документации.
Потому знать эти свойства не требуется, а нужно использовать публично доступные методы (вроде getFullYear()). Если тебе любопытно, как именно этот объект устроен, придется лезть в код интерпретатора Яваскрипт.
В Хроме и другх браузерах на Webkit/Blink в качестве интерпретатора JS используется библиотека v8. Она написана на C++ и очень сложная, вплоть до того, что содержит компилятор JS кода в машинный код, который процессор выполняет напрямую (но зато быстрая).
Вот код, который инициализирует JS-движок и добавляет встроенный объект Date, и его функции:
Дальше, к сожалению, разбираться долго, я сразу так не нашел, что к чему. Можешь поискать сам. Но сразу предупрежу, что это долго и мало что можно понять без подготовки.
Во-первых, если тебе не нравится ООП, ты можешь попробовать решить задачу без применения ООП, включая часть про антикризисные меры. И сравнить потом код. Я не против, давай сравним ООП-подход против не-ООП подхода.
Правда, код показывает, что ты пока не понимаешь ООП.
> Наследовать Работников от Департамента в корне не верно. Я по моему об этом и писал выше, тут >>964062
В конструкторе Department ты обращаешься к полю, которое нигде не описано:
> $this->name = $name;
В метод countEmployees($employees) не нужно ничего передавать. Департамент и так знает, кто в нем работает и не надо специально передавать список работников. Зачем его делать методом, если он ничего из объекта не использует? Тогда его было логичнее сделать отдельной функцией.
Ну представь например такую ситуацию. Вот у нас есть функция, которая печатает информацию о депарматенте: название и сколько в нем человек работает. В нее передается только один объект департамента. Как ее написать?
function printDepartmentInfo($dep) { echo "Название: {$dep->name}, число сотрудников: ???\n"; }
И метод countEmployees не должен делать echo. Задача метода - посчитать результат и вернуть его, а что с ним делать, выводить его или нет, решает тот, кто вызвал метод. Ну может я хочу среднее по нескольким департаментам найти, но когда я буду вызывать эти методы, они будут что-то печатать, хотя мне это не нужно. Ну и если они печатают что-то они должны не с get, а с print начинаться (но это тоже будет неправильно, делать методы печати в классе Департамента, так как вывод данных на экран это не его зона ответственности).
> public function getSalary($employee) То же самое, тут в метод не надо ничего передавать.
> case 1: > $employee->baseSalary;//Ранг 1, зп по дефолту Эта команда ничего не делает.
> $employee->baseSalary+=($employee->baseSalary)*25/100; Что будет, если мы вызовем getSalary несколько раз подряд? Зарплата будет при каждом вызове увеличиваться что ли? Тогда метод должен называться "повысить зарплату", а не "узнать зарплату".
Если EmployeeGroup представляет собой группу работников, то логично, что его методы должны возвращать зарплату на всю группу, потребление кофе всей группой. У тебя же вычисление зарплаты для группы работников (умножение зарплаты одного работника на их количество в группе) сделано в классе Департамент. А почему? Это умножение очевидно должно делаться в EmployeeGroup. Он же знает и зарплату одного работника, и их количество в группе.
Ну представь например что мы возьмем из программы только один класс EmployeeGroup. И получается, имея объект этого класса, мы не можем даже узнать какая суммарная зарплата у группы работников, потому что код, который это считает, находится в классе Департамент, и мы даже вызвать его не можем. А хотелось бы чтобы у объекта был метод, который вернет суммарную зарплату этих работников. В одно действие. Твой код это не позволяет и заставляет нас копипастить по всей программе код, который умножает зарплату на количество.
Функция getAll() ничего не возвращает, хотя название "получить" говорит, что она что-то должна возвращать.
Сделай все в одной функции, можно даже без классов. Попробуй. Можно даже в начале без антикризисных мер, но потом их надо добавить.
> , после сказали работников заменить на ГруппаРаботников, что и было сделано. Я такого не говорил.
Я сказал, что если объект хранит информацию о нескольких работниках, то он должен называться EmployeeGrpup, а не Employees так как названия классов должны быть в единственном числе. Потому что нелогично, если например, мы создали всего один объект, называть его в множественном числе.
> Про наследования стало немного доходить, но тут Группуработников нельзя унаследовать от Департамента. Нельзя, так как это разные вещи, а не сущности одного типа.
Ты можешь использовать EmployeeGroup, но в антикризисных мерах например требуется взять часть работников (не всю группу целиком) и части повысить ранг или зарплату. это будет не очень удобно делать с нынешним подходом, но ты можешь попробовать. Лучше всего будет, если ты на деле увидишь недостатки своего решения.
Я хочу еще один пример привести. Там выше в уроке была задача про работников, где известно количество часов, которые этот работник отработал, надо найти сколько там обычных часов, сколько сверхурочных, сколько он заработал. Посмотри на ее код. Если ты ее не решал - вернись и реши.
Там есть класс Employee (сотрудник). Имея объект этого класса, мы можем получить информацию об этом сотруднике, например:
Узнать общее количество отработанных часов:
echo $employee->getTotalHoursWorked();
Узнать зарплату:
echo $employee->getSalary();
Видишь, здесь в методы ничего передавать не надо. Почему у тебя не так? Почему у тебя, даже имея объект EmployeeGroup или Department, нельзя получить какую-то информацию о нем, а надо передавать дополнительно какие-то массивы? Я не вижу, в чем тут выгода. Мне кажется, было бы удобнее, если не надо было ничего передавать, как в примерах выше.
>>965675 >Там древний код скорее всего, написанный по мотивам того, что видели в других CMS того времени. На самом деле 2.3 это одна из последних релизнутых версий (ей не больше полугода), и 3 версия готовится к выходу
>>965844 >Сделай все в одной функции, можно даже без классов. Я же ООП учу, зачем мне это? Я тут переписал немного с использованием советов. +создал 4 класса по профессиям
В общем есть несколько проблем: Это подсчет суммы по департаментам кофе/пейдж/зп, я не смог этого сделать и захуярил кривую функцию в конце. Как это правильно реализовать в рамках моего кода? И конечно же поле public $quantity; у СОТРУДНИКА, предвижу: >ТЫ ЧЕ ДЕБИЛ, ВСЕМ ТРЕДОМ ТЕБЕ ТУТ ВТИРАЕМ ЧТО ОН ЕДИНСТВЕННАЯ СУЩНОСТЬ И я понимаю, что так нельзя, не может быть у сотрудника кол-ва сотрудников. Может перенести это поле в департамент? Хотя и там оно не очень подходит, на мой взгляд.
>>965899 Я не ОП, но мне к примеру, если надо передать больше 2 переменных в метод - я использую ассоциативный массив, К примеру : http://ideone.com/KGHKk4 Это не замечание, но на мой взгляд так удобнее
>>965899 >И конечно же поле public $quantity; у СОТРУДНИКА, предвижу - Андрей Сергеевич Путин, так как у вас есть полный тезка в нашем департаменте и вы оба занимаете одну должность, поэтому мы вам просто добавим свойство quantity = 2. Может это тебе кажется удобным, но вносит непонятки
>>958715 (OP) Всем привет. В общем у меня в таблице несколько студентов. Команда SELECT * FROM Students WHERE gr='$get' выбирает только первого из них. Как выбрать сразу всех студентов?
>>965919 >Кажется это ненужное усложение. Когда станет параметров не 4, а 7 к примеру, ты каждый раз будешь вспоминать порядок передачи параметров если не пользуешься IDE, а так ты массивом вместе можешь передать параметры в любом порядке. Если тебе в будущем надо будет сделать не 4, а 5 параметров - придется либо задавать значение по умолчанию этому параметру либо искать все места где вызывается функция и дописывать везде 5ый параметр
>>965928 Судя по твоему запросу он и выберет все записи, а не одну (если только она не одна под условие подходит). Для выбора 1 записи можно обратиться по первичному ключу, но тогда фильтр смысла не имеет, либо же использовать limit 1. В твоем случае ни того ни другого нет. Ты вообще уверен, что у тебя под условие подходит более одной записи? Что в $get находится? Чому передаешь переменную пхп прямо в строку запроса?
>>965937 Предположу, что ты работаешь через голый пдо. Хз че еще предположить тут. Есть вариант, что ты используешь к примеру fetch, который работает с итератором по результирующему набору, и он возвращает записи по одной. Тогда юзай fetchAll. А вообще код покажи, а то это на кофейной гуще все.
Откликнулся на вакансию php девелопера в моем мухосранке (которые, стоит сказать, ну очень редкие), по телефону спросили могу ли в вордпресс. Сказал, что в глаза его не видел, но за неделю как нибудь по документации разберусь. Прислали тестовое пикрелейтед1. Скажите, оно слишком сложное? Смогу ли я его сделать, если сейчас с нуля буду учить вп по пикрелейтед 2 (нашел его в шапке wordpress треда на /wrk). Мой уровень знаний - недоделанный файлообменник опа.
>>965944 Читая твое задание мне аж дурно стало. Нет, не потому, что это сложно прямо, я с вп вообще не работал и не могу об этом судить, у меня дохуя лет опыта на фреймворках только. А потому, что я будто текст из другой вселенной читаю. Не могу объяснить этого чувства, но все же вот оно есть.
>>965954 А ещё когда придешь туда, и познакомишься с их тим лидом, почувствуешь легкий шлейф снобизма, ведь он уже с пятерку лет шаблоны натягивает на вордпресс.
Я сейчас пытаюсь понять MVC. Точнее, как прикрутить эту штуку к моему реальному проекту.
Суть токова: юзер нажимает кнопку и получает окошко с таблицей данных. Технически происходит следующее: при нажатии на кнопку срабатывает js-скрипт (Контроллер, так?), он передаёт через аякс пхп-скрипту (Модели) данные (что именно нажал пользователь и кто он вообще есть). Скрипт обращается к БД, что-то там вычисляет и выдаёт результат. И вот тут мне не понятно, как дальше всё сделать по фен-шую.
1) В https://github.com/codedokode/pasta/blob/master/arch/mvc.md написано, что он должен возвращать результат через return. Но пхп-скрипт, который вызывается в аяксе, оформлен у меня просто кодом на пхп, а не функцией (вернее, функции там тоже есть, но уже внутри). 2) Там же написано, что пхп-скрипт не должен выдавать ничего в echo. А как тогда должен? Единственный вариант, который я вижу - json. 3) Опять же, есть два стула. Для таблицы (которая показывается юзеру) нужно, к примеру, десять значений ячеек. Первый стул - это вернуть из пхп-скрипта (Модели) эти значения и уже в js-скрипте (Вид) подставить их в ячейки документа через document.getElementById("div_show_one_flight").innerHTML=data; Сам же внешний вид таблицы прописывается в index.php. Но в том же гайде пишут, что нельзя Виду работать с document. Да как так? Как выводить тогда вообще? Второй стул - это оставить в index.php только место для вставки, а полностью весь код таблицы набрать в пхп-скрипте, передать его через айкс обратно js-скрипту и вставить одним действием. Тоже лажа какая-то, получается: Модель напрямую рулит Видом.
Что-то не въезжаю я в караван мысли авторов этого паттерна.
>>965664 >Как раз при вызове $this->get() ты и вызываешь метод контейнера. Неа, не работает. Собственно в чем идея - я сделал класс ContainerWrapper который наследуется от слимовского контейнера. В нем у меня методы типа getTwig и phpDoc для него, все это для автодополнения кода. В контроллере это все работает, а вот в колбеке - нет.
Аноны, объясните дауну для чего нужен компонент Symfony HttpKernel - что он делает полезного? В демонстрационных примерах получают $request от пользователя и тут же скармливают этот реквест HttpKernel, результат работы которого записывается в $reponse и затем идет $response->send().
В чем прикол? Зачем скармливать реквест этому компоненту, чтобы потом сразу же отправить пользователю ответ?
А есть кто-нибудь кто работал с AMP (accelerated mobile pages) ? Документация очень скудная и в основном по верстке и отправке форм, а вот именно о том - можно ли организовать общение фронта с бэкендом ничего нет.
>>966380 Это амп, огрызок реакта. В нем нет поддержки ничего. Гугл собирает разметку страниц при индексации и потом добавляет страницы себе в кэш. Юзеры которые заходят на такие страницы - физически находятся на кэшированных страницах Гугла. Поэтому и такой вопрос. Там есть хуевая поддержка форм, но с ответами от сервера оно работать не умеет. Только с парой заголовков специфических, если бы обычный аякс мог работать я бы и не спрашивал
>>964072 >>961633 Спасибо, переделал на Concrete TI и изменил каскадные ограничения: http://sqlfiddle.com/#!9/889f2/1 STI показывал в прошлый раз, а Class TI не вижу смысла использовать в этой задаче. Если захочу запретить пользователю ставить лайк самому себе, то в MySQL нужно писать триггер, а Postgres просто использовать CHECK?
Да. С другой стороны, приватные свойства дают больше возможностей. Мы можем проверять присваиваемые значения на допустимость или менять одно поле при изменении другого.
>>965944 >ие), по телефону спросили могу ли в вордпресс. Сказал, что в глаза его не видел, но за неделю как нибудь п Книга лучшая что есть на русском языка на данный момент ( да и в принципе лучшая про WP). Так что с помощью глубокого чтения книги и гугления активного, сделать тестовое задание вообще на изи. Но я очень не уверен, что это изучить возможно за 1 неделю, система WP достаточно сложная, чё бы там кто не пиздел. Это не цэмээска для бложеков, а вполне себе платформа для создания сайтов любой сложности.
ОП, у тебя ведь есть архив старых тредов? Можешь пожалуйста скинуть, попробую написать парсер, чтобы старые треды можно было добавить сюда: http://phpclub.rf.gd/
8: https://jsfiddle.net/7w3eg396/6/ (исправлено) Теперь подряд идущие aside не накладаваются друг на друга, но всё равно непонятно куда девать лишний aside. Ещё если у aside будет больше высота, чем в соседнем абзаце, то нижний (следующий) абзац влезет вверх. Нужно каждую пару aside+абзац помещать в тег и ему прописывать clearfix?
11: https://jsfiddle.net/yyedd6ev/3/ Насчёт работы Tab/Shift+Tab - пытался через tabindex, перемещение работает, но по нажатию на Enter элемент не становится :checked. Можно подсказку?
>>969469 width: 100% указывает, что содержимое элемента (без границ и padding'ов) должно занимать 100% ширины родителя. Погугли блочную модель. Предполагаю, что width: 100% тебе вообще не нужен, а достаточно прописать display: block, так как блочные элементы занимают всю ширину родителя. Добавь ссылку на jsfiddle со своим кодом, помочь тебе будет проще.
>>969651 https://jsfiddle.net/2rwwpmne/ Вот пример из моего кода. Я делю область на несколько панелей. А внутри я хочу разместить вертикально друг за дружкой элементы, занимающие всю ширину панели.
Попробуй убрать стиль для звездочки, и увидишь что блочный div уехал в кукуево.
Вот и получается что я везде леплю первой строкой бордер-бокс. А тут он потерялся при переносе части стилей и весь макет разъехался, я пол часа думал, в чем причина, еле вспомнил про бордер-бокс.
Итак, является ли он необходимым по-умолчанию при верстке резиновых страниц, или я что-то упустил?
>>969717 > и увидишь что блочный div уехал в кукуево. Это из-за width: 100% + padding'ов. Ну и width: 100% не нужен, div ведь занимает всю ширину родителя, так как блочный: https://jsfiddle.net/2rwwpmne/1/
>>969857 как тогда сделать чтобы при слишком длинном содержимом панель чуть-чуть раздвинулась, вместила все так же и без полос прокрутки? https://jsfiddle.net/2rwwpmne/2/
Подсобите с регулярным выражением из задачки про номера. Не могу сделать так, чтобы 10 цифр отсчитывала, но при этом не обращала внимания на тире, скобки, пробелы.
Ты box model изучал? Width это внутренняя ширина контента, без паддинга и бордера. Тебе скорее всего нужен width: auto, который нефлоаченные элементы с display: block растягивает на всю ширину родителя.
В твоем примере кода можно просто для внутреннего элемента поставить width: auto. Изучай особенности определения размеров блочных элементов.
Также, я не понимаю, почему ты используешь звездочку. Тебе надо задать border-box для одного элемента, зачем задавать для всех остальных?
> Итак, является ли он необходимым Конечно нет. Ставить логичнее его только там, где надо. Иначе происходят плохие вещи:
- картинки у которых задана ширина/высота, уменьшаются при добавлении паддинга - сторонние виджеты, библиотеки, рассчитанные на box-sizing по умолчанию, отображаются криво
Кстати, bootstrap 3 тоже использует звездочку с border-box. И это примерно те же люди которые несколько лет назад писали везде что звездочки зло.
Нужна более сложная верстка. Если ты жестко задал ширину 20% то она никак не раздвинется. Вместо этого можно использовать float или inline-block с шириной auto и min-width: 20%. Но перед этим надо почитать урок https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md
Также, может быть, ты захочешь использовать display: table, сделав таблицу с одной строкой. Это позволит раздвигать одни ячейки за счет других и использовать вертикальное выравнивание.
> 8: https://jsfiddle.net/7w3eg396/6/ (исправлено) > Теперь подряд идущие aside не накладаваются друг на друга, но всё равно непонятно куда девать лишний aside. Ещё если у aside будет больше высота, чем в соседнем абзаце, то нижний (следующий) абзац влезет вверх. Нужно каждую пару aside+абзац помещать в тег и ему прописывать clearfix? Можно просто поставить на aside свойство clear. Оно добавляет такой margin-top, чтобы элемент оказался ниже самого нижнего из предыдущих флоатов.
А то сейчас как-то кривовато смотрится.
> article p { > padding-left: 110px; Тут ошибка. Почитай примечания к задаче. Что, если в тексте будут не только абзацы, а еще списки, картинки, заголовки и текст без тегов?
> 10: https://jsfiddle.net/18504y5y/2/ Если сделать на body max-width 1000px то видно что картинка увеличивается до этих 1000px. Но это неправильно, в задаче надо увеличивать картинку не более ее родного размера (иначе она размывается). Тебе нужен не width, а max-width.
Я думаю, это из-за того что инпуты скрыты через display: none.
Надо скрыть инпуты другим способом, без display: none (например: спозиционировать за пределы страницы, засунуть в див с оверфлоу хидден нулевых размеров, задать нулевую непрозрачность, в общем, заставить браузер думать что инпуты доступны для пользователя), и сделать подсветку кнопки в случае если соответствующий ей инпут сфокусирован (input:focus).
Установка tabindex, я думаю, это не выход, так как это позволяет элементу получить фокус, но ни на какие другие кнопки он без яваскриипта реагировать не будет (хотя если это label, может что-то и возможно, но я не уверен). Попробуй сделать не-стилизованные радиокнопки и проверь, как на них работают стрелки, таб и пробел/enter. Только настоящий чекбокс будет реагировать на пробел/enter, когда сфокусирован.
Без клавиатурной навигации, я подозреваю, с кнопками нельзя взаимодействовать например через программу чтения страниц вслух, так как она просто не поймет что кнопку можно нажать и не предложит такую опцию. Это конечно можно решить ARIA разметкой, но проще просто не скрывать инпуты.
> 12: https://jsfiddle.net/qozy8zsL/5/ Тут почти все хорошо, но из-за того что радиокнопки скрыты через none, невозможна клавиатурная навигация. Возможно ли решить эту проблему?
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме. ОПу ведь все это читать придется.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 2/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.
Платиновые вопросы
- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
- Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery
- Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/.
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
- Что самое главное для программиста? Умение аккуратно оформлять код.
- ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
- Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
-------------------
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492
Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
PSR-1: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md