Добро пожаловать. В этом треде мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в день, не жди его, решай задачки дальше.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Учебник дает основы языка PHP, но чтобы делать сайты, этого недостаточно. Если ты его прошел, то надо переходить в более серьезным задачкам, которые научат тебя как выдавать страницы в браузер, работе с таблицами в БД, работе с формами, MVC.
Вот небольшой туториал по тому как начать использовать PHP на сервере для отдачи странички в браузер: https://php.net/manual/ru/tutorial.php Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что, задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
Нужен ли ООП, фреймворки, MVC? — Да, однозначно. Посмотри любую вакансию. Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.net/45000175 Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492 ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет. Где искать работу и заказы — hh.ru, geekjob.ru, brainstorage.me, fl.ru, odesk.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 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
>>438085 >уроков плавно подводящих к тому, как сделать задачи выше, пока нет А когда будут? А то получается сначала синтаксис, а потом сразу ПАТТЕРНЫ ПАТТЕРНЫ ПРОЕКТИРОВАНИЕ ЗАПРОСЫ
Надеюсь, что позже сделаю, а пока что учимся путем проб и ошибок. Если ты сделал задание и у меня нет ни одного замечания, то ты выучил то, что требовалось. Ну и если ты будешь код показывать с самого начала, то я скажу что не так и тебе меньше исправлять придется чем если ты все по тихлому сделаешь и только в конце покажешь (на практике, процентов 50 в таком случае придется переделывать).
Куки — это данные, которые сервер может с помощью специального заголовка передать браузеру, тот их сохранит и будет в дальнейшем отправлять на серве с каждым запросом. То есть куки — это хранящиеся в браузере данные.
В описании кук тебе могут встретиться понятия вроде «HTTP запрос», «HTTP заголовок». Если ты их не очень понимаешь, почитай про протокол HTTP. Это протокол (что-то вроде языка), на котором общаются браузер и веб-сервер: https://ru.wikipedia.org/wiki/HTTP
Протокол HTTP относительно прост. Браузер посылает запрос (например запрос на получение определенной страницы или скачивание файла), сервер обрабатывает его и возвращает ответ. И ответ, и запрос состоят из заглавной строки, заголовков и тела (необязательная часть).
- как работают куки - свойства кук (path, domain, secure, httponly) - ограничения по размеру хранимой информации и числу кук - как из PHP выставить куку или прочесть присланные браузером куки - как удалить куки из PHP - как удалить куки в браузере - как работают куки в приватном режиме браузера
В качестве мини-задачи на куки можешь сделать такое задание: сделай страницу, на которой выводится какой по счету раз ты на нее зашел. Число посещений должно храниться в куках, так что при заходе из другого браузера или из приватного режима оно считается с нуля.
Добрый день, http://ideone.com/SLRLOu можно ли делать так как я сделал в function fillNotFilledStrings()? и если нет то есть вариант как упростить это?
А есть какой-то общепринятый стандарт структуры и наименования каталогов? > - Простая, но полезная задача сделать список студентов Вот в этой задаче index.php и edit.php в корневом, а еще файлы с классами, темплейты и css из бутсрапа их куда класть? Может вопрос глупый, но меня немного стопорнул.
>>438519 ага, временный каталог называй 1 каталог с настройками config каталог с приватными данными репозитория .git каталог с админкой admin, файл с паролями htpasswd файл с паролями к базам данных - config.php.old или даже index.php.old
Где то до setcookie стоит echo или ещё что-то, отправляющее данные в браузер юзера. Как только данные начали уходить - заголовки тоже того...
Кстати банальные пара пробелов в самом конце файла, после закрывающего тега ?> - и пробелы, а с ними и заголовки, уходят в браузер. Поэтому, кстати, сегодня никто в PHP не-вьюхах файлах закрывающих тегов не ставит.
Я ньюфаг, делаю сайт, который для начала должен просто регистрировать пользователя в БД, отображать данные из БД в нужных местах на нужных страницах, работать с html-шаблонами. Есть несколько вопросов. 1) Чем чревато создание шаблонизатора таким образом, что он парсит содержимое файла, через echo str_replace(array_keys(МАССИВ), array_values(МАССИВ), file_get_contents($this->path.ИМЯШАБЛОНА)); выводит пользователю на экран. Потеря в производительности? Другие подводные камни? 2) Структура проекта такова, что любой php-скрипт, на который осуществляется переход с передачей POST или GET, передает все параметры и производит вычисления через другой класс, запрашиваемый через require_once. То есть, какой бы не был php-скрипт, все вычисления, связь с базой данных, и прочее происходит через отдельный класс, и можно сделать так, что всё отображение производится через единственный index.php а все вычисления и связь с БД через core.php. Какие здесь подводные камни?
Спрашиваю, чтобы не наделать делов и потом переделывать весь проект в случае, если пойду по неверному пути.
На голом ПХП пишут только ньюфаги в этом ИТТ треде. А во всех фреймворках выходной поток перехватывается, и ничего лишнего никуда не уходит раньше времени.
>Чем чревато создание шаблонизатора > всё отображение производится через единственный index.php а все вычисления и связь с БД через core.php
Ты щас занимаешься тем, что изобретаешь собственный фреймворк. В первом случае ты делаешь тормознутое говно, а во втором - к твоей чести - ты все делаешь правильно. Ещё чуть чуть и до MVC самостоятельно додумаешься.
Не страдай фигней. Возьми микрофреймворк какой нибудь, типа Slim - там всё это уже изобретено для тебя куда более опытными дядьками. Если очень интересно - как это правильно делать - можешь исходники того же Слима почитать.
>>438671 А насколько тормознутое? Например, при 100 пользователях онлайн на каком-нибудь типичном недорогом хостинге будет ли задержка заметна. Не хотел вставлять php-код в html-шаблоны из-за безопасности, вдруг кто-то сможет каким-то образом включить свой код и творить всё что угодно. Ну а про MVC я читал уже, поэтому старался все компоненты изолировать друг от друга.
>>438675 >е хотел вставлять php-код в html-шаблоны из-за безопасности
какие то у тебя страные соображения о безопасности. как может повредить строка в шаблоне вида <?php echo $someVariable ?> если в $somevariable строка вида '<?php makeEvilThing(); ?>' ??
Она же ни при каких услдовиях не исполнится (если только ты её в eval() не передашь, но про этот оператор забудь, он не для нубов)
>>438681 Потому что ob_end_clean просто очищает буфер. Удаляет всё, что нарендерено. Но тебе же с ним что то сделать надо? Например echo ($renderer->render(['a'=> 'somestring]))
Сайт и бд в utf-8 кодировке. Читаю текстовый файл.
Файл в кодировке win-1251. И конечно же русский текст становится кракозябрами на php странице (чья кодировка utf-8) и не заносится в БД (где тоже все записи в utf-8)
Вопрос, как не трогая кодировку текстового файла (он должен быть в win-1251 - он генерируется одной програмулиной) и тем более кодировку сайта, всеже считать текстовый нормально
гугол мне выдает всякую хрень не связанную с вопросом
>>438846 Вместо <submit> делаешь <button>, вешаешь на него onclick-событие. Когда событие происходит, выполняется js функция которую ты привязал, она собирает нужные данные формы, создает XMLHttpRequest объект, в .open() указываешь ему хттп-метод и урл куда слать, если нужно знать результат отправки на .onreadystatechange указываешь колбек функцию которая будет обрабатывать результат и отсылаешь реквест через .send(данные запроса). Если выбран метод GET то будет .send(null), если POST, то строка в виде "поле1=значение1&поле2=значение2".
Задача рассчитана на то что бы делать её в ООП? Если делать в ООП то как правильнее описать класс, элементом класса будет каждое поле формы? То есть
class student { public $name; public $lastname; ... }
Как лучше сделать возможность редактирования, когда я писал в обычном процедурном стиле это задание я использовал в случае правильно записи в базу данных такой код
Потом по вот этому $_SESSION["id"] для записи в которой такой же id выводил ссылку по которой можно пройти на редактирование данных. Но что то подсказывает мне этот метод не правильный.
>>438861 Ну тогда надо повесить событие на поле. Там целый зоопарк их, в зависимости от того что тебе конкретно надо, есть onchange, onkeyup, onkeydown, oninput. Функция будет вызываться на изменение поля, будешь смотреть в ней, достаточно ли в поле инфы, чтоб её считать валидной и отправлять XHR если да.
>>438085 Подскажите хорошее облачное хранилище, чтобы моя локальная папка с проектом синхронизировалась с этим облаком. Дропбокс, гугл драйв не подходят так как синхронизируются только данные внутри их корневых папок. Яндекс диск не подходит так как он не отслеживает изменения файлов и синхронизирует только если появляется/удаляется файл. Спасибо
Ребятаны, как лучше в задание про рег.студентов поиск реализовать, что бы можно было ввести "iv 49" и две подстроки искались бы отдельно во всех столбцах?
если резать строку по пробелам, то приходится для разного количества подстрок разные запросы делать, это наверно не правильно
Вот есть у меня файл login.php который выглядит примерно так: http://ideone.com/mBz8XW Вот при удачном логине я начинаю сессию и кладу в массив $_SESSION два элемента. Далее они используются у меня в основном файле index.php и всё такое. Пока что всё правильно реализовано? Теперь у меня главный вопрос: как правильно делать разлогинивание пользователя через сессии? Не просто же ансетать все переменные которые ты клал в этот массив во время логина?
О, хорошо что ты написал. Я собирался посмотреть твой проект, но все откладывал на потом.
Вообще, уровень проекта довольно высокий, я вижу что ты разобрался и с асинхронной работой с сокетами, и с протоколами HTTP/Websocket, и с ООП.
Вот советы и замечания по коду.
Не вижу где в репозитории конфигурация для mongoDB. Например, где определяются индексы? Где создаются коллекции?
У тебя немного странно разложены файлы по папкам. Обычно делают одну папку для сущностей (вроде RoomEvent, RoomUser), другую для мапперов, и т.д. У тебя же как-то все получилось разбросано по разным папкам.
Не очень понятно зачем наследовать RatchetServer от Pimple. Обычно наследование используют чтобы расширить наследуемый класс, но RatchetServer это явно не расширение для DI контейнера. Возможно, ты копировал схему котору. использует Silex, но мне кажется это неудачная идея.
Далее, напрягает то, что у тебя там по факту 2 контейнера и приходится определять сервисы по 2 раза: в RatchetServer, и в Webapp. Гораздо лучше если бы и websocket сервер и приложение разделяли общий контейнер. Вполне можно использовать тот, что в Webapp.
При этом подходе одной сущности всегда соответствует ровно один объект. Если мы 2 раза пытаемся загрузить пользователя с одним и тем же id, то мы получаем тот же самый объект. При этом если ты хочешь реализовать IdentityMap сам, ты натолкнешься на утечку памяти: так как объекты только добавляются туда и никогда не удаляются, эта структура начинает неограниченно расти в памяти. При этом удалять объекты ты не можешь так как не знаешь, исользуются ли они сейчас где-то или нет. Решением этой проблемы является WeakMap — специальная структура, которая позволяет сборщику мусора собирать объекты из нее, если они больше нигде не используются: http://php.net/manual/ru/book.weakref.php
Не уверен, впрочем, что в твоем маленьком проекте это обязательно. Наверно, можно и без этого прожить, но знать про такую штуку стоит.
Класс RoomEvent наверно стоило сделать абстрактным.
Далее, не очень понятно по каким принципам распределен код по классам RatchetServer, Chat, RoomUserHandler, RoomEventHandler, такое ощущение что они примерно одним и тем же занимаются. Было бы логично оставить RatchetServer работу с соединениями, а всю логику поместить например в Chat. Зачем вообще нужны Handler-классы?
В приложениях обычно делают слой сервисов, который находится на уровень выше мапперов ( http://martinfowler.com/eaaCatalog/serviceLayer.html ), но в твоем случае получается 2 уровня: Handler и Chat, и один из уровней тут явно лишний. То есть лучше сделать 1 или несколько классов-сервисов, без Handler классов.
Насчет проблемы с заходом пользователя с нескольких устройств или вкладок, тебе надо вместо пользователя ввести понятие «соединения». Это относится и к удалению пользователя из комнаты (надо удалять соединение) и к untrackUser в UserHeartbeat.
> https://github.com/d-beekeeper/ratchat/blob/master/app/User/UserRegister.php#L39 > public function __construct(Webapp $app,$username,$password,$checkPass) Очень странно что в конструктор передаются имя и пароль. Наверно логичнее сделать класс-сервис для регистрации пользователей, а не класс для регистрации единственного пользователя. Тем более что в функцию registerUser(User $user) ты и так передаешь объект-пользователя.
> https://github.com/d-beekeeper/ratchat/blob/master/app/ADataMapper.php#L32 > protected function convertId($_id) Это очень странная функция. Ее не должно быть и она выглядит как костыль. Потому что создается ощущение что ты сам не знаешь в каком формате у тебя хранится id. нужно сделать, чтобы он везде хранился в единообразном виде, а не как попало. Особенно вот этот код шедеврально выглядит:
> if (!\MongoId::isValid($_id)) { > $_id = substr(md5($_id),0,24); Это какой-то кривой костыль, явно.
То же самое и с датой. Ты можешь делать преобразование id и дат в маппере при сохранении/загрузке: маппер для этого и предназначен вообще-то.
> @param RoomEvent|RoomEvent[] $roomsEvents Мне кажется, так делать не стоит. Это и усложняет код и повышает вероятность пропустить ошибку. Тип входных параметров функции должен быть однозначно определен.
> $roomUser->user = $this->cleanupUserInfo($roomUser->user); Это (фильтрацию аттрибутов) надо делать на этапе экспорта из объектов в массив (для кодирования в JSON). Ты даже можешь сделать у сущности метод вроде getPublicData() или делать фильтрацию снаружи сущности.
Также, получается не очень хорошая ситуация: ты в BackendToFrontendMessage при преобразовании в JSON удаляешь часть полей и у пользователей, а потом восстанавливаешь из JSON. В итоге у нас в приложении ходит 2 набора сущностей: полноценные и с отрезанными полями. Это провоцирует баги.
Внешних пользователей обычно делают как отдельную сущность, которая связана с внутренними пользователями соотношением много-к-одному. Это позволяет например с нескольких внешних аккаунтов входить в один и тот же внутренний.
> https://github.com/d-beekeeper/ratchat/blob/master/app/User/User.php#L73 > if (isset($this->username)) $attrs['username'] = $this->username; Не очень понятно, почему ты прововеряешь равенство поля null через isset, и не очень понятно почему такие поля не попадают в массив. В чем удобство того, что мы имеем массив с неизвестным числом полей?
> public function receiveByAttributes(User $user) Тоже странная функция. Как я понимаю, она используется для проверки уникальности имени, ну так и надо сделать функцию isUsernameUnique
Вместо curl в VkApi удобнее использовать нормальный ООП HTTP клиент, например Guzzle, это еще и сделает код гибким и тестируемым, позволив передать вместо Guzzle заглушку, и даст готовые объекты Request/Response (кстати на Request/Response наконец-то готовится стандарт: https://github.com/php-fig/fig-standards/blob/master/proposed/http-message.md ).
> $decoded = json_decode($string,true); > if (is_null($decoded) || json_last_error() !== JSON_ERROR_NONE) { При ошибке до if управление скорее всего не дойдет так как json_decode выдает Warning который некоторые фреймворки (не знаю как насчет Silex) превратят в ErrorEcxeption. Если ты хочешь обрабатывать ошибку сам придется поставить @. Это конечно бардак, система ошибок в PHP.
> public function receiveByAttributes(User $user) Тоже не очень удачно сделана функция, лучше явно передавать массив условий.
> TODO следующий блок нужно вынести в отдельный скрипт, исполняемый кроном раз в N секунд, где N < UserHeartbeater::MAX_USER_DEAD_TIME/2 Вообще, ты мог бы засунуть это в server.php, он же асинхронный и он может делать действие раз в N секунд. И запускать в отдельном процессе, чтобы он не блокировал обслуживание вебсокетов. Тем более что у крона минимальная периодичность запуска минута.
А сейчас у тебя если никто не обновит страницу чата, старые сообщения не удалятся.
> {{ app.security.token.user.username }} > app.session.getFlashBag.get('vk_error') Стоит явно передавать это в шаблонизатор, а то шаблонизатор очень глубоко в недра приложения лезет.
> <meta name="viewport" content="width=device-width, initial-scale=1"> Это ты скопировал или у тебя правда адаптивный дизайн?
> options.chat.find('#chat-message-template') Вместо того чтобы передавать словарь с одим параметром, лучше сразу передавать chat в конструктор. Вообще, options имеет смысл когда опций куча и большинство не обязательны, и это по моему не очень хороший подход. Тут например можно опечататься и никакого сообщения об ошибке не будет.
> options.chat.data('eventSequenceNum'), Вообще тут наверно проще без data-аттрибутов обойтись и передать число прямо в конструктор или метод setSequenceNum.
> Если не удалось установить ws connection, или он поработал и разорвался - делаем fallback к ajax transport Мне кажется, если вебсокет отвалился, но соединение возможно, лучше повторно соединяться через WS. Отваливающиеся соединения — обычное дело.
У тебя на клиенте есть какое-то ограничение на число отображаемых сообщений? Браузеры тормозят при большом числе DOM нод. Например, нет особого смысла отображать все сообщения, достаточно последних N, и в неактивных комнатах тоже, а добавлять новые можно при прокрутке. Посмотри, как например скайп это делает (он отображает сообщения внутри WebView, встроенного браузера, если я ничего не путаю).
> alert('Ошибка: ' + value); alert очень плохой с точки зрения юзабилити.
> this.chatRooms[event.chatRoom].addMessages Нет проверки что такая комната есть.
> this._$sendbtns.attr('disabled','disabled'); disabled надо ставить через prop(), так как это свойство. Атрибут лишь задает его начальное значение. Не путай свойства и атрибуты: http://stackoverflow.com/questions/5874652/prop-vs-attr
> Chat.prototype._enableControlBtns = function () { > this._$roomAddBtn.click(function () { удалять/добавлять события — признак плохой архитектуры. Используй disabled или переменную-флаг лучше.
> if (code==2 || code==3) { Там конастант нет что ли? Что за магические числа?
> https://github.com/d-beekeeper/ratchat/blob/master/web/js/chat.js#L290 > if ($(this).queue().length == 0) Это вообще где-то в документации описано? Почему ты в объект jQuery передаешь непонятно что? Если ты хочешь исплоьзовать очередь из jQuery лучше нормально создать отдельный объект через this.queue = $().queue();
> $messageTemplate.find('a.msg-template-avatar-link').attr('href',avatar); Тут явно стоит использовать шаблонизатор
В общем, такой вот набор советов по улучшению. Но в общем, код на очень хорошем уровне.
Еще мне кажется, все-таки стоит сделать тесты производительности. Вебсокеты используются как раз для обработки большого числа соединений, разработики монго много говорят про ее производительность, ты явно хотел сделать высокопроизводительный чат (хотя, он же работает в одном процессе и не масштабируется) и разумеется все это должно быть проверено тестами, так как на словах можно сказать что угодно. Ну и если ты хочешь стать highload разработчиком, то это полезное умение.
Для простых ситуаций вполне может хватить простых инструментов вроде ab или siege. ab (Apache Benchmark) просто шлет указанное число раз в указанное число потоков один и тот же запрос. Он примитивный, но позволяет оценить скорость обработки запросов. siege сложнее, он может слать запросы на разные URL по заранее составленному списку, имитируя действия разных пользователей. Также, ты можешь отправлять запросы например своим скриптом на php c http клиентом вроде guzzle.
Искать узкие места в скрипте можно с помощью профайлера, входящего в xdebug. Профайлинг можно запускать как для веб-приложения, так и для Cli скрипта при передаче определенных параметров. Файл с результатами можно просмотреть через программы вроде KCacheGrind или WinCacheGrind.
С помощью нагрузочного тестирования можно заметить проблемы при обработке большого числа соединений или сообщений: увеличение времени ответа, увеличение потребления памяти, падения приложения, рост числа ошибок.
Вот что, по моему, стоит протестировать:
- изменение времени добавления сообщения по мере их накопления. Просто сделай скрипт который отправляет сообщения в чат и меряй время обработки запроса. Например, время на отправку 1, 10, 100, 1000, 10000, 100000 запросов, а потом посмотри, нет ли деградации по мере накопления сообщений
- то же самое но с N подключенными слушателями
- проверку на максимальное чило клиентов (не уверен что это можно сделать стандартными средствами). Соединяешься с чатом с N клиентов, и смотришь как меняется время ответа с ростом числа клиентов и не упадет ли приложение
- то же самое, но каждый клиент отправляет 1 сообщение
- время загрузки страницы с чатом при наличии N сообщений в чате
- также, можно померять производительность ajax- и POST-транспорта, но это не так критично, так как мы предполагаем что использовать будет вебсокет.
В общем, тестирование дало бы тебе полезные навыки и наверняка обнаружило бы узкие места в приложении. Для чистоты эксперимента перед каждым тестом надо очищать базу.
Кстати, как у тебя с очисткой старых сообщений? Они когда-нибудь очищаются? Или производительность по мере их накопления деградирует?
Ну и вторая вещь, которой можно было бы заняться, это покрыть приложение тестами. Вот например мой обзорный урок про виды тестирования: https://gist.github.com/codedokode/a455bde7d0748c0a351a Почитай. может интересно станет с этим разобраться.
Ты можешь выставлять заголовки (и ставить куки) пока не начал что-то выводить. Если начал то поздно так как то что ты выводишь идет в теле ответа, а заголовки идут перед телом.
> global $phrasesDodge; Глобальные переменные это плохо. Лучше сделать в Game метод getRandomPhrase(). Константы не нужны так как они нигде не используются, а выбрать случайный элемент можно и без них.
> можно ли делать так как я сделал в function fillNotFilledStrings()? Вообще, плохой код. Зачем ты в классе Game снаружи меняешь свойтва героев. если можно просто сделать методы у героев и поместить код туда?
Этот код вообще абсолютно неправильный:
> $this->heroes[0]->doubleHit = $charAbs; Шанс на двойной удар это не свойство героя так как оно зависит от соперника. Значит оно должно вычисляться в методе а не храниться в свойстве.
> $this->heroes[0]->hitChance = round(($this->heroes[0]->skill надо сделать метод $hero->getHitChance вместо этого
> $this->heroes[0]->enemyBlock = $this->heroes[1]->block; Это вообще бессмысленный код. Зачем копировать свойство если мы всегда можем взять его из второго героя?
Вообще, странная идея хранить в герое свойства другого героя. Бред же. А если драка будет 3 на 3, ты в герое будешь свойства каждого соперника хранить?
Функцию fillNotFilledStrings() надо удалить и лишние свойства тоже удалить и сделать методы в классе Hero вместо этого.
> private function makeOneHit($hero) Почему передается только один герой? Он сам с собой дерется что ли? Надо сделать чтобы передавалось 2 героя, кто с кем дерется.
> if ($this->heroes[0]->health < $secondDamage) { для этого лучше сделать метод. Более того, вот это вот heroes[0] смотрится плохо. Нельзя циклом обойти, раз уж у тебя массив?
> return 1; Что это за магические числа? Непонятно что это значит? Кто победил? Тогда логичнее возвращать не число.а сам объект и null в случае ничьи.
> мощный рубящий удар, цель удара чудом избежала чудовищного удара. Что-то тут у тебя слово «удар» 3 раза повторяется. Лучше бы избегать таких повторов, а то как-то не очень хорошо смотрится текст.
> if ($this->heroes[0]->health < $secondDamage) { > $this->heroes[0]->health = 1; > $this->heroes[0]->health -= $secondDamage; Лучше сделать у героя методы takeDamage($damage) и isAlive() Ты же вместо того чтобы положить относящийся к герою код в его класс, разимазываешь его равномерно по всей программе. В ООП объект это набор данных + методы для управления ими. А ты не хочешь делать методы, а исплоьзуешь объект как массив, зря.
Вообще, чтобы ты лучше прочуствовал эту концепцию, сделай свойства закрытыми, то есть не public, а private и используй методы для доступа к ним и их изменения.
Бутстрап не надо разбирать на части. Кидай все как есть в папку css/bootstrap или static/bootstrap
Также, для классов есть 2 стандарта именования файлов (имя файла получается из имени класса), они помогут тебе когда ты захочешь использовать автозагрузку:
> Чем чревато создание шаблонизатора головной болью. Прочитай пункт 6 из статьи: http://habrahabr.ru/post/230737/ и откажись от этой идеи. Велосипедистов никто не любит, имей в виду. Исплоьзуй twig например.
В частности в твоем шаблонизаторе нельзя делать циклы, нет экранирования данных от XSS (урок по XSS: https://gist.github.com/anonymous/52adda0113428b274c64 ) и вооще тот кто потом будет читать твой код захочет тебя убить наверно за такое решение.
> То есть, какой бы не был php-скрипт, все вычисления, связь с базой данных, и прочее происходит через отдельный класс, и можно сделать так, что всё отображение производится через единственный index.php а все вычисления и связь с БД через core.php. Какие здесь подводные камни? лучше бы ты испльзовал фреймворк или микрофреймворк. Вообще, пока из твоего описания проблем не вижу.
Дело не в тормознутости (не факт что твой вариант тормозить будет). Почитай описание того же шаблониазтора twig и почитай какие там возможности и сравни со своим. Тебе придется писать более громоздкий и неудобный код в шаблоне и нельзя делать if, циклы и прочее. Как вообще без if и циклов ты собрался писать шаблоны?
Более того в php уже встроен шаблонизатор, лучше чем твой.
> Не хотел вставлять php-код в html-шаблоны из-за безопасности, вдруг кто-то сможет каким-то образом включить свой код и творить всё что угодно. если ты не используешь eval и его братьев (create_function, assert) то ничего не будет. А вот XSS можно пропутсить, но если почитаешь мой урок то научишься от нее защищаться.
А зачем ob_get... если без них будет так же? Более того, у тебя нет обработки исключений — при исключении ob_start никогда не отключится. такие вещи надо заворачивать в try/catch
Ладно, пусть так будет, хотя мне хак с font-size не особо нравится. Хорошие варианты по моему это вариант с комментарием и незакрытые теги. Главное чтобы ты знал про эту особенность CSS.
Это плохая идея так как форма не будет отправляться по нажатию Enter. Надо исплоьзовать событие submit и предотвращать действие по умолчанию в обработчике (preventDefault/returnValue = false).
> если нужно знать результат отправки на .onreadystatechange указываешь колбек функцию Это надо делать в любом случае чтобы обрабатывать ошибки отправки, блокировать кнопку на время запроса и показывать индикатор отправки. Если ты делаешь аякс то ты должен делать защиту от двойно отправки, обработку ошибок и индикатор иначе это будет кривая индусская поделка, которая постоянно будет ломаться и путать пользователя.
Ну и с аякс удобно работать через библиотеки, например jQuery.
Код по моему с ошибкой. Ты после битвы не восстанавливаешь состояние героев, в частности здоровье. Правильным решением будет клонировать героев и драться каждый раз новыми клонами (мануал: http://php.net/manual/ru/language.oop5.cloning.php ).
> то как правильнее описать класс, элементом класса будет каждое поле формы? Ты по моему не совсем правильно мыслишь. Ты думаешь что главное это форма и все строится вокруг нее. Но это не так. Главное — это модель, то есть сущность-студент, а форма это лишь способ изменять знаения его полей, и не обязательно едиснтвенный. Потому ты не должен делать класс представляюшщй форму с полями, а должен делать класс представляющий информацию о студенте.
> class student { > public $name; > public $lastname; Вполне подойдет, но имя класса надо писать с большой буквы.
> Как лучше сделать возможность редактирования, когда я писал в обычном процедурном стиле это задание я использовал в случае правильно записи в базу данных такой код Есть стандартный алгоритм работы с формой на все случаи жизни:
------------
$values = значения по умолчанию (пустые); $errors = пустой массив;
Если (форма отправлена через POST) { Переносим значения полей из POST в $values;
Если (все заполнено верно) { Делаем требуемое действие (например вставляем запись в БД); Редиректим куда-нибудь; Выходим; }
Кладем ошибки в $errors; }
Выводим форму($values, $errors);
----------
В твоем случае удобно в качестве $values использовать объект класса Student.
Сам же студент ничего про базу данных знать не должен. При таком подходе каждый занимается своим делом и код не спутан.
> Потом по вот этому $_SESSION["id"] для записи в которой такой же id выводил ссылку по которой можно пройти на редактирование данных. Но что то подсказывает мне этот метод не правильный. Неактивные в течение 20-30 минут сессии удаляются. Сессия это временное хранилище. Так что да, используй тут лучше куки для которых мы можем выставить срок хранения. например, можно генерировать каждому студенту при регистрации длинный уникальный код, записывать его в куки и его же исплоьзовать для аутентификации.
Можно настроить дропбокс папку на 1 уровень выше чем папка сервера наверно. Либо сделать git репозиторий в папке дропбокса и пушить в него периодически.
if принято писать с маленькой буквы (с большой пишут константы и имена классов, что это такое ты потом узнаешь). exit в строке 26 лишний, можно без него. Нет проверки на ничью.
Команды в скрипте выполняются по очереди, сверху вниз, только один раз. Чтобы они закольцевались, надо сделать цикл, об этом ты узнаешь в следующих уроках.
> как правильно делать разлогинивание пользователя через сессии? Не просто же ансетать все переменные которые ты клал в этот массив во время логина? Почему, unset вполне пойдет, а также там есть session_destroy для большей надежности.
> Вот при удачном логине я начинаю сессию и кладу в массив $_SESSION два элемента. сессия удаляется при 20-30 минутах неактивности. Это неудобно и тебе придется дополнительно что-то класть в куки дял автоматического перезалогинвания. Сессия не постоянное, а временное хранилище.
Не знаю. Можешь написать задачу, а я подскажу как ее разбить. А вообще, это умение приходит с опытом, смотри код правильно написанных библиотек, например Symfony 2, читай книги про паттерны (Фаулер паттерны проектирования корпоративных приложений). В большиснтве случае решение уже есть и не надо ничего придумывать.
>>439197 >Почему, unset вполне пойдет, а также там есть session_destroy для большей надежности. Вот так вот сделал logout.php, на который ссылка ведет при клике на свой ник в index.php, в общем всё как на форумах http://ideone.com/9kkdFG Правильно? Сначала я проверял условием
if(isset($_SESSION['user_login'])){ А вот тут ансетал элементы } но потом подглядел вот такой способ на хабре.
>сессия удаляется при 20-30 минутах неактивности. Это неудобно и тебе придется дополнительно что-то класть в куки дял автоматического перезалогинвания. Сессия не постоянное, а временное хранилище. Так что делать? Параллельно запускать соленые куки? Я прочитал вроде мануал по сессиям в новых версиях пхп5, и там сказано, что если на сервере включить нужные параметры, то всё будет ок, и механизм пхп сам будет слать куки, вот ссылка: http://phpfaq.ru/sessions#use >Научился бы уже плейсхолдерами пользоваться: Ты меня верно вычислил на раз, прости пожалуйста, что я не следую твоим советам. Я на самом деле следую им, но у меня столько косяков и пробелов, что я не могу нормально всё это систематизировать. На самом деле я просто откладываю некоторые вещи постоянно, и мне очень стыдно. Обязательно выучу и покажу более годный вариант тебе. Еще я такой человек, которому трудно учиться по книгам, мне нужен учитель, которого у меня нет, и поэтому я так медленно ползу, очень медленно.
> Вот так вот сделал logout.php, куча лишнего кода
> setcookie(session_name(), session_id(), time()-606024); session destroy и так это делает, зачем второй раз писать?
> echo "Тебе тут не место! Скорее всего отобразится как кракозябры так как нет тега meta уакзывающего кодировку
> session_start(); > if ( session_id() ) { После session_start скорее всего session id всегда будет непустой и if становится бессмысленным
> Я прочитал вроде мануал по сессиям в новых версиях пхп5, и там сказано, что если на сервере включить нужные параметры, то всё будет ок, и механизм пхп сам будет слать куки, вот ссылка: Ты понимаешь как работает сессия? данные сессии хранятся на сервере и подчищаются сборщиком мусора. В куках только id сессии. Соответственно еслим файл сессии удален на сервере то кука ничего не решает.
Делаются свои куки, например слогином и каким-нибудь хитрым кодом. Если сессия пустая то прежде чем считать пользователя разлогиненным мы проверяем есть ли куки и правильные ли в них значения и если да то создаем новую сессию и залогиниваем незаметно для пользоваетеля. Погугли, как работает галочка «запомнить меня»
И разумеется для этого наверняка есть либо библиотеки либо опции в фреймворках.
Для авторизации в куках можно хранить логин + хеш пароля или хеш от смеси пароль + какой-нибудь код. Например вконтакте раньше в куках хранил id и хеш от пароля.
Можно хранить в куках не связанный с паролем код, например просто длинный случайный код. В любом случае в куках должна быть информация идентифицирующая пользователя (кто это) и подтверждающая что это настоящий пользвоаетль, а не пытающийся притвориться им злоумышленник.
Некоторые вообще отказываются от сессий и используют только куки. Проблемы удаления сессий в этом случае нет.
Вообще плохо что ты сам изобртаешь систему авторизации. С твоим подходом она скорее всего окажется дырявая и ненадежная. Надо либо прочитать подробно о том как такие вещи делаются либо использовать готовую (какую? не знаю). Ну например если бы ты использовал фреймворки вродк Yii2 или Symfony 2, там уже все это реализовано.
> How To Remain Logged In - The Infamous "Remember Me" Checkbox
Я еще хочу найти информацию на русском но честно говоря половина ссылок на эту тему ведут на какие-то быдлокодерские форумы, которые я не готов давать в качестве образца.
>>439211 Вот переделал по мере возможностей учитывая критику. Куки сюда сейчас впаивать не буду, с ними я разбирался в другой задаче, где солил их и проверял через функцию, сейчас я просто разбираюсь с сессиями. >>439215 Да, спасибо, я не пытаюсь изобрести особо велосипед, я просто пытаюсь научиться использовать сессии. Ну и попутно выполняю учебное задание так сказать.
> Контроль отсутствия активности пользователя встроенными средствами PHP > ini_set('session.gc_maxlifetime', $sessionLifetime); Скорее всего нерабочий, так как очистка сессий может выполняться крон-скриптом как это делается в дебиане и ini set никак на него не влияет.
В общем, статья плохая и содержит какие-то странные велосипеды.
>>438085 https://github.com/Purplepeak/TestHub ОП, посмотри пожалуйста тестхаб, когда время будет. В основном хочется услышать мнение по поводу кода относящегося к составлению и прохождению теста.
>>439225 >> <!DOCTYPE html> > session_start( ); >Это не будет работать. нельзя ставить куки после того как начался вывод. Ну а как мне тогда указать кодировку не приплетая html? И при этом не делая отдельный шаблон под такую мелочь? Вместо обращения к юзеру сразу его релокейтить?
>>439227 >>439229 Кстати, в прохождении теста хотел сделать изящную деградацию. Но что-то очень много гемороя из-за нее, и на поиск решений уходило довольно много времени. Поэтому решил отложить.
А в чем проблема? Страница с вопросом это же обычная форма, а сохранить/далее/назад это обычные submit кнопки. По моему так элементарно все делается. Определить какая кнопка нажата легко если у них разные имена так как в POST посылается только нажатая кнопка.
>>439233 С этим-то я разобрался. Я забил на это дело, когда писал отображение ошибок валидации и кнопку "пропустить". К сожалению, сейчас не опишу проблему конкретно, код писался довольно давно.
Помогите разобраться в проблеме. После того как я худо-бедно сделал регистрацию / логин / логаут на своем учебном задании, я хочу прикрутить туда гостевуху, что бы пользователи могли оставлять сообщения. Вот что я делаю, пикрилейтед. Что я делаю не так?
ИТТ мы будем говнокодить на самом поганом и в то же время самом популярном языке для веб-разработки на стороне сервера. Юзаем LAMP или WAMP стек, по умолчанию.
The League of Extraordinary Packages is a group of developers who have banded together to build solid, well tested PHP packages using modern coding standards. http://thephpleague.com/
Уже порядком устаревшие, но тем не менее культовые обучающие книги по PHP для новичков: 1) PHP 5 для чайников – Джанет Валейд (2005) [Диалектика] 2) PHP5 в подлиннике (2-е издание) – Котеров, Костарев (2008) [bhv] И сотни других.
Awesome PHP – огромный список отличных библиотек и утилит, а также ресурсов по PHP на все случаи жизни. Есть также awesome-python и awesome-ruby. https://github.com/ziadoz/awesome-php
Pear Ныне мертвый стандартизованный набор библиотек PEAR (PHP Extension and Application Repository). http://ru.wikipedia.org/wiki/PEAR
Котаны, посоветуйте, мне есть вообще смысл ближайшее время пытаться влезть на вакансиию джуна? Похапэ знаю так себе - тут задачи прошел до кошек-мышек(не включая). Пару исправлений осталось. По оф.мануалу проходился, но практики в тех же исключениях/сессиях и прочей лабуде не хватает, если честно. Руку там не набил. ЖС-на самом примитивном уровне. Даже DOM так и не освоил. Это, в принципе подтянуть можно. Было бы. Если стоило бы. SQL - простейшие запросы. Даже, блеать, не помню как бэкап сделать. Верстка - периодически подглядываю в чит-щит. Временами не оче получается с позиционированием.
Время - неделя. Мухосранск. Готов работать за еду. p.s. После прочтения своего поста, в принципе, понимаю, что смысла нет, дурака валять не стоит, а стоит пойти говно месить. Чего-таки скажете?
>>439306 Сейчас попробую, а пока дропнул даже таблицу юзерс, что бы пересоздать её, потому что вот эту темку почитал http://stackoverflow.com/questions/2799021 Ну и собственно там написано что поле user_id должно быть идентично в обоих таблицах, ну и пара других ньюансов.
>>439313 Ну попробовать можно, от тебя не убудет. Тут был один, устроился с еще меньшими знаниями, после задачки на банкомат устроился куда-то за еду. А потом уволился потому-что ехать до работы было долго, ЛОЛ, теперь плачет тут. Говорит буст охуенный по знаниям, когда работаешь, изучаешь все в два раза быстрее, чем сидя дома.
>>439313 Собственно ничего не потеряешь если походишь по собеседованиям, я примерно твоего уровня, но мне что бы ходить по собеседованиям надо ехать в какой-то крупный город в моём 30К городе само собой нет никаких вакансий по ПХП, поэтому ещё месяца 3 а может и больше буду учить всё это дома, сейчас пока работаю копирайтером, поэтому деньги на элементарные вещи есть, можно не спешить. А если у тебя в городе есть то почему бы и не рискнуть?
>>439318 Всё верно говоришь почти, но не уверен что прям с намного меньшими знаниями. Самые азы mysql + php / php + html я знал. НУ и на пхп задачи все в плоть до бонусных таки прорешал. Собственно я и сейчас тут сижу, восстанавливаю старые знания после месяца задротства в игоры и учусь новому. Поэтому >>439313 конечно пытайся бро, лучше начать за минималку работать, чем дома ебланить.
Таки создал эту херню, >>439314>>439302 и тут я ссылался на несуществующую таблицу: user вместо users, а вот тут >>439250 так и не ясно в чем была проблема.
Котаны, делаю задачу на файлообменник, пока в процедурном виде без фреймвокров, и заметил такой момент, картинки и файлы которые созданы мной (при помощи пейнта, Ворда, блокнота и т.д.) нормально распознаются браузером при попытке их загрузить, в то время как скачанные картинки бразуер не видит, не распознаёт очень часто их размеры, типы а главное tmp_name, без которого я не могу их загрузить в нужную мне папку, код на пикче. Может каким-то образом надо помогать браузеру распознавать всё это?
Кстати, аноны, ещё один вопросик, как сделать так что бы файл можно было скачать? Я делаю на него ссылку, но бразуер его просто открывает в другом окне если это картинка.
>>439324 Да минималка-не минималка то пофиг. Они меня просто на хуй с порога не пошлют с такими знаниями?
Олсо, только в требованиях "джуниор-погромист" или и на просто вакансию "программиста" можно пойти проситься джуном? Или вообще пойти по адресам офисов аки бомж - "приютите, люди добрыя!", лел.
> а вот тут >>439250 так и не ясно в чем была проблема. Иногда создание ключа вместе с таблицей не работает. Если при этом в 2 этапа (создать таблицу а потом ключи) все работает то видимо это какой-то баг или особенность MySQL. Я сам сталкивался с ошибкой MySQL 150 и обычно разделение на 2 команды помогает.
Подробности о последней ошибке с внешними ключами можно увидеть командой SHOW ENGINE InnoDB STATUS \G (выполняется из под администратора, то есть root) в разделе LATEST FOREIGN KEY ERROR. \G нужна чтобы строчки не разрывало.
Попробуй запустить эту команду. Это конечно плохо что MySQL прямо не пишет в чем проблема.
Кстати команда SHOW ENGINE еще выдает много полезных данных которые пригодятся например при тюнинге размеров разных областей памяти для максимальной производиетлньсноти. Она документирована тут:
Еще эта штука покаызвает причину последней проблемы с блокироваками (она проявляется только на высоконагруженных сайтах, но ты хоть будешь знать где искать причину).
>>439333 Я просто запилил резюме джуниора на сайт по поиску работы и меня самого нашли. Но нужно все варианты пробовать, в том числе и тем писать у которых висит просто "прогроммист php" и спрашивать не нужен ли джун за еду. Стори о которой >>439318 упоминал возможно еще не уплыла, поищи в декабрьских тредах. Там картинки приложены к постам цветные, легко найти. А сейчас мне лень писать тоже самое, да и спать сильно хочется.
Пилю кулстори, начал изучать пыху здесь. Прошел тот базовый уровень обучения по ссылкам выше, параллельно просмотрел\сделал лекции Бауманки честно украденные кем-то и выложенные на рутракере, потом были всякие wisdomweb and javascript.ru, учебник Астаховой по SQL, естественно до кучи научился юзать гиты-композеры, есть даже написанный проект на пыхе и что ты думаешь, анон, я блядь не могу устроиться ебаным джуном. Заебался уже резюме рассылать - либо морозятся, либо мы бы тебя взяли, если бы ты в совершенстве владел ZF2, Yii, Magento\Drupal\WP. Что я делаю не так? Не дохуя ли джуну "отличные навыки в МВЦ и ЦМС", я конечно раздуплил сейчас пару ЦМС, но честно говоря мне кажется, если я еще пару месяцев буду зубрить\писать проекты, то я буду уже СТРОНГ джуном, а куда тогда берут обычных джунов за еду? ЧЯДНТ?
>>439377 >>439375 Всё потому, что пхп не воспринимается как серьёзный язык для веб-дева. Все думают, что ты должен был учить его лет с 14 в школе или хотя бы в инсте, а годам к 20-23 ты должен был по идее всё это знать. Или у тебя должен быть бэкграунд, чтобы всё это выучить за пару месяцев, а не учить всё с нуля в 25. Да дело даже не в конкретных цифрах возраста, а в том, что ты поздно начал.
>>439193 я пробовал. дропбокс, хорошо, но там лимит 2гб, а у меня проект 4. там картинки и разная поеботина, а если грузить сугубо код, то теряются пути к этим самым картинкам, так как ссылки относительные. но я нашел неплохую альтернативу - cubbies.
Ребята, дико заебался с кодировкой. когда через аякс передаю значение в файл, который должен его записать в бд, кирилица читается норм(вывожу через эхо, например) но вот в самой бд там закарлючки. Файлы в windows-1251. Сами файлы: https://ideone.com/caGrwo https://ideone.com/xzAvbb Вместо буквы "я" записывается "СЏ". Пикрелейтед кодировки в моем опенсервере и phpсторме. Пробовал менять кодировку с помощью: iconv_set_encoding("output_encoding", "WINDOWS-1251"); iconv("UTF-8","windows-1251",$name); в самом ajax файле, но по неясным причинам это не помогает. Буду рад любой помощи, потому что нет больше моих сил.
>>439377 Так пиздуй работать грузчиком или продавцом-консультантом. С хуя ли ты решил, что потратив месяц на чтение учебников ты уже стал специалистом и можешь приносить хоть какую-то пользу? Думаешь, кто-то будет тратить время и деньги на твое обучение?
Пиздец. Паттерны, заморочки, ООП-говно. Как всё это выучить и откуда брать материал? Как же не хочется ебать мозги месяцами и искать верный епути иметодом тыка всё пробовать. Почему в 2015 нет нормального руководства по всему этому говну? Нахуя всё так усложнять?
>>439451 > на начальном Это на котором учишь синтаксис? А когда начинаешь пердолить бложек или ресурс с богатой админкой/лк, паттерны тоже не нужны? И где всё это брать после начального этапа?
>>439456 >Как узнать, что мне нужен молоток и для чего, на каком этапе и т.д.? >Как узнать, что я хочу какать и для чего, на каком этапе и т.д.? Изучай MVC на примере любого фреймворка. Остальное используется редко и нужно понимать, для чего конкретно, а не просто впердоливать чтоб было.
Аноны, я всё никак не уймусь, прошу подсказки уже второй раз. Кажется браузер не распознаёт картинки, когда я пытаюсь их загрузить через форму загрузки файла, вернее распознаёт только те которые созданы мной (при помощи Paint например), все остальные просто не распознаёт, то есть ничего не записывается в:
$_FILES["filename"]["tmp_name"];
Когда загружаю обычное изображение в формате jpeg, png или ещё в каком-нибудь. В то время как картинки созданные мной в пейнте получают свой tmp_name, это может быть ошибка с браузером или с операционной системой? Или это нормально?
ООП немного описан в учебнике из ОП-поста, а также в 2 книгах. Я вообще не знаю, где изучают ООП, наверно есть какая-то хорошая книга на эту тему, но я ее не читал.
Насчет паттернов, начинающему их тружно понять, так как у него мало опыта и он может просто не понять вообще о чем речь. Паттерны это способы решения типичных ситуаций, возникающих при разработке.
Самая известная (культовая?) книга про паттерны это книга Фаулера «Шаблоны корпоративных приложений» ( Patterns of Enterprise Application Architecture ). Фаулер (это чувтвуется по тексту) очень опытный и умный программист, видел большое число приложений и он пытается в книге обобщить какие есть варианты решения той или иной проблемы, какие преимущества и недостатки.
Ты можешь почитать книгу, но будь готов к тому, что ничего не поймешь. Книга ориентирована на опытных, а не начинающих программистов.
Если ты посмотришь, то увидишь что паттерны во многом связаны с ООП и работой с базой данных. Это потому, что большинство приложений использует ООП и работает с базой данных (капитан очевидность).
Учить паттерны начинающему бессмысленно, если он их не понимает. Если какая-то компания спрашивает знание паттернов у людей без опыта то это издеватеьство над здравым смыслом и скорее всего там эти паттерны толком никто не знает кроме какого-нибудь синглетона (кстати синглетон это скорее вредный паттерн).
Некоторые паттерны (и ООП с MVC) ты можешь изучить в ходе решения практических задач в нашем треде.
Если у тебя есть какие-то вопрсоы или что-то непонятно, задавай.
Ты можешь сделать то что я писал выше то есть поставить var_dump($_FILES); в начале скрипта и показать нам что он выводит? Твое описание к сожалению не позволяет установить причину проблемы.
> Остальное используется редко дело даже не в том что редко, а в том, что ты можешь этого не знать. Ты используешь Doctrine 2 например но не знаешь что она использует внутри паттерны Data Mapper, Identity Map, lazy Loading и другие (хотя конечно это плохо если не знаешь).
> А когда начинаешь пердолить бложек или ресурс с богатой админкой/лк, паттерны тоже не нужны? Такие вещи никто не пишет с нуля а берут фреймворк или CMS на худой конец и делают как там принято и как описано в документации.
> И где всё это брать после начального этапа? У нас есть неплохие практические задаки которые учат писать простые приложения с базой данных, с ООП/MVC. Они в ОП посте есть.
А зачем ты используешь win 1251? Странная идея конечно.
> когда через аякс передаю значение в файл, который должен его записать в бд, кирилица читается норм(вывожу через эхо, например) но вот в самой бд там закарлючки. SET NAMES делаешь и если делаешь то какой?
>>439483 >есть неплохие практические задаки Задачи есть, а как их решать не понятно, например. Откуда? Ведь есть только базовые уроки, документация, в которой куски кода, вырванные из контекста и всё. Откуда я могу узнать об ооп/mvc, если не знаю об их существовании. Советуют изучать по готовым фреймворкам, но как понять зачем это было сделано, вдруг это Вася какой-нибдуь очередной велосипед придумал. Ну и то же касается и других вещей. Это не претензия к ОПу, если что, просто опытные программисты напридумывали каждый свой велосипед, объединились в группы, а как это понять и дойти до этого новичку не понятно. Нет какого-то единства и конкретики. Подчеркну, что это со стороны новичка, а не со стороны того, кто в этом разбирается.
> iconv_set_encoding("output_encoding", "WINDOWS-1251"); Это тут не при чем (я сам не очень понимаю на что влияет эта настройка). ты не должен ставить наугад разные команды в надежде что все исправится, лучше разобарться в проблеме, это тебе потом пригодится.
> в самом ajax файле, но по неясным причинам это не помогает. Потому что SET NAMES не делаешь и там какая-то другая кодировка для взаимодействия с БД исплоьзуется. Ты должен через SET NAMES сказть базе данных в какой кодировке ты передаешь и принимаешь от нее данные.
Ну и я удивлен что кто-то в 2015 использует win 1251.
В разных компаниях разные требовния. Но от более взрослого кандидата наверно могут ждать больший набор знаний. Ведь молодого еще можно взять в надежде что он доучится, а взрослый наверно уже сам должен был к 30 годам все что нужно успеть выучить.
Я работая в одной компании слышал примерно такое: «люди после 25 у нас плохо уживаются».
Если есть такая возможность ты бы мог устроиться парт тайм на какую то работу, а оставшиеся полдня учить php. Наш тред всегда готов помочь с обучением.
Все зависит от компании. Где-то берут стажеров с минимальными знаниями, где-то требуется пилот шаттла.
Насчет знаний CMS/фрйемворков если компания маленькая то может быть предпочтительнее человек со знанием нужного продукта, который сразу войдет в курс дела.
Ну и с нынешней экономической ситуацией не стоит быть слишком разборчивым. денег будет меньше, нанимать будут меньше людей.
> а как их решать не понятно, например. Должны быть уроки которые этому учат, но их пока нет потому что ОП их не написал. Потому аноны идут, ищут какие-то уроки на других сайтах, делают, показывают решение, ну и половину примерно потом еще переделывают чтобы было правильно.
По идее там должны быть уроки про то как установить себе php/апач, как работает браузер и веб-сервер, протокол HTTP, язык HTML, про работу с формами в HTML/PHP, про базы данных и язык SQL, про работу с базой данных через PDO, про MVC, про Data Mapper (ну этот урок у меня написан: https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a )
Сразу после учебника можно прочесть про работу с формами, например вот это для начала:
ну и если что-то еще непонятно, ты можешь задавать вопросы в треде.
> Откуда я могу узнать об ооп/mvc, если не знаю об их существовании. Основы ООП же есть в учебнике, в последней главе. Читал? Также про ООП есть информация в книгах Зандстры и Шлосснейгла (в ОП посте).
MVC нету, но вся суть MVC в разделении кода на контроллеры, модель и view, можно нагуглить статьи на том же хабре.
> просто опытные программисты напридумывали каждый свой велосипед, объединились в группы, а как это понять и дойти до этого новичку не понятно. Ты можешь дойти, если так хочешь, но это будет долго. Ведь писать фреймворки гораздо сложнее чем использовать готовый. Потому и используют готовые. а не пишут свои. Но если ты очень хочещь, ты можешь попробовать ,а я укажу где косяки и чем плох твой подход.
> Нет какого-то единства и конкретики да, нету, потому что тут довольно большой объем работы и одному все эти уроки написать довольно сложно и требует много времени. Но с другой стороны, я вижу что другие аноны в итоге как-то справляются с задачами — значит все это можно где-то найти.
>>439445 вызубрил ООП, щеголял пособеседованиям на джуна, неплохо отвечал, но понял его только когда начал проэкт ооп писать. Такие дела. Теория без практики хуита, выше анон верно сказал, что ооп учится в процессе. Для начала почитай в целом за него, потом напиши что-нибудь в стиле ооп и дело в шляпе, азы выучены.
Выглядит норм, но если присмотреться, видны пара косяков в дизайне.
Во-первых, на кнопках текст упирается в край кнопки, ему там тесно — это некрасиво, надо чуть увеличить поля.
Сами кнопки можно сделать разными — кнопку «провести генерацию» сделать ярче чем «очистить данные», так как она основная.
Во-вторых, у тебя подпись к инпуту от него оторвана и прижата к соседнему инпуту выше. Это неправильно — подпись должна быть ближе к тому инпуту, к которому относится.
Сами поля ввода я бы сделал меньше по длине. Ведь в них будет вводиться всего 2-3 цифры — зачем такие длинные поля ввода?
пхп переменные мы называем $cameCase например. А как называть html-переменные которые скажем потом пойду в $_POST[]? До этого они у меня были простыми очень, по типу text, name, и соответственно из поста я забирал $_POST['text'], $_POST['name'] А сейчас у меня переменная из 2х слов впервые появилась, как быть в этом случае?
Пыхо-аноны, где найти готовый простенький сайт на PHP + MySQL? В гугле ничего путного не нашёл. Я нулевой в пыхе и мне надо для курсовой сделать интернет-магазин. С готового сайта проще разобраться и переделать под себя. Выручайте. Пикрандом.
>>439632 >Я нулевой в пыхе и мне надо для курсовой сделать интернет-магазин. Хуя себе, как по мне, то скорее всего уже уровень диплома, если самому писать. Но вообще наверное есть какие-то заготовки, и можно побыстренькому, хуяк-хуяк и только дизайн натянуть осталось и заполнить базу. Так что гугли эту хуйню.
>>439633 >>439634 Спасибо за ответы, анончики. Попробую на этом opencart, ибо лень основательно вникать. >>439656 Я ради тебя расчехлил своё старое задание по пыху на тему ООП, а там вот такое вот, пикрелейтед. Попробуй это, судя по всему функция сама подгружает классы. Погугли доки если что.
Взялся за давно заброшенную страничку. Тут простенькая валидация логина и пароля. Проблема в том что страница не грузится ВООБЩЕ, белый экран, до <html> даже не доходит интерпретатор. То есть вроде как ошибка в синтаксисе, но я ее не вижу хоть глаза выколи. Если этот кусок закомментировать - все ок, формочка показывается(но не работает, само собой). Причем на локальном серве все работает, а вот на удаленном - хрен и отображение ошибок там отключено в php.ini, включить нельзя.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
> включить нельзя. через ini_set('display_errors', true) пробовал?
А вообще то там должны быть логи и ты можешь посмотреть причину ошибки в них. Так будет правильнее. Пользователям незачем видеть подрбности потому на смотрящих в итнетрнет серверах отображдение ошибок отключают.
Во-вторых, праивльнее будет сделать датамаппер синглтоном в слиме, как описано тут http://docs.slimframework.com/#DI-Overview в разделе Singleton resources и обращаться к нему через $app->fileMapper
>>439671 >>439674 на локалхосте у меня ошибки включены, но их и нет. на удаленном php.ini изменить никак нельзя, в панели управления вроде как логи должны быть, но то ли отключены для бесплатных тарифов, то ли я найти не смог, написал в поддержку. пока ждал ответа начал перебирать, отключая по одной строчке. оказывается, нельзя создавать массив таким образом как у меня, то есть $_SESSION=[a,b,c,d]; через array(a,b,c,d) все работает. версия пыхи, что ли. неслабый такой подводный камень, приходится теперь вылавливать на всех страничках.
>>439666 Можешь перед этой штукой воткнуть error_reporting(-1);
Еще я у тебя не вижу mysql_connect(...) перед тем как делать запросы в базу.
Далее я бы начал с простого, например после первого же твоего var_dump($_POST); У тебя условия такие, что может быть они просто не выполняются, поэтому ничего и не работает.
Далее может быть дело в том, что на удаленном сервере неподдерживаются функции mysql_... пропробуй переписать через mysqli_...
The page you are looking for could not be found. Check the address bar to ensure your URL is spelled correctly. If all else fails, you can visit our home page at the link below. Visit the Home Page
array(0) { } и кнопка
хотя урл же не меняется и роутер должен нормально стработать
Если я в пхп создам массив из строк вроде $array = ['a', 'b', 'c'], то они будут хранится в кодировке файла? Если у файла кодировка utf-8, то как мне отсортировать строки в натуральной сортировке без смены локали (это ведь жутко неудобно)?
Антоны, записываю в базу данных дату таким через переменную:
$dt = timе;
Но дата не записывается, записывается 000-00-00, если через пхпмуадмин зайти и кликнуть по полю где это значение, то дата появляется. Вообще не понимаю что происходит, что это может быть?
> Если у файла кодировка utf-8, то как мне отсортировать строки в натуральной сортировке без смены локали (это ведь жутко неудобно)? Смена локали это плохая идея, плюс локаль работает только с 8 битными кодировками, а не с utf8 и тебе никак не поможет.
Во-первых, ты можешь отсортировать с помощью sort. Она сортирует не по правилам, а по кодам символов, но вдруг отсортирует как надо?
>>439796 не удержался, когда несут бред, >В Бд даты надо передавать в виде строки никогда не слушай этих "умных", даты переводы в ЧИСЛО и передавай ТОЛЬКО число, и храни именно ЧИСЛО. поиск среди чисел в 1000раз быстрей, занимаемое место ячейки бд всего 4 байта, индекс строится как бтрее в 100раз быстрей чем по строке datetime, легко получить лубую дату через date('str',time) и т.д.
Ты вставляешь кусок html прямо после вызова фреймворка. Получается у тебя для любых страниц выводится один и тот же html? Все страницуы будут одинаковые?
Более того, плохо вообще в одном файле смешивать php код и html шаблон.
Фреймворк slim предоставляет микрошаблонизатор для решения этой проблемы. Фактически этот микрошаблонизатор просто подключает указанный php файл и передает в него переменные.
Почитай документацию (если ты не понимаешь английский хотя бы примеры кода посмотри и попробуй перевод через bing translate почитать: http://www.bing.com/translator/ - там часть текста понять можно).
Учить его не надо, но хотя бы полистай, посмотри какие вообще типы бывают.
- не используй параметр filename в заголовке content-disposition. Для него не определена кодировка (точнее определено стандартом что нельзя использовать ничего кроме латиннциы) и разные бруаузеры воспринимают его по-разному.
Это был разбор кода. Теперь вернемся к твоему вопросу.
> Из $app->get вообще можно что то получить? > Мне нужно в хтмл использовать $file, но как её достать? Ты вызываешь app->render и передаешь туда все переменные, которые нужны.
Если есть еще какие-то вопросы по Слиму или вообще, уточняй.
Вообще, со Слимом твое приложение (точнее файл index.php) должен выглядеть примерно так:
// задаем функции обработчики для разных видов запросов $app->get ... $app->get ... $app->post ...
// запускаем приложение $app->run();
Если ты знаком с MVC то у нас фактически тут контроллеры пишутся внутри app->get и app->post. Напомню что app->get задает функию-обработчик для определенных GET запросов, а post для POST.
Еще нехороший момент: зачем ты пишешь присваивание внутри return?
> return $file=$mapper->showFilebyID($id);
надо писать в 2 команды как
$file=$mapper->showFilebyID($id); return $file;
Но если подумать то какой смысл создавать переменную file? Не логичнее ли сразу написать
return $mapper->showFilebyID($id);
Ты случайно не думаешь что в return $file = ... имя переменной file на что-то влияет? return просто возвращает значение, неважно как названа переменная (и есть ли там переменная вообще). Он возвраащет число, строку или что ты там ему передашь, а имя переменной не важно.
Ох, ты случайно не пропустил несколько глав в моем учебнике? Если бы ты эти ошибки в задачах делал я бы обязательно обратил внимание.
> `place` int(2) NOT NULL, > `sex` int(1) NOT NULL, Тут лучше подойдет ENUM. Я например смотрю на SQL код и не могу понять что значит 0 или 1. И другой человек, который захочет разобрать твой код, тоже не поймет без анализа кода.
В сложных случаях в SQL ты можешь добавлять комментарии к колонкам или всей таблице. Эти комментарии сохраняются в базе и отображаются в программах для работы с БД. Используй их: http://stackoverflow.com/a/200033
> `groupnum` int(5) NOT NULL, Лучше номер группы сделать строкой. А то как ты будешь сохранять номер 00010?
> `year` int(4) NOT NULL, Есть тип YEAR и догадайся-ка, для чего он придуман?
Я вижу ты плохо знаешь типы данных. Почитай (учить наизусть не надо, но ответ на вопрос «в чем хранить дату» или «в чем хранить номер телефона» или «в чем хранить сумму с копейками» знать надо):
Также, я советую поставить в редакторе настройку «заменять таб на 4 пробела», а то смотри как у тебя код расползся на гитхабе некрасиво.
> $id=$_COOKIE['studentscookie']['id']; Это ненадежно. Злоумышленник может подставить себе любой id (куки ведь хранятся в браузере) и редактировать чужую страницу. Чтобы он этого не мог сделать, надо вместо предсказуемого id использовать сложный случайный код, который генерируется при регистрации (у каждого студента он свой и злоумышленник его не знает). 32 или больше символа из диапазона [a-z0-9] вполне подойдут.
> if($mapper->emailUsed($_POST['email'])) Имя функции начинается с глагола, например isEmailUsed. Также, не забывай всегда ставить {} после if.
> https://github.com/NotBadCode/Students/blob/master/list.php#L5 > if(!isset($_COOKIE['studentscookie']['id'])){ То же самое, после header надо делать die. Ну и по условиям задачи список можно смотреть без регистрации. Ну и ты не должен молча пересылать пользователя на другую страницу. Ты должен в такой ситуации выводить там сообщение вроде «Список могут просматривать только зарегистрированные пользователи. Зарегистрируйтесь, чтобы полуить к нему доступ.»
Кстати, после обновления данных/регистрации надо выводить соответствующее сообщение. А то если форма молча перезагружается то не понятно — все в порядке или это ошибка какая-то?
> if(isset($_POST['submitsearch'])){ Для поиска (и других действий не меняющих данные на сервере) используют GET. Это позволяет например переслать ссылку на результаты поиска. Посмотри например как выглядит ссылка если зайти на http://ya.ru и что-нибудь поискать.
Аналогично, сортировка и постраничная навигация (она у тебя есть?) делается GET-ссылками.
> https://github.com/NotBadCode/Students/blob/master/lib/pdo.php#L9 > class DataMapper В файле с классом не должно быть постороннего кода вроде «new PDO». Каждый класс должен быть назван с большой буквы, а имя файла соответсвовать имени класса: Class -> Class.php В одном файле может быть ровно один класс и ничего больше.
Насчет именования классов и файлов, есть стандарты:
То что я написал выше, примерно им соответствует (PSR-4 требует все классы класть в неймспейс, но в нашем приложении из 10 файлов это не имеет особого смысла).
Класс логично назвать не DataMapper, а ProfileMapper.
> https://github.com/NotBadCode/Students/blob/master/lib/pdo.php#L21 > ORDER BY $sort $order"); Если ты подставляешь переменные в запрос, сделай тут же в функции проверку что они соответствуют разрешенному списку значений, иначе непонятно есть тут SQL инъекция или нет (SQL инъекция это когда злоумышленник вставляет свои данные в SQL запрос). Изучи теорию, проверь есть ли у тебя тут инъекция (я думаю есть) и добавь проверку:
SQL инъекция при умелом использовании позволяет получить все данные из базы, а в тяжелых случаях еще и менять их, читать файлы на сервере, в том числе с паролями, то есть полностью взломать сайт.
> WHERE name LIKE :request Там требуется искать по любой колонке.
> $STH->fetchAll(PDO::FETCH_CLASS, Имей в виду что такая конструкция создает объект без вызова конструктора (это пример непраивльного проектирования: ситуаций когда объект создается в обход конструктора быть не должно. Тот кто это делал явно не разбирается в ООП). Это неприятно, так как можно долго искать почему код в конструкторе не срабатывает. Добавь хотя бы флаг PDO::FETCH_PROPS_LATE (мануал http://php.net/manual/ru/pdo.constants.php )
Вот вопрос на SO с хорошим примером исплоьзования FETCH_CLASS когда параметры передаются через конструктор: http://stackoverflow.com/a/9134544 но он годится только когда их немного (так как делать конструктор с 9 аргументами неправильно).
> https://github.com/NotBadCode/Students/blob/master/lib/pdo.php#L49 > $STH->setFetchMode(PDO::FETCH_CLASS, 'profile'); Не используй setFetchMode, а передавай параметры прямо в fetch. Почему? Потому что setFetchMode делает код непредсказуемым: мы не знаем что нам вернет $STH->fetch так как не знаем с какими параметрами вызывалась setFetchMode до этого. В итоге мы теперь должны каждый раз ставить setFetchMode. Это в общем тоже пример неправильного проектирования, таких функций быть не должно.
> public function addStudent(Profile $profile) Обычно такая функция после вставки должна получить id из базы и записать его в $profile.
> $STH->bindparam(":name", $name); > $name=$profile->showName(); Зачем ты испльзуешь bindParam? Он предназачен для двухсторонней привязки (с получением данных из базы) и почти никогда не нужен. Используй bindValue, в который данные можно передать без промежуточной переменной, и сделай функцию в 2 раза короче.
> public function getLastID() Такой функции лучше не делать, так как результат который она вернет зависит от того какие функции вызывались ранее. Лучше при вставке в объект прописывать его id
> $STH=$this->DBH->query("SELECT COUNT(... Это неправильно. Во-первых, в базе могут быть пропуски (записи удалялись) и надо писать MAX(id). Но и MAX(id) использовать неправильно из-за того что при параллельной регистрации получается такая ситуация:
- первый студент делает INSERT - второй студент делает INSERT - первый студент делает SELECT MAX(id) и полуает id второго студента - второй студент делает то же самое
Видишь, какие сложные баги нам это принесет? К счастью, решение есть. У PDO есть метод lastInsertId который возвращает id последней вставленной записи в текущем сеансе связи с базой.
> https://github.com/NotBadCode/Students/blob/master/lib/profile.php#L15 > public function setFields($data) У тебя в одной функции объединено 2 вещи: простановка полей из массива и проверка на правильность. Надо разнести их в 2 отдельных функции, а то проверку нельзя вызвать без установки значений. Неудобно и нелогично.
Ну и еще, ты при ошибке не меняешь свойства объекта. Но ведь это значит что при вводе неправильного значения пользователь увидит пустую форму и все введенные данные потеряются. Лучше сначала скопировать все значения в объект, а потом проверять сам объект.
Я от себя посоветовал бы во второй регулярке поменять точку на \S. Это защитит от ошибок когда пользователи вместо @ пишут пробел. Хотя твоя регулярка неплохая и годится для задачи.
Ну и знай что в PHP есть функция для валидации email (хотя мне эта функция не нравится, так как она встроена в PHP и ты не можешь никак на нее повлиять):
> <?if($error=="sex"):?> style="border:2px solid red;" лучше не писать стили, а добавить CSS класс. Тогда мы легко можем менять вид проблемного инпута через CSS. Явно стоит тебе порешать мои задачки на верстку.
>>439990 Спасибо анон, ты тут расписал больше чем дал мне вузик за полгода. Буду исправлять. Почему ты так критично относишься к ифам без фигурных скобок?
А с вёрсткой просто было лень заморачиваться так то у меня есть несколько сверстаных макетов на гитхаб.
> Тело каждой управляющей структуры НЕОБХОДИМО заключать в фигурные скобки. Это стандартизирует вид управляющих структур и уменьшает вероятность возникновения ошибок при добавлении новых строк в тело.
А если ты не ставишь скобки то скобки за тобой придется ставить кому-то другому при редактировании.
Да. Причем так как эти функции воспринимают любой текст как 8-битный то utf8 коды символов будут искажены и получится битый текст. У меня чуть чуть этот тут описано: https://gist.github.com/codedokode/ff99e357e9860ea169b8
Что то у меня не пошла автозагрузка средствами композитора. классам написал namespase App; и в composer.json { "autoload": {"psr-4": {"App\\": "uppy/"}} } Но не заработало. Пришлось сделать так как сделал.
> https://getcomposer.org/doc/04-schema.md#autoload > When autoloading a class like Foo\\Bar\\Baz a namespace prefix Foo\\ pointing to a directory src/ means that the autoloader will look for a file named src/Bar/Baz.php and include it if present.
В твоем случае он при автозагрузке App\\Class будет искать uppy/Class.php а не uppy/App/Class.php
Не забудь после изменений вызвать команду для перегенерации автозагрузчика:
> After adding the autoload field, you have to re-run dump-autoload to re-generate the vendor/autoload.php file.
Ну и называть неймспейс App плохая идея, лучше название проекта использовать. Ведь идея неймспейсов в защите от конфликтов имен, а если все будут называть неймспейс App то конфликты будут.
Пхп-мастера, подскажите пожалуйста. Хочу поставить modx не в корневую папку, т.е. чтоб в паблик_хтмл была не путаница из папок самой модх, а допустим мои папки с стилями и жс, и папка с названием модх, в которой собственно сама цмс. Собственно вопрос - как сделать чтоб при заходе на сайт отрабатывала сама модх? Первое что пришло в голову это редирект апачем, но понимания как это сделать нет. И хочется чтоб в адресе не было самой папки модх, а ведь если будет туда редиректить, то и в адресе оно будет? Или совсем не в ту сторону думаю?
- текст статьи вываливается влево под меню - пункт меню с длинным текстом переносится на вторую строку, и она выглядит как отдельный пункт. Надо чтобы при перенносе межстрочное расстояние не было таким большим.
> <div id="header"> > <h1> Тут в принипе div не нужен
Ну и насчет полей. Такие вещи обычно проще делать через паддинг на родителе (body например) чем на каждом элементе ставить margin 10px;
> font-family: 'Trebuchet MS'; Надо объявлять тут еще станадртный шрифт вроде serif/sans-serif на случай если требушета нет.
> vertical-align: top; Это свойство применяется только для 2 вещей:
- выравнивание контента в ячейке таблицы - выравнивание inline/inline-block друг относительно друга в строке
Видишь, текст все равно по центру вертикально выровнен.
Также, не применяй стили к ul. Ведь в тексте на главной тоже может встретиться список и ты своими стилями его сломаешь. Сделай класс и применяй стили к нему.
> И зачем тут использовать свойство clear? Я в этой задаче не нашел ему применения. Не знаю, если он не нужен то не надо конечно. Может там имелось в виду что надо просто выучить это свойство?
В апаче есть mod_rewrite который позволяет определить какой скрипт должен вызываться, но используя нестандартную конфигурацию ты рискуешь что что-то не заработает.
mod_rewrite это не редирект. Он задает правила например что при обращении по адресу /x/ надо вызывать скрипт y.php причем там можно использовать регулярные выражения.
ОП, очень нуб здесь. Решаю задачу про исправление пробелов и заглавных букв. Вроде работает. http://ideone.com/u1v1Lb Но есть вопрос, внутри функции fixText я хотел запихнуть регулярные выражения как $key и то, на что надо заменять результат поиска как $value в массив и пройти foreach, но чего-то не то оно делает, первый проход норм, а второй исправляет уже исправленное, причем непонятно по какой логике это делает, а вот так по отдельности все ок. Чому так?
PHP-кун, можешь посоветовать что-нибудь по юзабилити и дизайну для веб-приложений?
Возникла задача спроектировать с нуля достаточно объемное и как можно более удобное веб-приложение энтерпрайзного толка. Я понял, что, если с ui паттернами для десктопного приложения такого плана я знаком, то вот с тем, как это делают в вебе, я не знаком совсем.
Есть ли какие-то хорошие гайды, книги или примеры, которые можно будет взять за основу?
>error_reporting ( - 1 ); Молодец, серьезно. И не убирай это в продакшене, как советуют всякие.
В строке 15 ты, по факту, уже нашел первые буквы всех предложений во второй подмаске, ([a-z|а-я]). Кстати, символ | тебе тут не нужен, символьные классы в регулярках группируются без него. Давай не будем делать двойную работу (строки 16-24).
Ты давай либо код, либо задачу. Описывать неработающий код словами, да еще без уточнения, что конкретно ты делаешь (например, заменяешь кавычки, угадал?) - самая плохая постановка вопроса. Никто тебе так не поможет.
> И не убирай это в продакшене, как советуют всякие. Вообще-то error_reporting отвечает за игнорирование некоторых видов ошибок (странная настройка: кто может захотеть игнорировать ошибки?). За вывод на экран отвечает другая настройка, display_errors.
Подскажите мне вот следующую вещь: Вот в скрипте у меня есть условие, при прохождении которого начинается работа с переменными сесии. Собственно у меня вопрос, session_start лучше писать непосредственно перед работой с этими переменными? Или лучше писать в начале скрипта? А если в начале скрипта, то нормально ли написать эту строчку в отдельном файле с другими штуками, который инклудится в начале каждого файла?
>>440718 В общем уточню. Речь о том, что бы всю подобную копипасту разбросанную по файлам, написать в одном файле и инклудить его в начале каждого файла со скриптом. http://ideone.com/P6OkF4 Сначала у меня был только файл config.php, в котором был массив для коннекта к базе и ничего больше, и я инклудил его непосредственно перед работой с базой. Но потом 1 товарищ указал мне на то, что у меня error_reporting в начале каждого файла написано, а так же session_start разбросаны по скрипту, и посоветовал всё такое скинуть в отдельный файл и его инклудить.
Единственное что меня смущает, так это то, что когда я читал инфу про сессии, там вроде бы не рекомендовалось писать session_start в начале скрипта, а делать это только когда начинается работа с сессией непосредственно. В общем жду пояснений от гуру.
>>439989 >Это ненадежно. Злоумышленник может подставить себе любой id (куки ведь хранятся в браузере) и редактировать чужую страницу. Чтобы он этого не мог сделать, надо вместо предсказуемого id использовать сложный случайный код, который генерируется при регистрации (у каждого студента он свой и злоумышленник его не знает). 32 или больше символа из диапазона [a-z0-9] вполне подойдут.
Мне нужно так же хранить этот код в базе и возвращать нужного студента проверяя этот код?
>Не вижу где в репозитории конфигурация для mongoDB. Например, где определяются индексы? Где создаются коллекции?
Эм, индексы я вообще не создавал, отложил это на попозже, и так и не сделал. А коллецкии разве надо руками создавать? Мне показалось они сами создаются, если их не существует, но ты в неё пишешь. Кстати где в коде это делать? Что, каждый раз при запуске PHP скрипта, проверять, есть ли нужные коллекции\индексы? Это же разовая процедура должна быть
>озможно, ты копировал схему котору. использует Silex Ага, хотел чтоб было также как в веб-части. >Гораздо лучше если бы и websocket сервер и приложение разделяли общий контейнер Тогда в серверной части в контейнере лежало бы куча всякого, ему вообще ненужного
>Обычно в мапперах реализуют подход IdentityMap >Зачем вообще нужны Handler-классы? Вот handler классы я изначально как раз и делал, для того, чтоб они кешировали обьекты RoomUser и RoomEvent, чтоб не было повторных обращений к БД, когда мы теже самые обьекты пытаемся получить. Но, по ходу дела понял, что это очень плохая идея, т.к. у нас есть два "писателя" в БД, server и webapp, Соответственно, Webapp что то поменял в коллекции RoomUser - как RoomUserHandler в Server части об этом узнает? В общем фигня вышла, я этот код выкинул, а ненужные промежуточные классы остались.
>Насчет проблемы с заходом пользователя с нескольких устройств или вкладок, тебе надо вместо пользователя ввести понятие «соединения» Да, я пришел точно к такому же выводу: https://github.com/d-beekeeper/ratchat/issues/1 Только жаль что поздно до этого додумался. Надо приличный кусок кода под это дело теперь переделывать. Сначала думал, что можно будет обойтись "малой кровью" - простым счетчиком заходов юзера в отдельную комнату. Типа юзер зашел - увеличиваем. Вышел - уменьшаем. Эвент выхода генерим только когда счетчик==0. Но Heartbeater с таким решением не совместим в принципе. А соединения так просто не добавить, ибо там у каждого должен быть уникальный ID и т.д. Кроме того, в серверно части эти самые соединения есть - на уровне Ratchet. И как раз именно с уникальными ID. А значит webapp-соединение должно быть совместимо в server-соединением - в общем тут надо подумать, как грамотно сделать. Возможно вообще реализовать аналог WAMP, но с транспортом в виде периодических ajax запросов вместо WebSockets.
> protected function convertId($_id) >Это очень странная функция >Это какой-то кривой костыль, явно. Йап, ты как всегда прав. Надо переделать. А: > if (!\MongoId::isValid($_id)) { > $_id = substr(md5($_id),0,24); это из за того, что если мы сделаем new MongoId('some_custom_string') - будет ошибка. Почему то в PHP Mongo-клиенте, если мы создаем MongoId - ему обязательно нужно передавать hex строку (типа fa3fcc2e...) длиной ровно 24 символа. При том, что сам mongo server прекрасно хавает любые произвольные строки в качестве _id. ХЗ почему так.
>Не очень понятно, почему ты прововеряешь равенство поля null через isset, и не очень понятно почему такие поля не попадают в массив. Ну... я подумал что не имеет смысла сохранять в БД поля, которые null... зачем они там? Только для однообразности?
>>440745 Баланс отрицательный быть не должен. Смотри что получается, когда вместо 40 тысяч вписать кредит 5100 http://ideone.com/alQWUN Сумма меняется в разные стороны, сначала было 10к, а стало 7. Нужно проверять не отрицательную сумму, а меньше ли оставшийся долг наших ежемесячных выплат, чтобы не переплачивать и не загонять баланс ниже нуля.
>Что за странный <a> без href? >Это ты скопировал или у тебя правда адаптивный дизайн?
Эм, ну это все копипаста из заготовленных шаблонов на на странице мануала по Bootstrap
>Мне кажется, если вебсокет отвалился, но соединение возможно, лучше повторно соединяться через WS. Это все вшито в AutobahnJs client - он там сам пытается реконнектить вебсокет. см. ниже: { skipSubprotocolCheck:true, maxRetries: 5, retryDelay: 1000 } 5 попыток реконнета через 1000 мс. И только если не удалось - тогда вызвается onDisconnectCallback
>У тебя на клиенте есть какое-то ограничение на число отображаемых сообщений? Неа, учту.
> alert('Ошибка: ' + value); Да я это прекрасно понимаю, просто лень уже был писать модально-всплывающую фигню для отображения ошибок. Потом когда нить доделаю.
> if ($(this).queue().length == 0) >Это вообще где-то в документации описано? Нуу... там написано что очередь можно повесить на любой обьект. Ну я и повесил... надо же было её куда то приткнуть, мне показалось что так - норм вариант.
>Кстати, как у тебя с очисткой старых сообщений? Они когда-нибудь очищаются? Неа. По хорошему надо отдельную коллекцию - архив эвентов сделать, и туда переносить из основной коллекции events старые.
>Ну и вторая вещь, которой можно было бы заняться, это покрыть приложение тестами. Да, я это читал и писал с рассчетом на то, чтоб потом тесты можно было прикрутить относительно легко.
Займусь всем этим чуть позже. Щас пока не до чата. Во первых заколебался я его делать - это было совсем не просто без соотв. опыта, а во вторых щас немного не до этого: работаю джуном и ищу работу на позицию мидла, так что можешь скрестить за меня пальцы - твои уроки не проходят даром.
>>440747 > проверять не отрицательную сумму, а меньше ли оставшийся долг наших ежемесячных выплат Сделать проверку на 5 тысяч? Но получается еще большая хрень. В последний месяц остается 4100 долга, можно было бы выплатить одним разом, но банк начисляет комиссию в 1000 до твоей выплаты. В итоге получается долга 5100 и за последний месяц его выплатить не удается. Криво объясняю, но все же. Вот как получается, если сделать по твоему совету.
>>440752 >month++ >$paymentTotal = $paymentTotal + $creditBalance; Костыль какой-то, лучше сделать, чтобы выплачивалось все в следующем цикле, а не в текущем. А так у тебя к текущей выплате прибавляется оставшийся баланс без процентов и без сервис пеймента. Там должна быть сумма больше чем 59 тысяч. В итоге у тебя должна получится 61 тысяча с чем-то. Но с формулой $creditBalance = ( $creditBalance * $percent ) + $servicePayment - $monthlyPayment; у тебя такой ответ не получится хотя тут я немного приврал, можно получить, но тебе я советую её переделать потому-что она сразу отнимает месячную выплату от баланса, не проверив при этом оставшуюся сумму кредита. Наверное сумбурно объяснил, ОП придет и расскажет подробнее.
>>440752 ну так подразумевается, что банк начисляет тебе в начале месяца, а платишь ты например только в конце. Ты можешь сделать и наоборот, если хочешь. Ты тут просто моделируешь реальную жизнь, ты можешь даже рандомить себе карманные деньги, которые ты сможешь выплачивать, или дату их поступления. Типа выплачивать до или после начисления.
Сначала определи сам как все происходит ирл, а потом напрограммируй это.
>>440693 >Строки с 15 по 24 можно заменить так Спасибо, учту. >Ты давай либо код, либо задачу. http://ideone.com/ldeKxk Вот такую конструкцию я имел в виду. Неуверен в ее необходимости в данной задаче, но захотелось почему-то применить foreach.
>440754 >костыль Именно! Я программирую первый день, и уже занимаюсь придумыванием каких-то костылей. Как поизящнее решить эту задачу? Допиши её как будет правильнее, уже весь мозг себе сломал, ничего кроме костылей в голову не идёт.
>>440817 Я бы не сказал, что ты её решил, ведь результат у тебя не тот, что должен быть, сумма другая выходит и месяцы тоже. Но это нормально, эту задачу почти никто за 1 день не решает. ОП придет и поможет тебе разобраться.
>>440790 Я не слово не говорил тебе про костыли, но
вот этот:
if ($creditBalance < 5000) { $paymentTotal = $paymentTotal + $creditBalance; $creditBalance = 0; $month ++; echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n"; echo "С меня хватит!\n"; break; }
действительно выглядит странным. Попробуй переписать его, что бы все шло своим чередом. Но когда у тебя долг становится меньше чем твой ежемесячный платеж, то и выплата в этом месяце идет равная этому долгу.
Еще вот тут: for ($month = 1; $month <= 20; $month ++) {
можешь задать условие, что у тебя будет цикл идти не пока пройдет 20 месяцев, а пока не кончится долг, это тоже избавит тебя от костылей.
>>440826 Ключевой момент, что ты сразу отнимаешь месячную выплату вот здесь $creditBalance = ( $creditBalance * $percent ) + $servicePayment - $monthlyPayment; А потом у тебя уже идет проверка на условие. То есть допустим у тебя долг 4 тысячи. От них нам нужно посчитать проценты и добавить к сумме + сервис пеймент. Но мы тут же отнимаем от этой суммы 5 тысяч и долг уходит в минус. По логике мы сначала вычисляем сумму кредита, потом проверяем не меньше ли она ежемесячной выплаты, а уж затем отнимаем от кредита какую-то сумму в зависимости от проверки.
Господа, доброго времени суток. Пришёл я к вам с такой проблемой. Учусь я значится на прикладного информатика в менеджмент ( на кусок говна вообщем ). И вот уже на пороге 5-й курс и диплом. И тема моего диплома такова - Интерактивный WEB интерфейс. Отображает информацию о проходах сотрудника, позволяет сотруднику и его начальнику интерактивно работать с отчетом (сотрудник помечает причины отклонений от режима, начальник подтверждает или отклоняет мнение сотрудника, кадры получают отчет уже после обработки начальником и подчиненными). Требует знания MySQL+PHP, основы HTML. Тема: разработка интерактивного WEB приложения для обработки инцидентов, выявленных системой контроля рабочего времени. Предзащита значится у меня в мае и вот такой вопрос. Реально если ты полной ноль в php и mysql сделать то, что описано выше?
Вот >>440829 он тебе тоже всё верно сказал, что у тебя математическая модель не отражает реальности. Не нужно пытаться все пихать в одну кучу с вычислениями. Может между этими вычислениями нужна проверка, которая повлияет на второе действие. Поэтому лучше разбивать всё на действия в таком случае, и каждое действие писать в отдельной строчке. Что бы логика и смысл был во всем.
>>440838 Ну по секрету скажу что php было пол года и у половины группы, в которую я не входил и было это 2 года назад. А после 2 года мы познавали маркетинг, менеджмент и как надо правильно расставлять товары на полки магазинов.
>>440835 Ну ты паскаль то знаешь хотя бы, информатик? Цикл запустить умеешь? Я вот дрочу уже год пхп и по твоему описанию чет не могу понять как бы я делал эту программу учета.
>>440840 Какая-то нифига не прикладная у вас информатика, если программированию из 5 лет учат всего пол-года, да и еще и у одной половины группы. Что же учила вторая? Какой-то язык ты должен ведь знать?
>>440842 Да типичная история. У меня такая же хрень была в вузе, но я еще и заочник был. По факту вся группа попиздила в интернете курсовых и даже защитить не могла, не зная где тут цикл, а где условия. Я со школьными знаиями по паскалю на фоне этого цирка выглядил как античный бог на сверкающем пегасе среди чумного города.
>>438085 Господа, что можете подсказать по поводу CORS? Проблема: Есть api ems почтыроссии, результат хочу тянуть аяксом, но в итоге получаю хуй в виде "Политика одного источника запрещает чтение удаленного ресурса на блаблабла". Конечно же, в htaccess прописал Access-Control-Allow-Origin "*", но это не помогло. МОжет ли быть, что я ещё где-то лоханулся?
Задача: выкинуть некоторые символы из строки перед отправкой в БД. Кроме как регэкспами не увидел способов это сделать. Сейчас пытаюсь отфильтровать всё кроме русских букв.
Использую /[^А-Я]/ / начало выражения [^ любые символы в любом месте кроме А-Я русских букв (не чувствительно к регистру) ]/ конец выражения
При таком раскладе всё работает, кроме букв Ё и ё. Но при попытке добавить букву Ё всё летит к чертям и многие русские буквы заменяются квадратиками. Подробности и код тут https://ideone.com/Gs7hPB
Может быть я неправильно формулирую? Мне нужно чтобы в конце концов получилось: не русские буквы и не буква ё
>>440876 По ссылке переходишь на какой-то конкретный URL(кстати по какому ты адресу переходишь). И по этому самому URL определяешь какую функцию запускать, какие шаблоны выводить.
Смотри вот у меня test.ru/upload там запускается index.php
Когда я перехожу например на test.ru/upload/file через <a> у меня 404 Обработчик $app->post('/:file', function ($id) use ($mapper){ $app->get('/:file', function ($id) use ($mapper){ Не запускается
>>438085 Похаписты, халп! Репощу из соседнего джава-треда. Помогите гуманитариедауну решить простенький тест по регулярным выражениям. С меня нихуя. 1. Придумайте произвольное регулярное выражение, которому соответствует ровно 231 различная строка. Поясните свой ответ. 2. Придумайте строку, которая найдётся и по запросу [клмн](прст)?, и по запросу (клмн)?. 3. Придумайте регулярное выражение, которое будет находить арифметические выражения типа 6 * 4 = 24, 2+7=9, 141-15 = 126, 900 / 2=450 sic! пробелы так и должны быть 4. Сколько в файле alice.txt слов, которые начинаются и заканчиваются на одну и ту же букву (напр., alpha, deed, stops)? Опишите алгоритм поиска. 5. Сколько в файле alice.txt слов, которые начинаются на глухой согласный звук? Опишите алгоритм поиска.
Анончики, в регулярках иногда встречаются конструкции вида ${1}, что это такое? Я даже не знаю где о них почитать, можете поделиться ссылкой, как они называются? В документации по функциям preg_match_all и т.д. ничего не нашёл
>>440622 Если используешь запрос к базе данных в функции, без globаl переменной не обойтись же? Не в каждой же функции писать подключение к базе данных.
Ставить sidebar на li было необязательно. Гораздо лучше поставить только на ul и исплоьзовать
.sidebar { ... } .sidebar > li { ... }
Так и писать меньше, и путаницы меньше.
id в стилях лучше не использовать, лучше использовать классы потому что классы в отличие от id могут повторяться и можно поставить несколько классов на элемент. То есть они удобнее.
> ul.sidebar{ > height:900px; Это неправильно. Почему именно 900px? Откуда взялась эта цифра? Она добавляет большой пустой оступ снизу: http://jsfiddle.net/8xypLhot/12/
> Но есть вопрос, внутри функции fixText я хотел запихнуть регулярные выражения как $key и то, на что надо заменять результат поиска как $value в массив и пройти foreach, но чего-то не то оно делает, первый проход норм, а второй исправляет уже исправленное, причем непонятно по какой логике это делает, а вот так по отдельности все ок Без примера кода трудно понять в чем дело. Покажи код.
> [ ]?+ А зачем тут ?+ Ты не опечатался? Добавление знака + к квантификатору это штука для оптимизации (описано тут в конце http://php.net/manual/ru/regexp.reference.repetition.php ). Ты ведь явно хотел что-то другое написать.
> [a-z|а-я] В квадратных скобках | не имеет специального значения и обозначает символ вертикальной черты. Также, буква ё в регулярках не входит в диапазон а-я (так вышло) и ее надо писать отдельно.
Надо писать [a-zа-яё]
> if (($arr [$i] == "." | $arr [$i] == "!" | Чтобы написать логическое «или» надо писать ||. Знак | обозначает двоичное побитовое ИЛИ и это совсем другая операция. Мануал:
> for($i = 0; $i < (count ( $arr ) - 2); $i ++) {//первые символы оставшихся предложений в заглавную букву Работать со строкой по символам довольно неудобно. Как посоветовал другой анон, через preg_replace_callback полуается гораздо проще, если ты знаешь эту функцию. Если нет то можно оставить цикл.
> задачу. Вот > Задание: дан неграмотно написанный текст, состоящий из нескольких предложений на русском языке. Ошибки заключаются в неправильной расстановке пробелов и отсутсвии заглавных букв. Исправить текст так, чтобы все предложения в нем начинались с большой буквы, а после знаков запятая, точка, восклицательный и вопросительный знак стоял ровно один пробел (а перед ними — ни одного).
Глобальные переменные зло. Так как функция которая зависит только от переданных аругментов понятнее и предсказуемее.
Ты наверно хочешь спросить: неужели мне теперь надо в каждую функцию работы с БД передавать $con? Я отвечу: в случае исплоьзования функций, придется (либо придется пользоваться плохими глобальными переменными), в случае использования ООП такой проблемы нет. Хороший повод перейти на ООП, кстати.
Вообще хорошие книги по юзабилити это Алан Купер ( «Об интерфейсе» — большая) и «Психбольница в руках пациентов». А также Раскин «Интерфейс» (кстати, у меня они все есть в бумажной версии, а вот книг по программированию ни одной нет).
Но они объясняют общие принципы, вроде локуса внимания (пользователь смотрит в одну точку в один момент времени), подсчета числа действий и много других интересных вещей. Это скорее теория которая помогает понимать, почему делают так или иначе (после ее прочтения ты скорее всего сможешь смотреть на интерфейсы другими глазами). Также, там описывается подход к проектирование через определение задач и поведения пользователей. Книги реально полезные, если ты их не читал, советую прочесть.
Книги не про веб-приложения, а про юзабилити и и интерфейсы в общем. Но для конечного пользователя нет особой разницы между веб- и десктопным приложением.
С технической точки зрения различия есть, и довольно большие.
> то вот с тем, как это делают в вебе, я не знаком совсем. Хорошо бы посмотреть какие-то существующие интерфейсы. Google Drive может быть?
Если ты про набор виджетов, то в вебе нет какого-то стандартизованного набора (как например в WinAPI или Qt). Есть встроенные в браузер контролы, есть сторонние библиотеки виджетов вроде jQUery UI, Kendo UI, есть библиотеки реализующие один контрол вроде Chosen.
Также в плане реализации ты можешь делать клиент тоньше или толще, перенося меньше или больше логики в браузер с сервера. Тут тоже есть плюсы и минусы.
Проектировать интерфейс стоит начать с составления сценариев, какие задачи будут решать пользователи, и как им решить их быстрее и исходя из этого решать какие будут экраны, какие на них элементы с какими возможностями.
Получился довольно абстрактный совет, так что если есть уточняющие вопросы, задавай.
> Собственно у меня вопрос, session_start лучше писать непосредственно перед работой с этими переменными? Пока ты не начнешь сессию, массив SESSION будет пустой.
Также, session_start должен стоять до начала вывода, так как он ставит куки, а куки это заголвоки, а заголовки должны идти до тела HTTP ответа.
> А если в начале скрипта, то нормально ли написать эту строчку в отдельном файле с другими штуками, который инклудится в начале каждого файла? Нормально. Кстати, такой файл инициализации обычно называют bootstrap.php
> Речь о том, что бы всю подобную копипасту разбросанную по файлам, написать в одном файле и инклудить его в начале каждого файла со скриптом. так и надо сделать
> там вроде бы не рекомендовалось писать session_start в начале скрипта, а делать это только когда начинается работа с сессией непосредственно Это экономия на спичках, если у тебя не миллионы посещений то это ничего не меняет.
> Мне нужно так же хранить этот код в базе и возвращать нужного студента проверяя этот код? да, код должен храниться в базе чтобы можно было его проверить и определить по нему о каком студенте речь.
По идее можно сделать и без сохранения в базу. Например, шифровать id, а при редактировании расшифровывать, но это намного сложнее получается. Зато без обращения к базе можно проверить правильность кода.
Прмитивный вариант шифрования это добавлять к id подпсиь вида
md5("длинный секретный пароль" . $id)
Но тут есть недостаток что при похищении одного пароля злоумышленник получает доступ ко всем аккаунтам, так как пароль один для всех.
> Эм, индексы я вообще не создавал, отложил это на попозже, и так и не сделал Тормозить будет, без индексов любой поиск сводится к полному перебору коллекции, если в ней хотя бы сотня тысяч элементов, будет тяжело. Даже если меньше, все равно будет не быстро работать. Ну и неправильно говорить что ты знаешь монгу если ты не умеешь пользоваться индексами, по моему.
>Мне показалось они сами создаются, если их не существует, но ты в неё пишешь. Если так то ок.
> Кстати где в коде это делать? Что, каждый раз при запуске PHP скрипта, проверять, есть ли нужные коллекции\индексы? Это же разовая процедура должна быть
Ничего не ищется. Печалька. Значит, надо писать велосипед. Видимо надо сделать php-скрипт который запускается из командной строки и делает вызовы ensureIndex в нужном количестве.
В любом случае, индексы должны быть в репозитории, а не где-то вне его.
> Это же разовая процедура должна быть Проект развивается, индексы добавляются и удаляются. Никак не разовая.
> Тогда в серверной части в контейнере лежало бы куча всякого, ему вообще ненужного пусть лежит, какая разница. Это же 2 части одного приложения, удобно когда любой сервис доступен из любой части приложения. И дублирование кода — нехорошо.
> Вот handler классы я изначально как раз и делал, для того, чтоб они кешировали обьекты RoomUser и RoomEvent, чтоб не было повторных обращений к БД Это (identity map) делается не столько для кеширования, сколько для поддержания абстракции. ORM/ODM создают абстракцию, как будто бы никакой базы нет и все объекты хранятся у нас в памяти (в абстрактном репозитории). Такая абстракция позволяет писать код проще, так как мы не должны вообще думать о хранилище и его особенностях. Ну и когда один пользователь соответствует ровно одному (а не нескольким объектам) тоже проще получается.
Если ты будешь изучать Doctrine 2 (она входит в симфони), то со всем этим столкнешься.
> у нас есть два "писателя" в БД, server и webapp, Соответственно, Webapp что то поменял в коллекции RoomUser - как RoomUserHandler в Server части об этом узнает? Как решение, можно после обработки каждого websocket-события очищать identity map.
> Сначала думал, что можно будет обойтись "малой кровью" - простым счетчиком заходов юзера в отдельную комнату. Типа юзер зашел - увеличиваем. ой-ой, это же очень тяжело отлаживать, и потерять единичку тоже легко.
> А значит webapp-соединение должно быть совместимо в server-соединением - в общем тут надо подумать, как грамотно сделать. При загрузке страницы сервер генерирует ей id сеанса. Вторая вкладка в браузере — второй id. Она передает его во всех ajax запросах. Его можно и в heartbeater исплоьзовать кстати. И в вебсокете тоже.
Эта проблема кстати есть и в мессенджерах: при заходе с нескольких устройств куда слать сообщения? В джаббере есть приоритеты, где-то шлют на последнее подключенное/активное устройство, где-то на все сразу.
> Возможно вообще реализовать аналог WAMP Это усложнение наверно. Мне кажется хватит id сеанса.
> Каждый MongoId состоит из 12 байт (преобразующихся в 24 шестнадцатеричных символа).
А то что ты делаешь какие-то костыли. Заметь что тут http://php.net/manual/ru/mongoid.construct.php видно что при создании объекта он сам генерирует новый id. У меня есть подозрения что класс MongoId это класс для генерации или хранения сгенерированных id и если он тебе не нравится то можно просто им не пользоваться.
Если ты не хочешь использовать 12 байтовый формат то наверно можно просто не исплоьзовать MongoId, а передавать свой id строкой (или нельзя? наверняка можно).
>>440835 >Отображает информацию о проходах сотрудника Если имеется в виду какой-то турникет, к которому сотрудник прикладывает магнитную карту и фиксируются его проходы, это очень проблематично. Я неправильно понял?
Ответ должен быть около 61270. Там в учебнике специально дан код с ошибкой, и надо ее исправить (или написать с нуля без ошибки).
> if ($creditBalance < 1000) { Это неуниверсальное решение, так как ты его сделал под частный случай. Почему именно 1000? Если мы поменяем сумму или условия кредита, оно перестанет работать.
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга - если остаток маленький, выплачиваем сколько осталось и уходим - иначе платим 5000
Я кстати придумал еще кое-что, что можно улучшить. У тебя сейчас приложение не масштабируется. твой демон однопоточный и он не может задействовать больше 1 ядра процессора. А ведь на серверах обычно стоят 16-64 ядерные системы , да и самих серверов может быть много. Но твой демон можно запустить только в 1 экземпляре и рано или поздно он упррется в нехватку CPU. Соответственно, задачей могло бы было сделать масштабируемый демон, который можно запускать в N экхемплярах, и клиенты бы случайно или как-то еще выбирали один из них.
Это если тебе интересна тема высоких нагрузок, масштабирование (но прежде чем за это браться надо разобраться с индексами и тестами производетельности).
> ну это все копипаста из заготовленных шаблонов Надо хотя бы понимать что копипастишь
> Нуу... там написано что очередь можно повесить на любой обьект. Тут явно лучше сделать очередь отдельным свойством так как неизвестно какие она свойства добавляет в объект, да и вообще бардак какой-то получается, объект одновременно и объект и очередь.
> а во вторых щас немного не до этого: работаю джуном и ищу работу на позицию мидла, так что можешь скрестить за меня пальцы - твои уроки не проходят даром. Ну ясно. Удачи тогда. Это кстати хороший пример другими анонам был бы.
> 6 задача Заменчания тут есть: >>440961 так как 900px ты убрал, то в общем задача решена.
> 7 зачада
> Кстати, в жсфиддле пришлось высоту другую указывать, в хроме у меня почему-то когда 30 пикселей указываешь, то высота блока такой и будет. А ты читал примеания к задаче? По историческим приинам часть элементов форм использует box-sizing: border-box, а часть content-box. Причем исплоьзует уже лет 15 или больше, когда этого свойства еще в помине не было, а разница уже была. Я помню как лет 5 назад сам делал исследование в разных браузерах и обнаружил этот эффект (в интернете информации особо не было, пришлось опытным путем проверять. В стандарте куда я заглянул в первую очередь написано что на элементы форм правила CSS не распространяются).
Потому ты должен либо учитывать и ставить разную высоту либо использовать box-sizing (c префиксами чтобы охватить больше браузеров).
Почему у тебя в Хроме этого эффекта нет — не знаю. Может просто не так заметна разница?
В фаерфоксе элементы не выравниваются вертикально, один выше другого на пару пикселей. vertical-align исправляет проблему.
Вообще, элементы форм это конечно боль. Вот еще в ФФ например надпись на кнопке находится не по центру, а ниже. Паддинг может быть виноват.
Покажи код, я напишу что не так и что исправить. задачи ведь ты решаешь для себя, чтобы лучше научиться программировать, а с готовыми решениями твой мозг ничему не научится.
Есть еще книги по всему сразу вроде Р. Никсон "Создаем динамические веб-сайты с помощью PHP, MySQL, JavaScript и CSS". Книга в общем весьма сомнительная так как примеры кода плохие, много устаревшией информации, код с ошибками и уязвимостяим. Но если ты не собираешься быть программистом, а просто надо сделать задание и забыть и никогда в жизни ничего не писать на php то может тебе подойдет.
Но вообще, я не уверен что ты сделаешь. Ты готов каждый день по несколько часов все это учить? Ты скорее всего забьешь и бросишь на полпути.
> Конечно же, в htaccess прописал Access-Control-Allow-Origin Прописывать должен не ты, а почта России. Если не прописывают значит не одобряют такой вид запросов. И если это API то наверно оно рассчитано на вызовы с сервера?
Ну и вообще кстати, писать такие вещи как ты прописал довольно опасно. Это может привести к уязвимостям вроде XSRF на твоем сайте.
Подключать Слим конечно лучше бы через композер было. В таком случае в репозитории только твой код и ничего лишнего. И обновлять проще.
То, что у тебя конечно не подойдет. Я вообще не вижу в index.php где Слим используется. Да он и не исплоьзуется вообще.
Идея Slim в том что у тебя один файл index.php и роутингом (определением что надо делать в зависимости от URL и метода) занимается фреймворк. Я писал выше как должен выглядеть код: >>439909 надо сделать примерно так, без файлов list.php, file.php.
Ну и добавить .htaccess который перенаправляет все запросы к несуществующим файлам на index.php
То есть что я хочу сказать? Фреймворк тем и отличается от библиотеки что это основа (каркас) приложения. Он задает структуру приложения. если в Слиме принято писать роуты в index.php значит надо их там и описывать.
Так что не сдавайся, давай разберем что у тебя не работает и в итоге все таки добьемся чтобы оно заработало.
Насчет композера, это пока можно оставить как есть, но позже надо переделать на исплоьзование композера. Найди время для этого. Если что-то работать не будет, пиши, я посмотрю. Если ты что-то не понимаешь, напиши что именно.
Да и там весь мануал читать не требуется, только то что ты исплоьзуешь.
Еще, я там написал много замечаний. Их надо либо все исправить либо как-то отреагировать, например написать что «это непонятно» или «это и так нормально сделано».
> Когда я перехожу например на > test.ru/upload/file через <a> > у меня 404 Ты файл .htaccess добавил? Покажи-ка его. По умолчанию Апач пытается найти папку upload/file и с помощью htaccess мы заставляем его вместо этого вызвать index.php где запустится Слим и вызовет нашу функцию.
> И ещё апп-рендер можно только пхп-файл предавать? Можно не php но он просто выведется как есть. расширение и имя файла не важны, важно что в нем.
Я бы тебе советовал в этой задаче использовать не шаблоны на php, а освоить шаблонизатор twig. Он удобный и современный (используется в symfony 2, вдохновлен питоновским jinja) и полезно его знать.
> ужно ли в этой задаче обходится без дубликатов сохранённых картинок? Уменьшенные картинки разумеется можно создавать и сохранять. Только имя лучше дать понятное например
thumb-(имяфайла)
или
thumbs/filename.jpg
А ты все файлы в одну папку кладешь? Что если загрузить 2 файла с одинаковым именем но разным содержимым?
По коду, быстро проглядел:
> src="uppy/container/_{{ file.key }} Ты в шаблон помещаешь логику определения имени превьюшки. Неправильно. Должна быть функция или метод.
> {% if isImage == true %} Это удобно сделать методом у File наверно? Мы же ООП используем. {% if file.isImage() ...
> {{ file.size }} байт Вывел бы лучше в человекопонятном виде вроде 16,5 Мб
> href="{{ hostName }}/download/{{ file.key }}" Тут наверно лучше сделать где-то еще функцию или метод для получения ссылки на скачивание.
> <a class="brand" href='{{ hostName }}/main'>UPPY</a> Обычно эта ссылка ведет на главную. Непонятно почему она разная в разных шаблонах.
В форме поиска надо добавить кнопку. Я не уверен что без кнопки она вообще будет отправляться.
> https://github.com/tokotun/uppy/blob/master/uppy/app/File.php#L22 Вот это точно не там должно быть. У нас File представляет собой информацию о файле и он не должен выводить какие-то заголовки, что-то там отдавать в браузер, мне кажется. Для этого должен быть внешний метод или функция, а у тебя класс File и швец, и жнец, и на дуде игрец.
> header('Content-Disposition: attachment; filename=' . $this->name); для опции filename разрешено исплоьзовать только латиннциу (ASCII если точнее). русские буквы разные браузеры понимают поразному. Лучше не используй эту опцию вообще.
> ORDER BY dateLoad DESC Индекс по dateLoad сделал? А то mysql будет в память выкачивать всю таблицу файлов и сортирвоать (ты бы мог сказать что никто тебя этому не учил; что поделать, учись: http://www.mysql.ru/docs/man/ORDER_BY_optimisation.html )
Без индекса на большой таблице файлов разница будет большая, порядка 2 мс против 2 секунд например на таблице с сотней тысяч файлов.
- использование URL для того чтобы представить какой-то ресурс. Ну например URL /users/10 может соответсвовать пользователю с id = 10 и разные методы вроде GET/POST/PATCH/PUT/DELETE исплоьзуются для операций над этим пользователем
Если ты не понимаешь что такое URL, метод то тебе стоит сначала изучить HTTP, так как REST обычно реализуется на нем.
- остутсвие состояния на сервере. Это значит что например для выполнения какого-то действия надо сделать один запрос, а не несколько (подготовить данные для обновления, обновить данные). Соответственно, нежелательно использовать штуки вроде сессий, кук в API.
Отстутсиве состояние упрощает масштабирование сервиса на несколько узлов, перезапуск и т.д.
А где схема таблицы (команда CREATE TABLE в которой описаны типы полей)? Может у тебя типы полей не те?
Ну и может, ты просто 2 раза вызываешь функцию вставки.
Код кстати плохой. Там куча сомнительных мест. И использование статических методов это не ООП, а процедурный код. И класс у тебя занимается и работой с БД, и очисткой POST параметров.
> return $fileMapper = new \Uppy\FileMapper($pdo); Переменная не нужна тут
> 'cache' => dirname(__FILE__) . '/vendor/twig/cache', По моему не очень удачный выбор так как vendor это папка для сторонних библиотек, а не временнных файлов. Лучше сделать папку типа tmp, cache и подобную. И закрыть в нее доступ через htaccess.
> resizeImage($file->key, $app->config('uploadPath')); Это надо делать один раз, а не при каждом просмотре страницы.удобно делать при загрузке или при первом обращении к странице.
> $file->fileForceDownload($app->config('dirHost')); Скачивание лучше бы реализовать без участия php так как Апач отдает файлы горазло быстрее и с меньшим потреблением ресурсов. Но вознимает проблема как указать имя файла? Параметр filename не годится, потому остается только один вариант: имя должно быть в URL в конце, например:
/download/10/file.txt
Второй вопрос как сделать чтобы файл отдавал Апач?
- можно с помощью php только начинать загрузку и передавать ее Апачу с помощью X-Sendfile (нужен модуль mod_sendfie): http://habrahabr.ru/post/151795/
- можно вообще обойтись без php, сделав правило в htaccess что при обращении к URL вида /download/10/... надо отдавать файл с именем files/10.dat
И еще один момент. Когда ты делаешь загрузку файлов всегда есть риск что тебе закачают на сервер:
— php-скрипт — htaccess файл изменяющий настройки Апача с целью выполнить какой-нибудь файл как php
Соответственно злоумышленник получает полный контроль над сервером.
Ты от этого защищен? Ты отключил выполнение php скриптов в папке загрузок? Ты меняешь расширение при сохранении?
Все же в GET параметрах указываются дополнительные какие-то опции, например какие подробности нужны про юзера, а ид юзера должен быть в uRL. Чтобы у каждого юзера был свой URL.
URL не обязан соответсовать файлам один-к-одному. Ты можешь настроить сервер так чтобы при обращении к любому URL вида /user/xxx вызывался один и тот же файл, например user.php.
Для nginx это делается через правило location, для Апаа через mod_rewrite.
Обычно при работе на фреймворке просто пишут правило что любые обращения перенаправлять на index.php, какой бы не был URL.
>>441011 Скажи пожалуйста подробнее про сомнительность кода. Не знал куда засунуть эти методы. Метод очистки $_POST, методы получения/отправки данных в БД, потом ещё методы для Cookies появятся, и что-нибудь ещё с шифрованием данных. Для удобства сделал их принадлежащими классу user, чтобы под ногами не валялись. Методы статические, пока не знаю для чего в этом случае делать конструктор (ведь при переходе на другой php-скрипт состояние класса User будет теряться). Про CREATE TABLE не знаю, подробнее почитаю про SQL, буду разбираться.
>>441007 >Если тебе дать готовый ответ, ты ничего не выучишь. Изучи регулярныйе выражения, задания-то простые. Дружище, я вообще на филологическом, и бог с ним, что не выучу, мне бы только зачет сдать и забыть, как страшный сон. Да я и сам вижу, что простые, в иных условиях задрочил бы теорию и сам сделал, но на мне другие зачеты висят, а время поджимает. Помогите, аноны, вы же сечете, для вас это как алфавит.
статические методы = процедурный код, а не ООП. Со статическими методами ты не можешь создать несколько экземпляров класса с разными настройками, не можешь подсунуть один класс вместо другого, в общем это не код, а процедурная лапша поулчается. Ты не можешь использовать ни одного преимущества ООП.
Ну и дело не только в преимуществах. «Правильный» код быстрее понять, проще исправить и поддерживать. С ним приятнее работать.
> ведь при переходе на другой php-скрипт состояние класса User будет теряться Верно, но это не повод отказываться от ООП.
> Метод очистки $_POST это тоеж в общем неправильный подход. Зачем его очищать? Если пользователь ввел что-то неправильно лучше показать ему форму и предложить исправить ошибки, а не вбивать в базу непонятно что
> Не знал куда засунуть эти методы. Каждый класс должен заниматься своим делом. Класс работы с БД умеет вставлять пользователей в базу, но не знает ничего про POST и очистку данных, класс работы с POST умеет работать с ним, но не умеет с базой, и тд.
> Про CREATE TABLE не знаю, подробнее почитаю про SQL, буду разбираться. Как ты таблицу создал не зная? Как вообще с базой работать не зная SQL? Если через phpmyadmin то там должна быть опция показать схему таблицы или как-то так, или можно дамп сделать и в нем посмотреть.
Вообще, ты сначала должен изучать SQL а потом браться за визуальные инструменты вроде phpmyadmin. Вот тут есть ссылки на неплохие туториалы для начинающих: https://gist.github.com/codedokode/10539213
Еще, настройки работы с БД не должны быть в коде, обычно их выносят в config.php чтобы легко было поменять. Класс работы с БД не должен сам коннектитья к базе а должен получать объект PDO например через конструктор, это гарантирует что его не забудут передать.
unset не нужен, он там ничего не делает. Локальные переменные и так удаляются при выходе из фукнкции.
В общем, хороший класс это как инструмент. тебе надо забить гвоздь ты берешь молоток и забиваешь им гвоздь. Аналогично с ООП, ты хочешь сохранить юзера — ты создаешь объект класса для сохранения и сохраняешь:
$mapper = new UserMapper($pdo); $mapper->save($user);
при этом этот класс занимается только сохранением, не лезет в POST, ничего не очищает и вообще ничего не делает о чем его не просили. Это хороший класс так как ты можешь с его помощью сохранить любого юзера (не обязательно переданного через POST) в любую базу данных.
На филологическом изучают программирование на Яве? ты серьезно? Что за специальность? Тебе не кажется что правильнее пойти в деканат и потребовать отменить этот маразм, ты же не на матфаке?
>>441030 >>441031 Не Ява и не программирование вообще. Исключительно регулярные выражения. Не знаю, наверно для работы с поисковыми системами и машинным переводом. В любом случае информатика была у нас только один семестр и больше не будет, мне бы только экзамен злоебучий сдать.
>>441040 Спасибо, вроде годный мануал. Хоть и времени в обрез, придется, видимо, обмазываться этими вашими регулярными выражениями. Хотя они у меня бубноватые какие-то получаются.
>>440901 Сейчас я тебе помогу. Просто после мануала ты и сам сможешь решить пару заданий оттуда. Я вот не могу в первое въехать. Какое-то условие не очень внятное
>>441042 Так вот и я не особо просекаю. Вообще там было еще два задания, но их я вроде и так сделал, может, и проверите заодно:
1. Какой из этих шаблонов не является правильным регулярным выражением? Выберите верный ответ и поясните его. (А) [фывапр][1-7] (Б) [ПРСТУ]) (В) ([0-36]) (Г) п|р Ответ: Бd'uh
2. В какой строке текста жадный запрос и.и и ленивый запрос и.?и найдут одну и ту же подстроку ненулевой длины? Выберите верный ответ и поясните его. (А) Александр Сергеевич Пушкин (Б) Михаил Юрьевич Лермонтов (В) Анна Андреевна Ахматова (Г) Марина Ивановна Цветаева Ответ: А, подстрока в результате: «ич Пушки». В варианте Б жадный запрос найдет «ихаил Юрьеви», ленивый – «ихаи»; в вариантах В и Г оба запроса найдут пустую строку (так как в В нет букв «и», а в Г вторая «и» в верхнем регистре).
А дальше я уже перестал въезжать. То есть, синтаксис-то этот понимаю, и примерно представляю, как делать, но как доходит до составления выражения, начинаю путаться в квантификаторах и прочей ебалде. В итоге может получиться какая-то хуерга на три строчки, которую можно было бы оптимизировать до 5-10 символов.
>>441054 Спасибо, доброанон! В принципе, у меня что-то похожее получалось, хотя меня пугали длинные формулы. Альзо, насколько я понимаю, alice.txt - англоязычный файл (судя по 4-му заданию), но подправить тут будет не проблема. Кидай Яндекс, дружище, оплачу тебе завтрак.
>>441054 >>441054 Я ошибся Во втором задании ответ: нет такой строки
потому что [клмн](прст)? ищет одну из букв из первых скобок, далее либо всю вторую скобку, либо нихуя. А вот (клмн)? ищет либо клмн целиком, либо нихуя, так что я не знаю какие у них пересечения, скорее всего не существует таких. Но то что я тебе там написал, явно неправильный ответ.
>>441062 Да, у меня тоже такая мысль проскочила, но я как-то пока забил на это задание, с другими разбирался. А вообще да, не будет тут совпадений. Я так понимаю, ответ "пустая строка" будет? Или он и пустую не найдет? Не совсем этот момент понимаю. >>441065 Печально. Все равно спасибо, я хоть как-то продвинулся. Если вдруг озарение насчет остальных заданий придет - точно вознагражу!
>>441067 По первому заданию тебе нужно что-то типа кастрированной регулярки валидации айпишника вхерачить. Но если там ищет 256 различных вариантов, то тут надо сделать поменьше. Например напишем выражение, которое ищет числа от 0 до 230. Получим как раз 231 различных строк.
>>441077 Чем я, по-твоему, занимаюсь до пяти утра? Сорян, что я не задрачивал ЯП и околоЯПную теорию годами, а теперь мне прилетает такая плюха в виде экзамена по регулярам. Теорию задрочил уже вдоль и поперек, готовые выражения могу разбирать, но как до составления собственных выражений доходит, нихуя не получается. Мог бы сам решить, вот уж на харкач бы не обращался.
>>441076 Не сразу дошло, но это же вообще нехуй делать тогда. Я строки в традиционном смысле рассматривал просто, поэтому даже не подумал об этом. Вот потому и нечего гуманитариеблядкам программирование навязывать.
Насчет поиска слов, анон, там есть специальная штука \b (не знаю есть ли она в том диалекте который изучает гуманитарий, но в pcre она есть). Соответственно она обозначает границу слова: http://php.net/manual/ru/regexp.reference.escape.php
\d если его нету в нужном диалекте заменяется на [0-9]
>>441082 Не троль, я же разобрался с этим уже, и тебе спасибо, агрессивный погромист. >>441081 >>441085 Не знаю, не знаю насчет диалектов. У нас же не какой-то определенный ЯП, да и программирования как такового нет, сугубо регулярные выражения, вырванные из контекста. Уместно ли будет использовать выражение, работающее только в определенном диалекте? Да и вообще я глянул, там больше из программирования всяких "флагов", "подмасок", пустые слова для меня. Неужели нет какого-то традиционного способа такую задачу решить? Чтобы выражение в любом языке и диалекте работало.
В регулярных выражениях есть так называемые диалекты. Фактически есть несколько видов синтаксиса. То есть в основном они похожи, но некоторые фичи в некоторых диалектах отстутсвуют или пишутся по другому.
Так как тут php тред то мы используем диалект pcre, а если у тебя другой диалект (наверняка другой) то какие-то вещи может быть надо подправить или заменить.
Но базовые вещи вроде точки, вертикальной черты, плюса, звездочки везде общие.
> там больше из программирования всяких "флагов", "подмасок", пустые слова для меня Подмаски это то что в круглых скобках.
Флаги это особенности pcre — в твоем диалекте их может не быть.
>>441092 Но у меня нет никакого конкретного языка, и вообще программирования нет. Просто тест по регулярным выражениям, блджад. Я не совсем представляю, как это должно выглядеть и под что я должен "изменять". Я думал, они типа общие и одинаковые для всех.
Ну смотри, (клмн)?.* значит, что у тебя в начале строки стоит или не стоит клмн, а потом стоит точка, которая обозначает любой символ кроме переноса строк, и далее звездочка, которая говорит, что этих любых символов может быть от 0 до бесконечности. По факту любая строка подходит под эту регулярку. То есть тебе осталось придумать строку которая подходит под вторую регулярку: [клмн](прст)? а она читается так: одна из букв к л м н обязательно, и возможно сочитание прст стало быть все возможные ответы 1. к 2. кпрст 3. л 4. лпрст 5. м 6. мпрст 7. н 8. нпрст
>>441095 Не было нихуя. Короче, было 6 или 8 занятий, на которые я не ходил, но по рассказам одногруппников он на них ни слова о РВ не говорил, показывал презентации по истории машинного перевода и прочую чушь. Потом дал экзамен (этот тест), сказал, открывайте википедию или что хотите там и делайте задания. Вот как-то так. Сам экзамен я тоже проебал, поэтому теперь тот же тест пишу заочно.
>>441096 Да, звучит логично, спасибо. >>441099 >любой диалект который тебе нравится Хэлоу? Я позавчера узнал, что такое регулярные выражения. Мне никакой диалект не нравится, потому что я ни одного не знаю, мое представление о программировании ограничивается ПРИВЕТ МИР в паскале в 9-м классе. В общем, хуй с ним, с заданием этим, тащемта все остальные практически решены, думаю, на зачет наскребу. Не стоит оно того.
>>441101 под > используй любой диалект который тебе нравится. он имел в виду: Используй то, что мы тебе тут нарешали и не выебывайся. С теми объяснениями которые приложены к ответам я бы защитил эту хуету на 5, инфа 100% Ну и вообще, судя по твоим объяснениям, я тебе рекомендую прост забирать доки с вуза и идти заниматься чем-то более полезным. Нахуя ты там тратишь своё время? Если на платном учишься, то тем более шли нахуй. Ты же понимаешь, что ты как бесполезный долбоеб по факту, если: >Короче, было 6 или 8 занятий, на которые я не ходил... >Сам экзамен я тоже проебал. Ты не знаний не получаешь, не социализацией не занимаешься там. Нормальный человек либо сам бы все решил, либо за счет одногрупников. Вот не в обиду сказано, просто сам такой же хуйней страдал в вузе, и если бы мог вернуть время назад, то дропнул бы всё еще в зародыше, как только начал скатываться. Сейчас вот сижу учусь сам, лол. Вот прост расскажи мне, чем ты занимаешься всё время?
>>441104 >пришел на двач ты >хочешь советов мудрых А я все ждал, когда же начнется разбор меня, моего вуза и моей жизни. Уж волноваться начал, не ошибся ли я бордой. Не беспокойся, дружище, свою жизнь я как-нибудь налажу, спасибо за заботу. Спасибо всем откликнувшимся, спасли брата-анона от возможного отчисления из-за ненужного говнопредмета. Даже агрессивному илиткопогромисту спасибо, что снизошел-таки до моего уровня и даже соизволил пообщаться со мной на понятном мне языке (не программирования). Вы няши.
>>441105 Ну может грубо сказано, но это лишь реакция на твои манеры. Это же все не наши проблемы, что ты проебывал пары и не учился. А когда ты еще и оправдываешь своё незнание материала этим, то выглядишь как полный долбоеб. По факту я просто попросил тебя рассказать о том, чем ты в жизни занимаешься? Сколько времени ты чему уделяешь. Это просто общением называется. К тому же когда тебе уже помогли, ответ на этот вопрос был бы хорошим тоном, вместо шаблонных вскукарекиваний про двач.
>>441111 >не выебывайся >я тебе рекомендую прост забирать доки с вуза >Ты же понимаешь, что ты как бесполезный долбоеб по факту >Это просто общением называется Это называется лезть в чужую жизнь и делать выводы по буквально двум словам (он сказал что проебал 6 занятий информатики, ебать он бесполезный отброс еще и на платном стопроц вообще нахуй тебе образование дропай и иди на заводы будешь полезным я лучше знаю как тебе жить). Ну или у тебя какое-то странное представление об общении. Я пришел за помощью с недопредметом, с этим маленьким шестичасовым прыщом на теле моей любимой специальности, помощь мне оказали, я поблагодарил добрых анонов и изволил откланяться. А ты мне вслед сыплешь какие-то никому не нужны советы, как мне жить и на кого мне учиться, глупый, глупый анон, ну неужели ты правда думаешь, что я не смогу сам свою судьбу устроить?
>>441111 Неужели ты правда думаешь, что я буду сидеть в 6 утра в похапе треде и рассказывать анонимусам историю своей жизни? Ты какой-то странный, суриасли.
>>441117 Пиздец, чет мне тебя даже жалко стало, бедный, зашуганный технарь, который к рандомным анонам на дваче с жизненными советами пристает. Ну может ты тогда свою историю расскажешь?
>>441118 >>441118 Ты же говорил, что тебе как будто больше нечего делать, кроме как тут сидеть в 6 утра. Там либо нечего рассказывать толком, либо дохуя. В итоге что то не нужно, что это. Не стану кукарекать про то, что у меня жизненного опыта больше, но просто я уже закончил учиться 2 года назад, на подобной специальности: Информатика в экономике называлась, и сейчас понимаю, что лучше бы я те 5.5 лет, которые я там потратил, занимался совсем другими вещами. Просто сначала я был мамкиным корзиноидом, который не знал что ему по жизни делать, вот и пошел в вуз. А когда ты курсе на 3 понимаешь, что это тебе и нахуй не нужно, и ничему ты уже не учишься, и не делаешь. А если и хочешь взяться за учебу, то ты охуеть как отстаешь от программы, то с другой стороны как бы жалко дропать, ведь уже столько времени и сил проебано на это. И с каждым семестром эта яма становится все глубже. ДА И МАМКУ НЕ ХОЧЕТСЯ РАССТРАИВАТЬ. В общем так и мучался последние пару лет, занимаясь хуйней полной. А после того как получил диплом, понимаешь что ты по факту у разбитого корыта. Вот и спрашиваю у тебя, не занимаешься ли ты тем же чем и я? Ведь если ты поступил, то нужно либо учиться, либо дропать. Ну или знакомства заводить полезные, которые тебе помогут в жизни. А бухать или ебашить в дотан с одногрупниками днями напролет, можно и без УЧЕБЫ В ВУЗЕ
>>441121 Стереотипы-стереотипчики. Без обид, но я должен это сказать: да пошел ты на хуй со своими выводами, нихуя не знаешь ведь, пидорасина такая. хаха бухать дотан с одногруппничками, хули ты о моей жизни знаешь? >когда ты курсе на 3 понимаешь, что это тебе и нахуй не нужно Да что ты говоришь? Высшее образование не нужно? И ты это только к третьему курсу понял? >учиться в универе >actually ходить на занятия и слушать совковых преподов Ох лол. Универ - последнее место, где тебе могут дать знания. И что ты к информатике приебался? Она была у нас три недели, я вообще в хуй не тарабаню, зачем ее нам поставили. Разумеется, я на нее не ходил, какие знания мне там дадут? Я-то ценю свое время ну да, расписываюсь тут перед рандомным хуем.
>>441123 Бля, да ты же школьник до сих пор. Который себя умнее других считает. Охуеваю с тебя. Встал в агрессивную позу после того как я твою детскую злобную сучью мразотную душенку задел парой нелестных фраз, ты должен был быть готов к этому и срет теперь вместо диалога. Ну как хочешь, можешь дальше выебываться, я не против.
>>441129 Бедный, бедный технарик. Как же хуево вам живется. Ну ты это, шторку иногда открывай, на улицу там выходи, что ли. Попробуй хотя бы с раза в месяц начать. Глядишь, через пару лет реабилитурешься, на людей кидаться перестанешь, в общение научишься. Жаль, жаль, конечно, зверьков.
>>441131 А ты и все продолжаешь срать, причем сагрившись на то, что я якобы сделал выводы по двум словам о твоей жизни, ты делаешь так же выводы о моей. Но ты еще и пытаешься злобно тралить, дешевыми приемами, а я с тобой спокойно ведь разговариваю, иду на диплог, про себя немного рассказал. Тебя правда так ужалило? Или ты просто неудовлетворенность жизненную на меня пытаешься выместить?
>>441132 Джииз, ты и правда животное необучаемое. А говорят, у технарей с логикой все в порядке. Пора сделать то, что собирался еще два часа назад - откланяться, спасибо за помощь, аноны, извините за этого полоумного, поднасрали здесь чуток.
У меня небольшой затуп с подготавливаемыми запросами. Если то как подготовить и выполнить INSERT в принципе разобрался: $stmt = $mysqli->prepare("INSERT INTO users(user_login, user_password) VALUES (?, ?)"); $stmt->bind_param("ss", $login, $password); $stmt->execute(); - как то так в упрощенном виде.
То вот как провернуть это с SELECT непонятно. Как мне получить результат моего селекта после того как я пишу:
if (!($stmt = $mysqli->prepare("SELECT user_id, user_login, user_password FROM users WHERE user_login = ?"))) { echo "Не удалось подготовить запрос: (" . $mysqli->errno . ") " . $mysqli->error; } if (!$stmt->bind_param("s", $login)) { echo "Не удалось привязать параметры: (" . $stmt->errno . ") " . $stmt->error; } if (!$stmt->execute()) { echo "Не удалось выполнить запрос: (" . $stmt->errno . ") " . $stmt->error; }
>>440961 >>440991 Спасибо ананасы, я все осознал. Вообще пугает в погромировании то, что залепишь что-нибудь вроде [ ]?+ в регулярке, а в голове даже не шевельнется что это косяк. Только когда со стороны носом ткнут. И главное непонятно, чем ты думаешь когда косячишь, потому как очевидную ересь делаешь. очень нуб
Вот в моем коде я при создании объекта Game в конструкторе клонирую 2 объекта Hero, помещаю сами объекты в свойство Game - $heroes, а клонированных в $cloned; дальше в ходе 20 раундов оба основных объекта класса Hero изменяют значение свойства $health, посл е игры я пытаюсь присвоить $this->heroes = $this->cloned; но это не работает и в свойстве $heroes остаются те же объекты что и остались после 20 раундов.
>>441204 Но там же задача уже начата. Создай класс отделов. Создай классы работников. По ним создай объекты. Потом создавай методы по расчёту их оплаты.
>>441288 Всё, нашел сам, оказывается дело не в клонировании было - у меня просто return стоял выше в одной из управляющих конструкций и в большинстве случаев функция не выполнялась до места где совершалась замена .
Ты же фильтруешь не в oneFile() а где-то в другом месте. Как ты можеь гарантировать что не вызовешь эту функцию без фильтрации? Фильтровать надо прямо в функции. Ну и это все равно костыльный подход, есть плейсхолдеры которые специально придуманы для вставки данных в запрос, зачем ты пытаешься изобрести обходной путь?
Во всех языках кроме php данные вставляются через плейсхолдеры. Просто некоторые авторы учебников сами неграмотные, не разбираются ни в php ни в программировании и людей неправильному учат. В новых статьях и учебниках уже так никто не делает.
Ты не клонируешь ничего. Объекты отличаются от других типов данных тем что передаются по ссылке. Это значит что когда ты делаешь
$a = new Y(); $b = $a;
То ты в $b копируешь ссылку на тот же самый объект, а не клонируешь его. У тебя по прежнему один объект на который ссылаются 2 переменных.
И это сделано специально, в 99% случаев требуется именно такое поведение. Но тебе такое не подходит. Ведь фактиески ты вторую битву проводишь не героями со свежими силами, а теми что остались после первой, причем один из них скорее всего уже мертвый. Потому надо клонировать героев и отправлять на битву клонов.
Клонирование объектов надо делать явно, оператром clone.
Анон, выручай. Нубас, начал изучение этого вашего PHP и MySQL. Есть код: <?php include ("db.php"); $dan = $_POST["dan"]; // передаем переменной $dan значение глобального массива POST $sql = "INSERT INTO table1(text) VALUES('$dan')"; $zaprSQL = "SELECT * FROM table1"; $rezs = mysql_query($zaprSQL); while ($row = mysql_fetch_array($rezs)) { echo $row['text'] . "<br />"; } ?> По идее он выполняет соединение с базой, записывает в таблицу введенное в форме значение и выводит все записи этой таблицы. Работает, но выводит он мне все записи, кроме той, которую я только что добавил. Не пойму, что не так делаю.
Еще одна вещь с которой ты должен разобраться это вывод ошибок от MySQL. Попробуй выполнить неправильный запрос (напрмер 'SELECT ASDFGGGG') и убедись что ты видишь сообщение об ошибке. Если ты его не видишь то плохо, ведь ты не сможешь нормально отлаживать код.
В упрощенном виде ты зря убрал if, как я понимаю, без них сообщение не выведется. Видимо mysqli требует после каждого действия проверять результат.
Ну и еще, наверно есть библиотеки поверх mysqli которые позволяют писать меньше кода, сами проверяют наличие ошибок и тд.
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
— какие есть сущности, для которых мы сделаем классы? (Сотрудник и Департамент) — какие у них есть свойства (у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом). Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо. — что мы хотим от них получить (какие у них должны быть методы). Например мы хотим узнать сколько сотрудник заработал или сколько он пьет кофе. От департамента мы наверно хотим получить сколько всего выпито кофе и заплачено денег. — как сущности связаны? Очевидно, Сотрудник работает в каком-то Департаменте.
Также, сразу скажу еще один совет: гораздо удобнее сделать не один класс Сотрудник, а 4 класса: Инженер, Менеджер, и т.д. Тогда мы можем легко менять например правила расчет зарплаты или кофе для каждой профессии. Естественно, копипастить одинаковый код в 4 класса не надо — создай базовый абстрактный класс Сотрудник и унаследуй от него 4 класса-профессии.
>>441342 Неделя. Но я ни где не работал. Ни где не учился. И вообще ни чем не был занят. Хотя между задачками в дотку гонял. Было бы меньше свободного времени, то наверно месяц бы ушёл. Да, я ленивый хуй.
> У меня под виндой не создаётся файл без имени Сначала я хотел сказать, что у меня плохие новости: если ты не можешь справиться с созданием файла без имени, то тебе будет тяжело программировать.
Но потом я попробовал создать файл средствами винды и он действительно не создается! И даже кавычками проблему не решить. Но выход все же есть.
В-третьих можно использовать консоль как подсказал анон.
Сам я пользуюсь Total Commander и потому с такой проблемой никогда не сталкивался (но не рекомендую использовать эту программу: она платная, она несвободная, она старая и пора бы ее закопать уже).
То, что относится к герою должно быть в его классе. То, что не относится, не должно.
Например у героя должен быть метод takeDamage. Ты не должен снаружи лезть и менять какие-то свойства, это логика героя и он сам должен с ней разбираться.
метод isAlive тоже должен быть у героя, а не у игры. Это же герой живой или нет, а не игра. И у него не должно быть аргументов. Ты просто вызываешь isAlive и получаешь ответ, жив ли еще герой или уже нет (можно просто проверять равен ли HP нулю как я понимаю, если равен то мертв).
> if ($hero->isChance($hero->crit)) { Опять же ты занимаешься не своим делом. Должен быть просто метод isCriticalHit() и все.
> public function getHit($k) // Здесь ты неудачно выбрал параметр функции. Почему число? У нас же ООП. Передавай сразу объекты, кто и кого бьет:
getDamage(Hero $attacker, Hero $target)
Смотри, какая хорошая и понятная функция получилась.
> public function isDoubleHit($k) То же самое, лучше передавать в функцию героев
> if ($win == 0) { > $first++; Как-то запутанно. Не проще ли так?
1 — победил первый 2 - второй 0 - никто
Ну или вообще, возвращать объект героя-победителя или null при ничье.
Да, верно, там в документации есть готовый файл. А в статье на хабре можно прочесть и понять как это работает (работает просто: если идет обращение по URL который не соответствует никакму файлу, вызвать index.php)
> Работает, но выводит он мне все записи, кроме той, которую я только что добавил. Скорее всего она не добавилась из-за ошибки потому и не выводится. У тебя включен вывод ошибок? Если нет то очень плохо, как ты вслепую угадаешь в чем причина?
Если статья или учебник вставляет данные напрямую то скорее всего она неправильная и старая. Лет 10 назад действительно неграмотные авторы так учили делать, в итоге появилась куча уязвимого кода.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
>>441365 >Скорее всего она не добавилась из-за ошибки потому и не выводится. У тебя включен вывод ошибок? Если нет то очень плохо, как ты вслепую угадаешь в чем причина? Нет, она добавляется. То есть, если посмотреть через админку MySQL, то там все есть и если запустить форму по новой, то предыдущее значение теперь выйдет (а вновь введенное опять нет).
>>441380 >Если вставилось успешно то должна сразу же выводиться. Вот я поэтому тут и спрашиваю - должна, но нифига. Попробуй сам или подскажи другой код, где работает.
Я подозреваю, что проблема не в этом коде. Этот код же не сам по себе, у тебя какие-то другие файлы там еще есть, может быть из-за того как ты вызываешь этот код ты чего-то не видишь. Или ты что-то перепутал.
Этот код может либо не вставить запись вообще, либо вставить и вывести все что есть.
> $sql = "INSERT INTO table1(text) VALUES('$dan')"; > $zaprSQL = "SELECT * FROM table1"; > $rezs = mysql_query($zaprSQL); запрос из переменной $sql вообще не выполняется. И ты ничего никуда не вставялешь.
Сап. Есть изображение завернутое в ссылку. У всех ссылок на изображение одно и тоже "name". <a href = "" name ="" > <img src = ""> </a> Как можно вытащить "href" ссылки, которая оборачивает тег через <img>.
>>441342 Мне задачки ОПа проще на ассембли было написать, чем на php. Сразу начал свой фейс-бух хуячить, периодически в help заглядывая. Фейс-бух это такая социальная сеть для бух-галтеров.
>>441388 >запрос из переменной $sql вообще не выполняется. И ты ничего никуда не вставялешь. Да, теперь разобрался, тем не менее, у меня каким-то чудом все вставлялось. >Ну и код ужасен, я выше написал почему. Да, это буду учитывать в дальнейшем. Спасибо.
>>441441 Т.е класс внутри класса, это ничего страшного?
Я хочу сделать твою задачку по ООП про компанию "Вектор". Хочу сделать класс Cотрудник в котором будет указываться его //имя, должность. Ранг, зарплата, кофе, документы будут вычисляться методом при создании класса. Далее, будет класс Департамент, который будет создавать Сотрудников и вычислять\выводить необходимые данные.
Не совсем понимаю суть внедрения зависимостей. Например, есть класс User. Есть метод User::getFav (возвращает любимый предмет юзера).
Любимые предметы могут быть разные: "любимая еда", "любимая музыка", и т.д. И храниться они могут совсем в разных местах: базе данных типа SQL или в *.txt файлах.
Заранее мы не можем предсказать, что именно нам потребуется получить в будущем, любимую музыку или любимую еду пользователя, или ещё что-то, и из какого места хранения мы хотим это получить. В самом классе User описывать перечень возможных мест хранения и способов подключения к местам хранения, перебирать их через switch или if слишком суетно. Делать всё это зависимым от глобальных переменных ненадёжно, ведь глобальные переменные может изменить кто угодно где угодно и потом ищи-свищи.
Поэтому при создании объекта User::__construct($type) аргумент $type может являться объектом, указывающим тип места хранения, к которому мы подключимся для извлечения любимого предмета, и свойств такого подключения.
Объект класса User, в свою очередь, при создании заносит в своё свойство private $db_type переданнный аргумент $type, и дальше все методы, в том числе User::getFav работают через эту зависимость.
Таким образом мы сделали класс универсальным, мы можем передавать ему различные места хранения любимого предмета, тип любимого предмета, способы извлечения этого предмета из мест хранения, не оглядываясь на то какое именно место хранения и какой именно предмет нам понадобится. Вот это внедрение $type в качестве аргумента User::_construct($type) с последующим сохранением в private свойстве и является тем самым внедрением зависимости.
Правильно ли я понимаю, и если нет, объясните пожалуйста на этих аналогиях принцип dependency injection.
DI это вообще другое. Это способ решения проблемы связей между классами, что делать если классу A для работы нужны классы B и С (DI отвечает: надо внедрять их через конструктор например).
По твоему коду, ты пытаешься один класс сделать ответсвенным за все, и за хранение информаци о пользователе, и за получение ее. Нехорошо.
Лучше сделать для того 2 класса. Например пусть класс UserMapper загружает информацию о пользователе и вносит ее в класс User:
$user = $userMapper->loadById(100);
Маппером он называется так как отображает объект User на какое-то хранилище (то есть сохраняет туда и загружает).
Если используется несколько хранилищ (что странно), то можно сделать UserMapper чем-то вроде фасада который загружает информацию из UserDBRepository и UserFileRepository и собирает вместе.
> Поэтому при создании объекта User::__construct($type) аргумент $type может являться объектом, указывающим тип места хранения, к которому мы подключимся для извлечения любимого предмета, и свойств такого подключения. Это вообще как-то неправильно. Ты предполагаешь что пользователь обязан где-то храниться, но почему? Я могу захотеть просто создать пользователя в памяти и никуда не сохранять.
И более того, чтобы загружать себя откуда-то пользователю надо как-то получить ссылки на объекты которые этим занимаются (наример на соединение с БД).
Нехорошо, лучше сделать чтобы User ничего не умел сам загружать и вообще не знал где хранится информация о нем. Пусть этим занимается другой класс-маппер.
>>441476 Ты немного сумбурно расписал, но в общем ты всё правильно понял. Предположим у тебя есть класс, который выполняет какую-то свою задачу и у тебя появилась необходимость логировать информацию, допустим в тхт файл. Проще всего было бы прямо на месте в этом классе создать метод логирования и вызывать его где нужно. Но тогда бы ты нарушил принцип single responsibility, который гласит, что один объект должен выполнять только одно действие. Более того, ты бы нарушил принцип открытости/закрытости, ведь если бы понадобилось изменить способ логирования, скажем не в файлик, а в базу, то пришлось бы руками менять код основного класса, что неприемлемо.
Тогда можно было бы создать класс логирования отдельно class FileLogger, и создавать его экземпляр в конструкторе основного класса и засовывать в приватное поле private $loger и вызывать его по месту через $this->loger->log(); Но тогда бы ты нарушил принцип инверсии зависимостей и опять же принцип открытости/закрытости, так как при изменении способа логирования пришлось бы лазить в конструктор основного класса и менять там $this->loger = new FileLoger на $this->loger = new DbLogger. Теперь основной класс хоть и не диктует как именно логировать, он всё равно ответственен за выбор объекта, что неправильно.
Поэтому выход в следующем: создаём публичный метод-сеттер с сигнатурой public function(ILoger $loger) который будет принимать любой логер имплементирующий интерфейс Iloger, не задумываясь о том, что именно это за логер. Это и есть ООП абстракция и программирование не на уровне реализаций, а на уровне интерфейсов. Теперь будучи в основном классе ты можешь рассматривать $loger, как некий абстрактный логер, который будет делать то, что нужно именно клиенту твоего кода, без изменений в нём. Ну и нужно будет создать интерфейс ILoger с обязательными сигнатурами и каждый класс FileLoger, DbLoger, SomeWhereElseLoger должны будут этот интерфейс заимплементить.
>>441503 >метод-сеттер с сигнатурой public function setLoger(ILoger $loger)
fix
Олсо, дополню сеья. Тут у тебя может возникнуть вопрос, так а нах нужен этот самый интерфейс? Нужен потому что если в интерфейсе объявлена сигнатура скажем public function log($info); то ты теперь можешь с полной уверенностью в своём главном классе использовать $this->loger->log($someData); Да ты не знаешь, что именно за логер используется, но ты точно знаешь, что он умеет делать ->log($something), ведь у тебя в тайп хинте сеттера указано public function setLogger(ILoger $loger)
>А ты все файлы в одну папку кладешь? Что если загрузить 2 файла с одинаковым именем но разным содержимым?
Это я предусмотрел. Имя файла хранится в БД. А в сам файл хранится под уникальным кодом ну как то так D:\localhost\uppy\uppy\container\GhKEGFeeqJ А когда скачивается, то файл получает сохраненное имя из БД.
>Обычно эта ссылка ведет на главную. Непонятно почему она разная в разных шаблонах.
Потому что так сделано в RGhost.ru. Там кликом по лейблу можно переключатся между страничкой загрузки и страничкой закаченных файлов. Я же его копию делаю.
>В форме поиска надо добавить кнопку. Я не уверен что без кнопки она вообще будет отправляться.
Запрос отправляется нажатием на Enter. Опять же слизано с RGhost.ru там нет кнопки.
> header('Content-Disposition: attachment; filename=' . $this->name); >для опции filename разрешено использовать только латиницу (ASCII если точнее). русские буквы разные браузеры понимают по-разному. Лучше не используй эту опцию вообще.
мм... Именно эта опция отвечала за переименование файла. Из ..\uppy\container\GhKEGFeeqJ в .\uppy\container\filename.jpg Тогда, мне придётся поискать альтернативу. Пока на примете 2 варианта. Или вовсе не менять имя файла на уникальный код. И тогда не смогу хранить файлы с одинаковыми именами. Или сделать велосипедную свистопляску - перед скачиванием загружать под исходным именем этот файл в какую-то папку. А потом уже этот переименованный файл отдавать на скачивание. Ну, или какие существуют варианты этого решения?
>Я думаю, удобно при загрузке из БД преобразовать дату из mysql в php формат. А при вставке делать обратное.
Не уверен что правильно понял. Это нужно, для того, что б из такого формата "2011-06-10 15:18:00" переделывать в такой “4 июня 2011, 14:57″ ? Верно?
>Индекс по dateLoad сделал?
Теперь сделал.
>Ты отключил выполнение php скриптов в папке загрузок?
Нашел такое решение - создать в каталоге с файлами .htaccess
>>441560 Шindoшs переустанавливать уже пробовал? Попробуй переустановить ещё раз. Или воспользуйся нормальным редактором и сохрани код в кодировке UTF-8.
>>441584 хз, я его не знаю, но мне кажется что нужен. Я вот пока что пишу небольшой форум на процедурке, и мне уже начинает казаться, что если я буду накручивать на него функционал, то все там захлебнется в количестве костылей и говнокода. Утонет во всяких if и прочих include. Про ооп знаю только то, что мол помогает реализовать всё как в жизни и раскидать всё по полочкам, тот класс за то отвечает, тот за то. Думаю что оно нужно и пригодится мне в итоге.
Аноны, подмохите. Решил задачу двумя способами, но оба какие-то кривые и попахивают быдлокодом. Первый: http://ideone.com/gwfRo7 От второго у меня вообще KANSAS SITY SHUFFLE : http://ideone.com/NU8v7y
Ребят , я делаю задачки которые в ОП посте , дошел до регулярок , не могу понять толкм как делать задание с граммар наци. Там нужно написать все орфогрфические ошибки в одном регулярном выражении или для каждого свое? приведите пример кода пожалуйста
>>441635 не нужно. Да и как ты определишь вот это нет пробела после запятой, точки с запятой, восклицательного знака, вопросительного знака, двоеточия если разобьёшь на массив.
>>441630 Если не прописывать рандом для каждого отдельного слова, или не обновлять его как-нибудь каждый раз перед новым словом, то первая и вторая строчка стишка в output будут одинаковые, поскольку их структура word1 word2 word3 word1 word2 word3 word4 word5 и стих будет уровня Внезапных слов сухие листья Внезапных слов сухие листья Я оставляю смысл жизни да и Как ты запишешь count в рандом?
$letters = array('а','б','в','г','д');
$number = count($letters);
$random = mt_rand(0, $number);
Если так - ничего не выйдет. Count считает количество элементов(в данном случае их 5), а в массиве элементы дефолтно нумеруются с нуля. Следовательно, 0-4. Если выпадает пятерка - fail, ничего на экран не выведется. Это можно легко проверить на http://ideone.com/MYx54x
>>441631 Что бы задать поиск нескольких вариантов слова, применяется символ "|" (вертикальная черта) или //S здесь соотвертствует любому символу кроме пробела. Вот регулярка где после любого из этих символов . , ; ! ? : стоит непробел точка и запятая тут экранируются /\.\S|,\S|;\S|!\S|\?\S|:\S/u можно её чуть покороче записать /(\.|,|!|:|\?|!)\S/u А потом добавлять через | остальные правила. Вот на жи, ши, например. /(\.|,|!|:|\?|!)\S|жы|шы/u
> $random1 = mt_rand(0,3); то неудобно так как надо вручную считать число слов и пересчитывать при изменении массива. Надо сделать либо через count либо через функцию array_rand которая возвращает случайно выбранный ключ массива.
И ошибки исправить, они внизу написаны:
> PHP Notice: Undefined variable: rando5 in /home/iAXCy2/prog.php on line 34
> От второго у меня вообще KANSAS SITY SHUFFLE : Не, это наверно уже усложнение, массив сортировать незачем.
А вообще, твоя задача решается с DOM и XPAth. Xpath это язык запросов для поиска узлоов в доме. С ним можно например искать все теги a внутри которых есть img.
Подскажите кто прошаренный. http://ideone.com/VDERi0 перепиливаю свою гостевуху под подготовленные запросы и ООП-стиль mysqli_ вместо процедурного. И вот вопрос, в этом коде нужен подготовленный запрос? Я как бы понимаю, что он нужен там, где я подставляю в запрос переменную, а тут?
>>441676 http://ideone.com/6ArA06 Вот так хорошо? Не после каждой же строчки работы с базой писать проверку на ошибки? Если execute() сработал, значит дальше уже будет всё хорошо?
>>441700 Для регулярок. Есть сайты наподобие ideon. Там удобно экспериментрировать. И сразу видно что они находят. Скинул бы их названия да вакаба не пропускает.
>>441843 Нет, я как истинный гуманитарий заменил одиночные кавычки на двойные. Блджад, мне еще практиковаться и практиковаться. Порой глупейшие ошибки совершаю. Вот сейчас засел за задачку с числами прописью, чувствую, я далеко не раз выматерюсь на себя за свою тупость, пока её решаю.
Подскажите, вот у меня есть на sql сервере две таблички категорий, допустим 1. Мясо, 2. Рыба и вторая с подкатегориями и вторичными ключами к первой 1. Курица (1), 2. Свинина (1), 3. Окунь (2), Вобла (2) в скобках это втор ключи подкатегории. Я через php получаю значения полей первой таблички и вывожу их в виде <select>. Можно ли сделать так чтобы при выборе мышкой категории из первого селект, в соседнем <select> появлялись подкатегории (допустим нажал на мясо и в соседнем селект появились строчки Курица, свинина). Пока я только с помощью <form> и кнопки пост могу получить в переменную id первой категории, а как сделать динамически чтобы сразу выводились подкатегории во втором селекте? Может кто видел статью с подобной задачей? чую придется курить яваскрипт. база кстати pg-sql
>>441347 >базовая ставка Я что-то не могу найти этого в задаче. Или это то, сколько получает простой сотрудник 1го ранга? Тогда почему в абстрактный класс нельзя запихнуть кофе и бумаги?
>>441890 Но ты же сказал что > у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом но также есть и кофе и бумаги. Тогда почему нельзя все положить в один абстрактный класс?
> у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом). Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо. Я имел в виду, ты хранишь в сотруднике только его ставку, а зарплату с учетом ранга и босса хранить не надо, а можно вычислить методом. Аналогично с кофе: ты хранишь только базовую велеичну, а общее потребление с учетом ранга и босса вычисляешь методом.
Меня часто спрашивают аноны, сколько можно заработать на фрилансе. Ну я-то лентяй еще тот, потому лучше почитайте ответы и комментарии других людей: https://toster.ru/q/175375
Аноны, максимум тупой вопрос: как создают сайты со страничками без расширений .html/.php и т.д.? Например, этот тред с расширением html, а вот статьи на Лентеру - просто типа такого http://lenta.ru/news/2015/02/25/naftogaz/
>>442036 Наверное потому что там как таковых страничек и нету. Это не ссылка на страничку, а какой-то хитрый путь/запрос в базу. А страничка генерируется и верстается автоматически, просто беря инфу из базы. Сам уже задумывался над этим, но ответ не искал, поэтому ждем кто что еще скажет. Думаю что найду ответ изучая фреймворки.
Для чего задают вопросы "для чего используют ООП?" ? По моему любому, кто хоть раз использовал ООП, очевидны его преимущества перед процедурным программированием.
>>438085 Напомни пожалуйста, как называется схема, когда в бд есть произвольное множество объектов, которые имеют произвольное количество свойств каждый? Чтобы св-ва и знач-ия в отдельной бд?
>>441363 > public function getHit($k) // Здесь ты неудачно выбрал параметр функции. Почему число? У нас же ООП. Передавай сразу объекты, кто и кого бьет:
getDamage(Hero $attacker, Hero $target)
Смотри, какая хорошая и понятная функция получилась Не совсем понял, разве можно так давать ссылки на экземпляр объекта указывая его класс и через пробел сам экземпляр?
>>442171 Хм, вот смотри, там дается пример типа >/articles.php?tag=summer&action=list — просмотр списка статей с меткой summer (лето). У меня есть простенькая форма, в которой через кнопку выполняется скрипт, передается пара переменных (errorName и errorText). Если я создам гиперссылку, как в этом примере >/action.php?errorName=err1&errorText=errt1 то нифига эти значения переменных не передадутся. Там надо еще что-то делать? Тестирую все это на денвере.
>>442081 >кто хоть раз использовал ООП А задаются эти вопросы теми, кто его не использовал и только начинают учить. И кто желают знать с какой целью они его учат, для мотивации. Если есть мотивация, то осваивается легче и быстрее же.
>>442189 ООП и МВЦ, читай и используй ООП/МВЦ. Я реализовывал ЧПУ через создание экшенов, отлавливал введенный урл, создавал на лету имя экшена и вызывал его. Не очень сложно на практике.
>>438093 >Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода. Что-то нифига он не работает. Алсо, есть плагин для Notepad++ для подобного?
>>442291 >пока не выбран один из radio button Пропустил эту строчку. Я жопой похоже читал. PHP, исполняется на сервере. После того как он отдал страничку, больше он в неё не лезет. Сделать эту кнопку неактивной на уже отправленной страничке ПХП не может.
>>442314 Передаёшь функции переменную и можешь использовать её внутри этой функции. f($mysqli);
Но, лучше класс User исползовать для работы с пользователем, а для работы с БД создать класс который и будет этим заниматься. И который будет иметь свойство $mysqli. Но лучше используй PDO. Как то так.
>>442251 Поставь себе phpStorm, там есть форматирование кода и вообще очень удобная и простая штука, когда начнешь писать что-то посложнее оценишь. 1. Качай евалюэйшен. 2. Качай файл с паролями с русракера .... 3. ПРОФИТ!
>>442314 >Каким образом мне использовать перменную $mysqli? Её можно спокойно использовать внутри методов класса User? Можно, если ты ее передашь непосредственно в метод. Но лучше, раз уж ты познаешь ООП, используй паттерны. Почитай статью ОПа, там довольно доступно написано https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a.
Задачка про сумму прописью. Понимаю, что код весь из недостатков состоит, но хотя бы пните как надо переделать. Хотя работает и так, лол. http://ideone.com/WAyTn7 Предполагаю, что всю эту муть надо как-то в циклы засунуть, но как это сделать, межушный ганглий соображать отказывается.
Ты можешь настроить веб-сервер чтобы любой URL соответствовал любому файлу. То есть нанример при обращении /news/1/2/3 вызывался news.php. Или при обращении к 1.html вызывался 2.php
Обычно при исплоьзовании фреймворков все запросы перенаправляют на index.php, а там роутер анализирует URL и вызывает нужную функцию (кстати если будешь делать нашу задачку на файлообменник, познакомишься с этим способом).
ООП был придуман для больбы со сложностью приложений. По мере роста объема кода обычное процедурное приложение прверащается в лапшу из функций и переменных (примеры: вордпресс, друпал). Его трудно поддерживать и трудно понять как оно работает.
ООП позволяет писать более аккуратный, структурированный (то есть разбитый на части), повторно используеый код. Это делается за счет того, что данные и функции для их обработки помещаются в отдельные классы, независимые друг от друга. каждый класс занимается своим делом, и чтобы что-то поправить, не надо разгребать весь код, достаточно поменять один класс.
Сам ООП начали исплоьзовать в 80-х годах прошлого века и постепенно этот подход вытеснил остальные в промышленной разработке.
Ну а привыкнув к ООП начинаешь его везде исплоьзовать, даже в простых приложениях.
Мы в нашем треде изучаем современные технологии и потому изуаем и используем ООП.
> Не совсем понял, разве можно так давать ссылки на экземпляр объекта указывая его класс и через пробел сам экземпляр?
Hero это тайп хинт. Он говорит что в функцию можно передать только объект класса Hero или наследника.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное). Используй их везде.
> public function __construct($hero1, $hero2) > $this->cloned[] = clone $hero1; Это неправильно. Смотри, ты в конструкторе Game (то есть один раз за программу) делаешь 2 копии. А надо по-другому. Надо хранить исходных героев, а клоны делать перед битвой:
функция провести одну битву() { сделать клон героев сделать N раундов этими клонами }
При этом хранить в свойствах клонов не надо. Ты хранишь в свойствах только то что должно храниться долгое время, а клоны нам нужны на один раз — провести одну битву и выкинуть их.
То что ты сейчас делаешь, выглядит как костыль — сохранить здоровье, а потом восстановить. Ведь по если мы начнем усложнять код, добавим допустим запас маны, очки опыта и тд то ты замучаешься их все восстанавливать в начальное состояние. Надо клонировать героев перед битвой (ну или надо сделать метод в герое для полного восстановления в начальное состояние, но по моему клонировать проще).
Хороший ООП код должен быть написан так, что если ты меняешь класс героя (например добавляешь новые характеристики), то тебе не надо править класс Game для их восстановления. В этом и суть ООП что достаточно поменять один класс и не надо лазить по всему коду.
> public function getHit($attacker, $target) Поставь здесь и во всех остальных функциях куда передаются объекты или массивы, тайп хинты.
> $avoidAttackStat = $target->skill + $target->agility; > $avoidCrit = $target->dodgeCrit; Функция getHit($attacker, $target) поулчилась довольно сложной и запутанной. Я бы советовал вынести из нее отдельные расчеты в отдельные функции с понятными названиями:
- функция расчета $crit, полуает на вход 2 героев и возвращает $crit - функция расчета $dodge - функция расчета $block
Эти функции наверно должны принимать на вход обоих героев.
Так у тебя код станет проще и читабельнее, если его разбить на несколько функций. А сейчас ты смешал несколько расчетов в одну кучу и разобраться гораздо сложнее.
> return $target->isAlive(); думаю в этом нет необходимости. Тот кто вызывает функцию getHit может сам вызвать isAlive. А так ты в функцию помещаешь лишний код.
Более того, функция названа неправильно. Ее можно назвать getHit если она только расситывает урон но не наносит его. А твоя функция должна назваться просто attack, hit, makeDamage или как-то так, чтобы название отражало то, что она делает.
Переменные надо переименовать:
$x -> $firstHeroHitCount или $firstHeroDobleHit или как-то так
> foreach ($this->heroes as $number => $hero) { > if ($number == 0) { Вообще-то можно просто написать
$first = $this->heroes[0];
Зачем цикл?
И сразу же второй вопрос, а зачем тебе вообще массив героев, не проще сразу сделать свйоства firstHero и secondHero?
Цифры 1, 2, 3 лучше заменить на константы Game::FIRST_HERO_WINS, SECOND_HERO_WINS, NOBODY_WINS. Это сделаеn код читабельнее, а сейчас то значит цифра непонятно.
А ты попробуй без ООП решить задачу про ООО вектор например (один анон сдался, другой написал какой-то адский лапшекод и сам наверно понял что ерунда получилась).
mysqli (не mysql) тоже не старый. Но мне он например не нравится темто не умеет выбрасывать исключения и надо после каждой функции через if проверять ошибки.
Неправильно использовать mousedown (ведь оно соответствует и нажатию правой и нажатию средней кнопок мыши). Есть событие change. Ты явно плохо знаешь события.
Нет. Абстрактным может быть класс (это значит что нельзя создать объект такого класса) либо метод (это метод без тела, который обязаны реализовать наследники класса).
PHP тебе пишет на ideone:
> Properties cannot be declared abstract
> self::clculateSolary(); self:: используется для вызова статических методов: http://php.net/manual/ru/language.oop5.static.php (это методы которым не нужен объект и которые вызываются на классе, а не на объекте).
> $this->solary = $this->solary + ($this->solary это тоже плохая идея. Лучше в salary хранить базовую ставку, а зарплату никуда не сохранять, а просто сделать метод который рассчитает и вернет ее. А то что делать если мы решили повысить работника с 1 до 2 ранга? В моем варианте достаточно поменять rang c 1 на 2 и все будет работать правильно. А в твоем?
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
на винде можно исплоьзовать метод с htaccess. Настроить его так чтобы при запросе
/download/abcdef/filename.txt
отдавался бы файл /container/abcdef (который браузер сохранит как filename.txt из-за того что в URL стоит это имя).
Попробуй, это не сверхсложно, на хабре есть статья про mod_rewrite.
Ошибки, которые нашел другой анон, надо бы исправить.
Насчет композера, ты зря его избегаешь. Он прекрасно работает под виндоуз. Если ты не доверяешь его инсталлятору, ты можешь скачать с оф. сайта composer.phar и запускать командой
php c:\files\composer.phar install
То есть указывая полный путь. Перед тем как выполнять команду, надо перейти в папку проекта разумеется. Если composer.phar лежит в папке проекта то писать путь не надо.
Если у тебя php не в PATH то и к php надо писать полный путь:
Просто ты уже не совсем начинающий, потому с тебя спрос выше, и хорошо бы уметь пользоваться командной строкой хотя бы на уровне «выполнить простую команду».
Если что-то тебе кажется непонятным, задавай вопросы. Там где-то была на хабре статья про композер, ты ее сам можешь найти и почитать.
Фактически от тебя требуется создать composer.json, прописать туда нужные библиоетки (Slim) и их версии, и запустить установку через композер. А потом в index.php подключиь файл vendor/autoload.php.
Поэкспериментировать с композером лучше не на проекте, а на пустой папке (ее можно всегда удалить и создать заново). Создай папку, положи туда composer.phar, создай composer.json, запусти композер из консоли и попробуй установить что-нибудь. Композер должен создать папку vendor и в нее установить указанную тобой библиотеку.
Поначалу конечно что-то может не заработать. Пиши тогда в тред. думаю, лучше сразу разобарться с проблемой.
А и еще. Это же твоя вторая задача, было бы хорошо для шаблонизатора исплоьзовать twig. Ведь простые php-шаблоны ты уже исплоьзовать в первой задаче, лучше изучить новую библиотеку. Тем более что он удобнее чем простые php-шаблоны.
>>442511 >На PHP никак. Я понял уже. >А ты <?php в начале не забыл? Именно так. >>442501 >Ты можешь настроить веб-сервер чтобы любой URL соответствовал любому файлу. То есть нанример при обращении /news/1/2/3 вызывался news.php. Или при обращении к 1.html вызывался 2.php Где об этом почитать?
> singleton('newDM' Лучше назвать нормально, filesMapper. Ведь это маппер для файлов? Ну так и называй его fileMapper.
Класс тоже стоит переименовать. Заодно научишься пользоваться функцей «найти и заменить во всех файлах». В Sublime это например Ctrl + Shift + H.
> require_once "/lib/Datamapper.php"; В php есть такая штука как автозагрузка. Это когда при обращению к несущестующему классу вызывается функция-автозагрузчик и она может приинклудить нужный файл с классом. Таким образом, require писать не требуется.
При исплоьзовании композера тебе вообще не надо писать автозагрузчик так как в композере он уже есть. Тебе надо лишь в composer.json написать в какой папке искать файлы (и сами файлы должны быть названы также как и класс). Вот доки на английском: https://getcomposer.org/doc/04-schema.md#autoload
Заметь что композер поддерживает несколько вариантов автозагрузки.В первую очередь он расситан на код с неймспейсами, но можно и использовать с обычными классами, смотри пример после текста
> If you want to have a fallback directory where any namespace will be looked for, you can use an empty prefix like:
Ты уже делаешь второе, а не первое задание, так что с автозагрузкой и неймспейсами должен бы разобраться.
Надо сделать автозагрузчик (лучше всего через композер) и убрать лишние require_once.
> $app->container->singleton('newFile' Это неправтльно. В синглетон мы кладем объекты, которые должны быть в 1 экземпляре. Если обратиться к синглетону второй раз то вернется тот же самый объект что был создан в первый. Потому делать синглтон для new File бессымсленно — он всегда будет возвроащать один и тот же объект.
Файл нужно создавать через new File, без синглтонов так как каждый раз тебе нужен новый объект.
> while ($mapper->iscodeUsed($file->getCode())) { тут стоит добавить ограниение числа попыток. Хотя бы для защиты от заикливания на случай если ты ощибешься где-то.
Также тут уместнее не while, а do ... while.
Для защиты от выполнения кода хорошо бы не только использовать htaccess но и переименовывать файлы. А то бывают хостинги где команды php_flag и addType отключены. А вместе с ними отключается твоя защита (у одного анона так и получилось при загрузке на хостинг).
> $app->render('/header.html'); Этот вызов лучше перенести в шаблон /upload.html
> $id = $mapper->addFile($file); Обычно принято делать по другому.Маппер не возвращает id а просто проставляет его в объект File.
> $word5 Странное название, что значит 5? Почему не просто $word?
> function numberToText($number) { Тут куча унылой копипасты, а копипаста зло. Не надо делать склонение отдельно для рублей, тысяч, миллионов. Сделай одну универсальную функцию которая получает на вход число и 3 формы слова и возвращает нужную:
(17, соболь, соболя, соболей) -> 17 соболей
Соответственно исплоьзуя ее ты можешь избавиться от нечитаемой лапши в строках 140 - 160.
> if ($lastDigit == 1 && $lastDigits != 11) { > $word5 = " рубль"; тут проще сразу ставить return " рубль"; . Зачем вообще переменную заводить?
> $arrNumber = preg_split ( "//", $number, - 1, PREG_SPLIT_NO_EMPTY ); С числами надо работать с помощью математиеских фукнций: floor, ceil, round а не строковых.
Это просто, вот 2 волшебных команды:
// получить последние 3 цифры числа: echo 1234567 % 1000; // выведет 567
// получить число миллионов echo floor(1234678 / 1000000); // выведет 12
Комбинируя их, можно получить что угодно.
> $arrNumber Массивы принято назвать словом во множественном числе: $digits (цифры).
Код в строках 82-100 невозможно читать. Более того он явно сделан методом копипасты. Надо переделать по такомму алгоритму:
слова = пустой массив;
если в числе есть сотни { добавляем слова для сотен; }
если число оканчивается на 11-20 { доабвляем нужные слова } иначе { добавляем десятки; доабвляем единицы; }
Еще, никогда не создавай таких сложных функций. Посмтри сколько в них действий, десятки если не сотни. Надо разбивать большие функции на маленькие (ксттаи эта задача как раз должна обучать этому).
Функция numberToText($number) должна работать примерно так:
если в числе есть миллионы { доабвляем число миллионов; }
если в числе есть тысячи { доабвляем число тысяч; }
если в числе есть единицы { доабвляем число единиц; }
Твой код может и рабоатет, но как решение он не годится. Его невозможно ни читать, ни поддерживать, огромные функции-простыни кода, куча переменных с непонятными названиями, надо все переделывать и упрощать.
Поясните за таблицы. Их использование в разметке считается хорошим тоном, чтобы все не разъезжалось к хуям, если я правильно понимаю. Где почитать толково для нубов о правильном использовании?
>>442345 Сделал вот так: <html> <head> <title>Блокировка поля</title> <script type="text/javascript"> function agreeForm(f) { // Если поставлен флажок, снимаем блокирование кнопки if (f.errorLvl.checked) f.submit.disabled = 0 } </script> </head> <body> <form method="post" action="action.php"> <input type="radio" name="errorLvl" value="low" onclick="agreeForm(this.form)"> Низкая <p><input type="submit" name="submit" value="Отправить" disabled> </body> </html> Но оно работает только если одна радиокнопка. Если две или три (добавляем, например, строчку <input type="radio" name="errorLvl" value="high" onclick="agreeForm(this.form)"> Высокая<br>) - кнопка Отправить все время неактивна.
>>442604 Извините аноны, уже нашёл решение, но возник новый вопрос, допустим у меня есть такой код:
class news extends db {
public function getNews() { $pol="M"; $stmt = $this->mysqli->prepare("SELECT id, name, lastname, pol FROM student WHERE pol=?"); $stmt->bind_param("s", $pol); $stmt->execute(); $stmt->bind_result($id, $name, $lastname, $pol); while($row = $stmt->fetch()){ //Здесь надо что то написать } } }
Как мне получить вывод всех данных из таблицы, вот в этом куске кода:
while($row = $stmt->fetch()){ //Здесь надо что то написать }
Вариант записать в цикле что то такое $arr[] = $row не подходит, так как цикл всё выводит только если записать переменными вроде:
Заношу данные в базу MySQL через форму запроса. В таблице некоторое количество полей, как мне правильно сделать вывод этих данных? То есть, чтобы по гиперссылке открывалась страничка, где в таблице указаны введенные ранее данные. Обычный вывод в несколько строчек я сделал (через while ($row = mysql_fetch_array($rezs))), а как сделать вывод данных именно в виде таблицы? Я же не знаю, сколько строк у нее будет. И еще сразу вопрос - можно ли отправлять данные как в form, но не по кнопке, а через гиперссылку? То есть, например, есть ссылка в виде текстовой строки, по щелчке на ней идет выполнение action.php с параметрами, взятыми, например из текста этой ссылки (или еще откуда).
Ребят , нужно работать с mb функциями , я прописал
mb_internal_encoding ('utf-8'); но получаю: Call to undefined function mb_internal_encoding()
В php.ini раскомментил extension=php_mbstring.dll , файл php_mbstring.dll в папке есть , но когда открываю phpinfo модуль mbstring отсутствует. Подскажите пожалуйста как правильно его установить.
Ребяты, сделал сортировку таблицы из MySQL - щелкаешь по заголовку, таблица сортируется по этому параметру (передача через GET в урле). Как сделать так, чтобы повторном щелчке порядок сортировки менялся на обратный?
>>442693 гетом передавай порядок - прямой или обратный на страничке с также лови гет и формируй ссылку в зависимости от содержимого. <?php if ($_GET['order']=='desc') {$order='desc'} else {$order='asc'} ?> <заголовок> <a href='index.php?order='.$order> </заголовок>
>>442658 http://jsfiddle.net/k4qhtx4u/ Переделал немного. Теперь вроде немного лучше, но все равно остается много вопросов: Текст внутри картинки, по моему, имеет такую же прозрачность, как и блок в котором он находится. Как от этого избавится? В маленьком окне ширина блока с текстом внутри картинки вылезает за саму картинку. Что за херня? Как выравнить однёрку правее, чтобы она прилегала к тексту? Если изменить margin, то 2 3 4 будет внутри основного текста.
>>442850 >Текст внутри картинки, по моему, имеет такую же прозрачность, как и блок в котором он находится. Как от этого избавится? заверни весь текст в абзац с опасити=1, че ты?
>>442524 Задачка про сумму прописью. Второй подход к снаряду. http://ideone.com/5BiRqV Столкнулся с небольшим вопросом. Изначально я определял функцию spellingsOutp внутри функции inclineWord, inclineWord в отдельном файле в таком виде работала прекрасно. Когда поместил это непосредственно в программу, то фатал еррор нельзя переопределить, кровь, кишки. Вынес spellingsOut так сказать в корень, и все стало ок. Это почему?
Ошибка в том что не установлен (или не разрешен) модуль openssl. Вывести список подключенных модулей можно командой
php -m
Получить подробную информацию о текущих настройках php командой
php -i
Чтобы разрешить расширение openssl, надо открыть php.ini (если у тебя их несколько то тот который используется в командной строке) и раскомментировать или дописать строку extension = php_openssl.dll или как-то так.
В твоем случае openssl скорее всего идет в комплекте с php просто не разрешен.
Также, я не уверен но возможно что под денвером надо открывать не обычную командную строку, а через меню денвера, чтобы php получил актуальные настройки. Но я не уверен.
Ну и заметь что несмотря на отсутствие openssl композер все же смог скачать библиотеки другим способом.
Библиотека openssl нужна для установки защищенного соединения с сервером.
Таблицы предназначены для вывода табличных данных. Например, расписание турнира или таблица стран и их столиц.
Лет 15 назад, когда HTML/CSS был гораздо менее развит, таблицы от безвыходности использовали для верстки сайтов (а прозрачные картинки для создания полей и оступов). Но это очень плохой и неудобный способ, CSS дает гораздо больше возможностей потому никто так не делает.
На таблицах сейчас верстают только HTML-письма так как почтовые сервисы вырезают многие правила CSS.
Если ты говоришь про верстку таблицами, ты скорее всего учился по очень старому учебнику? Выбрось его и найди нормальный.
Напомню, что у нас есть хорошие задачи по HTML/CSS (ссылка в ОП посте) которые помогут найти пробелы в знаниях и научат тебя верстать средствами CSS.
Скачать можно тут https://www.apachelounge.com/download/ в архиве modules-2.4-win32-VC11.zip (или win64) но они возможно будут работать только с Апачом скачанным с Apachelounge. С другим — не факт. Заметь что они для версии 2.4.
Под Линукс зависит от дистрибутива, в дебиане/убунту ищешь расширение командой
Тебе надо сначала изучить язык php. Так как если бы ты его знал то ответ был бы очевиден: использовать какой-нибудь другой вид цикла или прописать поля прямо в шаблоне.
Надо сначала изучать php потом изучать sql и базы данных, потом библиотеки вроде mysqli/pdo.
А если ты берешь учебник или видеокурс, проматываешь сразу на середину и копируешь строчки не понимая что они делают, ты ничего не добьешься. Программирование так не работает.
> Я же не знаю, сколько строк у нее будет. Во-первых, ты знаешь. Ты же должен знать сколько у тебя в таблице колонок. Во-вторых, в html и не требуется писать число столбцов/колонок.
> можно ли отправлять данные как в form, но не по кнопке, а через гиперссылку? Можно сделать средствами CSS чтобы кнопка выглядела как ссылка. Но вообще это бред какой-то. Ссылка ведет на другую страницу и какой смысл делать ссылку-которая-на-самом-деле-кнопка, я не понмиаю. Чтобы пользователя запутать?
В сумме 99% + 22 px очевидно дают больше 100% и прямоугольник вываливается вправо. Это неправильо, смешивать пиксели и проценты.
Далее, вот это:
> display: table; Зачем? Только чтобы блок охватывал флоаты внутри? Для этого есть более удобный клеарфикс, ссылка на который дана в подсказках к заданию.
Ты из-за исплоьзования table не можешь поставить width auto и блок вываливается за край.
> В php.ini раскомментил extension=php_mbstring.dll , файл php_mbstring.dll в папке есть , но когда открываю phpinfo модуль mbstring отсутствует. Подскажите пожалуйста как правильно его установить. Апач перезапускал? php ведь сам новые настройки не увидит.
Да, ты правильно заметил. Подпись съезжает так как сверстана неправильно.
> bottom:-250px; Ты предполагаешь что высота картинки будет ровно 250px. С чего бы это? Надо чтобы работало с картинкой любой высоты.
Вообще, старайся как можно меньше прописывать абсолютные величины и как можно больше определять автоматически. иначе замучаешься потом поддерживать такую верстку.
Тайп хинтинг позволяет указать что аргумент функции должен быть определенного типа. Если передать аргумент другого типа, скрипт завершится с ошибкой. Это делает твой код гораздо понятнее и надежнее.
Можно указать несклоько вариантов:
— имя класса или интерфейса (должен быть передан объект этого класса или его наследник) — array (должен быть передан массив) — callable (должен быть передан указатель на функцию, виды указателей описаны в мануале http://php.net/manual/ru/language.types.callable.php )
> Объект в функцию разве не по ссылке передаётся, т.е. аддфайл изменит его? Да. Это нам и надо.
Объекты не копируются при присваивании или передаче в функцию, просто передается ссылка на объект. Смотри:
$a = new X; $b = $a;
Тут 2 переменных $b и $a содержат ссылки на один и тот же объект. С другими типами (массивы, строки, числа) команда $a = $b создает копию, а объекты передаются почти как по ссылке. Мануал: http://php.net/manual/ru/language.oop5.references.php
Чтобы сделать копию (клон) объекта надо использовать оператор clone. В 99% случаев он тебе не нужен, тебе нужно именно передать ссылку на объект.
> и у меня почему то не считается размер png, от чего это может быть? Не знаю, но я не думаю что дело в формате файла. Ведь размер файла никак не связан с его расширением. Должно либо для всех файлов работать либо для всех не работать.
> Текст внутри картинки, по моему, имеет такую же прозрачность, как и блок в котором он находится. Как от этого избавится? нужно не использовать opacity, а просто поставить полупрозрачный фон. Описание:
RGBA работает в IE9+ и в современных бюраузерах, так что проблем с ним нет (ну даже если не работает, пусть в старом браузере фон будет непрозрачным — это приемлемо и текст читать не мешает).
Потому я бы поставил 2 правила:
background: непрозрачный фон для старых браузеров; backgorund: прозрачный для новых;
Старые браузеры поймут только первое правило, а новые оба и второе переопределит первое.
> В маленьком окне ширина блока с текстом внутри картинки вылезает за саму картинку. Что за херня? Сделай чтобы переносилось как-то или текст обрезался. Главное чтобы картинка уменьшалась при уменьшении ширины окна.
> figure{ > position: absolute; AP (абс. позиционированные) элементы вырываются из потока и не занимают в нем места. Если после картинки идет текст, он окажется под картинкой. Это неправильно. Если ты этого не знал то перечитай внимательно учебник http://softwaremaniacs.org/blog/2005/08/03/css-layout-positioning/
Далее, под черной подписью у тебя 3-4 пикселя пустого места. Почему? Потому что img это inline элемент который выравнивается по базовой линии. Почитай
> figcaption{ > width: 340px; Не, так не пойдет. Надо чтобы работало с картинками неизвестного размера (например они могут браться из базы данных и заранее размер неизвестен).
У меня такое ощущение, что ты ставишь свойства наугад, в надежде что заработает. Это неправильно. надо понимать эффект от разных свойств и ставить те, которые нужны.
Например, у нас задача чтобы блок с картинкой (figure) с одной стороны зависел от размеров картинки, с другой стороны не превышал ширины родителя.
Давай подумаем, а в каких случаях ширина элемента зависит от содержимого? Ровно в трех: display: table/table-cell, display: inline-block/inline, float.
Table плох тем что в нем не работает абсолютное позиционирование. Ты не можешь позиционировать элементы относительно ячейки или таблицы.
Float плох тем что он выносится вбок из потока и текст следующий за ним подтягивается вверх, если к нему не применить clear.
Inline-block выглядит тут разумным вариантом.
Inline тут не подойдет, так как годится только для выделения слов в строке и например не умеет растягивать свою высоту по содержимому.
Таким образом, мы получаем что нам подойдет inline-block, который по умолчанию растягивается под размеры содержимого.
> Изначально я определял функцию spellingsOutp внутри функции inclineWord зачем? В какой сиитуации это вообще может понадобиться? Никогда не определяй функции внутри функций (кроме анонимных).
Ошибка так как при втором вызове функции inclineWord она пытается второй раз создать spellingsOutp, а создать 2 функици с одинаковым названием нельзя.
> spellingsOut($int, $array) Не называй переменную array так как это ничего не значит. Называй например $words.
> if ($int % 10 == 0 || ($int % 100 > 10 && $int % 100 < 20) || ($int % 10 > 4 && $int % 10 < 10)) { Вообще этот if можно было и не писать
> array_push ( $words, Короче и нагляднее писать
$words[] = ....;
Еще, пробел около скобок при вызове функции принято не ставить:
someFunction($a, $b, $c);
Так, вообще в сравнении с прошлой версией разница как день и ночь, стало намного аккуратнее и понятнее. Исправь мелкие замечания и я думаю, задача будет решена.
>Нет. Абстрактным может быть класс (это значит что нельзя создать объект такого класса) либо метод (это метод без тела, который обязаны реализовать наследники класса). А как быть тогда с don't reapet yourself здесь?
>А то что делать если мы решили повысить работника с 1 до 2 ранга? А что делать если мы решили что искусственный интеллект справляется лучше чем "работник"? Давай лучше будем отталкиваться от конкретной задачи. И вообще, для решения этой задачи мне придется внести новую переменную $newSolary, что будет масло масляное - не одобряю.
А как правильно реализовать вывод таблицы, если у меня много-много строк и я хочу разбить их на страницы? Не, мысли как запилить очередной велосипед у меня есть (считаю количество строк, делю их на желаемое количество строк на одной странице и с этим играюсь при создании ссылок на страницы), но может есть способ проще и доступнее? Или все верно думаю? >>443113 >Если ты говоришь про верстку таблицами, ты скорее всего учился по очень старому учебнику? Не, я просто ничего не знаю, это остатки 10+ летней давности школьных знаний. >>443115 >Тебе надо изучить яваскрипт, DOM и jQuery наверно сначала. как иначе писать скрипт не понимая языка и используемых библиотек? Я про то, что мне непонятно само слово.
>>443136 >А какое свойство отвечает за выравнивание текста внутри блока? text-align может быть? Ну я это первым делом и попробовал, но раз уж я тут, значит это не помогло. Вот http://jsfiddle.net/k4qhtx4u/2/
>>443144 Спасибо, учту. >пробел около скобок при вызове функции принято не ставить Мне Eclipse так раскидывает, при определении пробелов нет, при вызове - есть. В настройках форматирования стоит PHP Conventions, стоит переключить на PSR-2?
> А как быть тогда с don't reapet yourself здесь? Здесь проблемы нет. Ты в абстрактном классе определяешь свойство, а в наследниках переопределяешь его с добавлением значения.
> Давай лучше будем отталкиваться от конкретной задачи. > И вообще, для решения этой задачи мне придется внести новую переменную $newSolary, что будет масло масляное - не одобряю. По моему либо ты либо я что-то не поняли. У работника есть свойства вроде ранг, базовая ставка и тд. Хранить вычисляемые из них свойства вроде зарплаты (newSolary) незачем так как их в любой момент можно посчитать с помощью метода. Соответственно то, что я предлагаю это упрощение, а не усложнение. Я предлагаю удалить свойства вроде newSolary и упростить код.
> $this->rang = $rang; > $this->newSolary = $this->calculateSolary(); Это нехороший код. Базовый класс ничего не знает о своих потомках и не должен обращаться к свойствам которых у него нету.
То есть ты должен объявить свойства вроде rang у базового класса.
Вот это вот свойство
> public $rang; не надо копипастить, нужно один раз его объявить на базовом классе.
Далее, ты зачем-то по несколько раз присваиваешь свойство в нескольких местах. Это запутывает код:
> Не уверен в необхадимости этой строки, ведь это свойство и так изменяется само по себе. > По сему назривают следующие вопросы: > 1. Необхадимо ли передача этого параметра? лучше вообще убрать свойство newSolary. Зачем его вообще хранить в объекте? Используй обычную переменную.
> 2. Будет ли правильнее создание заместо этого параметра создать обычную переменную внутри функции и далее, её уже передавать? думаю, да.
> public function calculateSolary() { > $this->newSolary = $this->newSolary + ($this->newSolary x 0.50);
Это неудачно сделанная функция. Если ее вызвать несколько раз подряд, то зарплата вырастет в несколько раз. Такого не должно быть. Такие функции это как мины на которые легко может наступить любой программист. Ведь он ожидает что функция работает правильно сколько бы раз ее не вызывали.
Потому я тебе советую удалить это свойство newSolary и проблема исчезнет сама собой.
> public function __construct() { > $this->addManagersToDepartment(); Это не очень логично: почему департамент при создании добавляет сам в себя работников? лучше сделать, чтобы создавался пустой департамент и в него поле этого можно было добавлять работников.
Ты не должен делать нелогичные вещи только потому, что в задаче «этого не требуется». Да, в задаче не требуется создавать пустой департамент или менять ранг работника, но правильно написанный ООП код позволяет это сделать без изменений. А если не позволяет то скорее всего с кодом проблемы.
Хорошо написанный класс работника предполагает что мы можем создать работника, задавать ему любые разумные значения свойств (в идеальном коде мы не можем обращаться к свойствам напрямую, а только через методы которые выкинут исключение при попытке задать неправильный ранг например) и получать информацию например о выпитом кофе или выплаченной зарплате.
Хорошо написанный класс департамента позволяет создать департамент, добавить в него любое количество работников, назначить босса (в идеале при назначении нового босса старый должен переставать им быть) и посчитать общий расход кофе или число произведенных страниц.
Мне кажется, по этой причине лучше добавлять работников снаружи. Ну и убрать лишние свойства вроде public $expenses = array(); так как эту информацию всегда можно посчитать и незачем ее хранить.
Насчет департаментов, можно не делать классы для каждого департамента, а просто сделать один класс департамента. Они в принципе различаются только названием.
Далее, тут ошибка:
> $calculateManagersNumber = count($this->employees[$this->nameOfDepartment]['Managers']); > $calculateMarketersNumber = count($this->employees[$this->nameOfDepartment]['Marketers']); У тебя базовый класс департамента откуда-то знает какие именно типы работников существуют. Это значит что если мы захотим добавить 5-ю профессию, мы должны будем переписать весь код. Это нехорошо. Надо чтобы для добавления новой ппрофессии достаточно было сделать 2 вещи:
- добавить новый класс професссии - создать объекты этого класса (работников) и добавить в департамент
При этом код класса Департамент менять не требуется. В этом и преимущество ООП, что мы разбиваем код на независимые классы и нам не надо весь его переписывать при любом изменении. У тебя пока код не соответствует этому критерию, надо чтобы соответствовал.
Если тебе сложно сразу понять как надо сделать, давай ты напишешь что-то вроде схемы, какие классы, свойства и методы ты хочешь сделать, а я скажу правильно ли все или что-то надо исправить. Или можешь сразу код менять, если хочешь.
Аналогично, в депараменте не может быть методов вроде addMarketersToDepartment так как он не знает какие вообще профессии существуют. Он знает что есть базовый класс Employee и этого знания достаточно. И мы можем добавлять любое число профессий не меняя ни строчки кода в Департаменте.
> $this->employees[$this->nameOfDepartment]['Leader'][] Тут тоже усложнение. Зачем городить трехмерный массив? Сделай свойство employees которое будет массивом объектов, и свойство leader которое хранит босса. Этого достаточно.
Если тебе что-то неясно или у тебя есть своя точка зрения, напиши, обсудим.
> А что делать если мы решили что искусственный интеллект справляется лучше чем "работник"? Сделаем класс class AI extends Employee и у него в методе getSalary() напишем return 0 (денег то он не просит).
> считаю количество строк, делю их на желаемое количество строк на одной странице ну так это всего 2 строки. Вообще альтернативный способ есть: можно создать объект для управления постраничной навигацией (Pagination). Ты при создании даешь ему число записей, число записей на одной странице, номер страницы, шаблон ссылки. а он рассчитывает число страниц, генерирует ссылки и все прочее.
> Я про то, что мне непонятно само слово. Ну ок > инлайн до добра не доводит. Имеется в виду inline обработчик события, заданный с помощью аттрибута onXXX у тега.
> Юзай жикверя, jQuery — библиотека для работы с DOM. Юзай= используй (use)
А может ли быть такое что у тебя на компьютере несколько php.ini и ты включил расширение не в том файле? Увидеть исползуемый файл можно выведя phpinfo(), там написано где именно лежит php.ini
Это не помогло потому что у тебя ширина флоат блока равна ширине текста в нем и от text align ничего не зависит. Можно сделать чтобы блок был фиксированной ширины, например занимал по ширине все поле и тогда текст будет прижиматься вправо.
Еще тут можно использовать position absolute + хитрую комбинацию right и margin-right чтобы вынести блок влево и прижать его к правой кроме поля. Но я не уверен, на одной ли высоте с текстом он будет.
Я еще поясню. Это задача для изучения ООП и недостаточно, чтобы она выводила правильный результат. Это вообще тут второстепенно. Надо, чтобы код соответствовал принципам ООП. Ты можешь спросить, какие именно принципы? Ну есть такая аббревиатура SOLID например:
Начинающему может быть трудно понять (тем более что в статье в википедии нет объяснений), но например такого что базовый класс знает какие у него будут наследники, не должно быть. Это противоречит принципу «открытости для расширения»: если у тебя прописано в коде ровно 4 профессии, мы не можем добывлять новые не переделывая весь код. А правильно написанный департамент не должен знать, сколько существует профессий, он просто принимает любые объекты унаследованные от Employee.
Также, не стоит заводить избытоные свойства вроде newSalary. Оно избыточное так как его всего можно посчитать из имеющихся данных, а если мы его храним то мы вынуждены как-то реализовать код для пересчета зарплаты при изменении ранга. В реальных программах у объекта может быть 20 свойств и если у тебя будут такие сложные зависимости, ты запутаешься в своем же коде в итоге. А я пытаюсь от этого предостеречь.
Опчик ты тут? Тупой вопрос, смотри, ты писал: >>443115 >Если есть несколько элементов с одним именем то в >f.elements.name >будет массив этих элементов Какой тип переменных у этого массива? А то в яве для for each надо указывать тип.
Кстати, по поводу SOLID, нашел такую ссылку: http://blog.byndyu.ru/2009/10/solid.html — можешь почитать, если интересно, но возможно что-то будет сложно понять, так как это все же материал рассчитанный на более опытных программистов.
>>443393 И сразу вопрос, вот у меня допустим есть Index.html где осуществляется ввод данных и передается дальше через форму в скрипт который выше и на выходе допустим я получаю массив трех числе, как передать этот массив другому скрипту который бы осуществлял бы создание страницы вывода данных на экран? Не лепить же это под скриптом обработчика.
>>443391 Я еще больший лошара, чем думал - стандартный required не работает в IE, лол. В принципе, проверок заполнения форм в инете много, но я пока не нашел ни одну, нормально работающую с радиобатонами.
>>443338 > $this->rang = $rang; > $this->newSolary = $this->calculateSolary( ); >Это нехороший код. Базовый класс ничего не знает о своих потомках и не должен обращаться к свойствам которых у него нету.
>То есть ты должен объявить свойства вроде rang у базового класса.
>Вот это вот свойство
> public $rang; >не надо копипастить, нужно один раз его объявить на базовом классе.
Ты говорил что нельзя в абстрактном классе определять параметры, и вообще даже идоне мне об сказал >>442511 >Нет. Абстрактным может быть класс (это значит что нельзя создать объект такого класса) либо метод (это метод без тела, который обязаны реализовать наследники класса).
>Потому я тебе советую удалить это свойство newSolary и проблема исчезнет сама собой. Я правильно понимаю, что тогда вычисленная зарплата будет храниться в $solary? Я немного запутался.
>Если тебе сложно сразу понять как надо сделать, давай ты напишешь что-то вроде схемы, какие классы, свойства и методы ты хочешь сделать, а я скажу правильно ли все или что-то надо исправить. Или можешь сразу код менять, если хочешь. Я добавлю в класс конкретной профессией параметр держащий в себе название этой профессии. Далее, мне на ум приходит мысль о том, что можно не копипастить код, а иметь всего один класс Employee, и при его создании задавать все свойства (название профессии, начальная ставка, кофе, количество документов, ранг и является ли он лидером), точно также можно поступить и с департаментами . При таком подходе становиться необходимым сделать не слабый такой рефакторинг, а именно: 1. В классе конкретного департамента необходимо избавиться от параметров с количеством сотрудников, оставить лишь один параметр с массивом, который будет держать всех сотрудников, а добавлять их мы уже будем где-нибудь снаружи, как это и должно быть на самом деле. >лучше сделать, чтобы создавался пустой департамент и в него поле этого можно было добавлять работников. >лучше добавлять работников снаружи.
2. Подружить все это дело с методами расчетов\добавления сотрудника.
>Если тебе что-то неясно или у тебя есть своя точка зрения, напиши, обсудим. Нет, по большему счету мне все ясно пока, за исключением пару вещей: С новым подходом пропадает необходимость в абстрактных классах т.к. все можно сделать в одних и тех же классах (Employee и Department). Хотелось бы услышать что ты думаешь по этому поводу. Я лично думаю, что абстрактные классы не нужны здесь.
>в идеале при назначении нового босса старый должен переставать им быть Пока не знаю как это сделать, но хочу это самостоятельно придумать, но это уже после. Так что попрошу тебя, мне пока не говорить об этом. =^_^=
>>438085 посоны у меня почему-то на страничке два скролла, я все ксс файлы перелопатил, если ставлю оверфлоу hidden, то оба исчезают. как оставить один??
Вообще, мне кажется ты мыслишь в правильном направлении.
> Ты говорил что нельзя в абстрактном классе определять параметры, Абстрактные нельзя. А обычные можно.
> Я правильно понимаю, что тогда вычисленная зарплата будет храниться в $solary? Я немного запутался. куда ты ее положишь, там она и будет храниться. А зачем ее вообще хранить? Можно сразу например выводить на экран.
> Далее, мне на ум приходит мысль о том, что можно не копипастить код, а иметь всего один класс Employee Копипастить код конечно плохая идея.
> С новым подходом пропадает необходимость в абстрактных классах т.к. все можно сделать в одних и тех же классах (Employee и Department). Хотелось бы услышать что ты думаешь по этому поводу. Я лично думаю, что абстрактные классы не нужны здесь. Отдельные классы для профессий удобны тем что легко добавлять новые профессии. В принципе можно и одним классом но там у тебя будет такой некрасивый огромный свич:
switch ($position) { case self::POSITION_ENGINEER: ... ...
Неудачное название getDmg. Обычно так называют функции которые ничего не меняют, а просто возвращают какое-то значение. А тут ровно наоборот — она не возвращает, а принимает урон.
> return 1; // вернет 1 если первый убил второго героя Вместо комментариев надо использовать говорящие константы вроде Game::FIRST_HERO_WINS
Но вообще, конечно код стал намного аккуратнее, и по моему, чуть компактнее.
> sequence(start = 0, step = 1) { Это конечно удобно, параметры по умолчанию, но это то ли ES6 то ли ES5 который не везде работает. Это полезно, его изучать, но попробуй решить эту задачу в рамках ES3.
>>443683 >Попробуй сам написать например Да я сделал уже, но только для радиобатонов и там надо жестко задавать число батонов, что коряво, как мне кажется.
>>442509 >Все зависит от компании. Куда-то возьмут с первой, куда-то потребуют минимум 3 решить.
Т.е. если я довольно быстро решил два задания, можно попробовать походить по собеседованиям, а что им говорить/писать? показывать гитхаб и говорить что я быстро учусь?
>Отдельные классы для профессий удобны тем что легко добавлять новые профессии. В принципе можно и одним классом но там у тебя будет такой некрасивый огромный свич: > >switch ($position) { >case self::POSITION_ENGINEER: ... >... Эм, все красивенько получилось - нету никаких огромных свичей ^_^
>>438085 Анончики, нужна ваша помощь, есть код и есть неработающая его часть. Суть в том что желтый блок должен растягиваться, но в отличии от пхпдисайнджера локалхост растягивать её не хочет. Поясните нубу в чем дело?
>>444012 Во-первых, это не ответ. Во-вторых, в твоем примере ты задаешь одним и тем же блокам флоат и инлайн-блок. Зачем? Убери из сайдбаров инлайн блоки, задай левому бару и #контент флоат лефт, правому бару флоат райт. А потом выкинь эту странную софтину, который ты пользуешься, и скачай sublime/phpstorm
И у меня для тебя есть кое-что еще. Ты тут много со мной спорил, мол зачем писать универсальный код, если у нас есть конкретная задача. Действительно, разумное возражение. Давай тогда дополним условия задачи таким образом:
----- ..... Задание: напиши программу для учета расходов и результатов работы всего дружного коддектива компании «Вектор».
Пока ты решал задачу по выводу отчета о сотрудниках и департаментах, разразился мировой экономический кризис. Доходы компании начали снижаться, и совет директоров поставил перед руководством задачу принять меры. Менеджеры 3-го ранга, блестящие выпускники топовых экономических вузов столицы, быстро смогли разработать три альтернативных антикризисных решения:
1. Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга. Если инженер является боссом, вместо него надо уволить другого инженера, не босса.
2. Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков, а количество выпиваемого им кофе с 50 до 75 литров. В тех департаментах, где руководитель не является аналитиком, заменить его на аналитика самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)
3. В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
Совет директоров в затруднении: какой путь выбрать? Помоги им с этим, распечатав прогноз по потреблению и расходам (аналогичный тому что требуется в задаче) после принятия каждой из мер.
-----
Я тебе советую сделать это задание, так как оно поможет лучше разбираться в ООП-подходе. По моим прикидкам при правильном коде это потребует дописать строк 40-50, что на мой взгляд немного. Сразу предупрежу, что антикризисный код вроде «уволить 30% сотрудников» не должен быть в классе Департамент (так как бороться с кризисом задача руководства компании, а не департамента), но ты можешь написать в департаменте универсальные методы вроде «уволить указанных сотрудников» или «выбрать N% сотрудников определенного типа».
Также, тебе скорее всего понадобится метод клонирования компании, чтобы сделать несколько копий компании и принять в каждой из них нужные меры.
> //Я помню, что ты был против этой переменной, но с ней просто будет проще удобней посчитать средние значение. Сделай замечание если что-то не так. Получилась плоха функция, потому что непонятно, что вернет результат вызова calculateAvargeValue? Среднюю зарплату? Среднее потребление кофе? Упадет с ошибкой? Такого неоднозначного кода быть не должно. Ты должен либо сделать конкретные методы (посчитать среднюю зарплату, посчитать среднее потребление кофе и производство страниц), либо ни одного. По моему, проще не делать ни одного (так как среднее там считается сложением чисел по департаментам и делением на число департаментов).
> calculateDepartmentExpensesCoffeAndDocuemnt Лучше сделать 3 метода, чтобы они возвращали конкретное число. Сам сравни:
echo $department->getTotalSalary(); // просто и понятно
и
list ($totalSalary, $totalCofee, $totalPages) = $department->calculateDepartmentExpensesCoffeAndDocuemnt();
echo $totalSalary; // неужели это удобнее, писать 2 строки вместо одной?
но это очень плохой код так как непонятно что такое 0?
Потому я советую сделать 3 отдельных функции с нормальными именами. Я так понимаю, ты не хотел писать цикл 3 раза, но это не тот случай когда такая оптимизация оправдана.
> Я сомневюась в необхадимости этой функции, ведь можно зделать тоже самое снаружи класса: Конечно создавать работников надо снаружи. Департамет только принимает их на работу, а не создает. И разумеется такой код никуда не годится:
$department->employees[] = new Employee(...);
гораздо лучше закрыть доступ к массиву снаружи через метод:
> я использую такое же имя переменной как и у свойства. Не приведт ли это к путанице? Нет, так как переменная и свойство хранят одно и тоже, логично их назвать одинаково. Перепутать их не получится из-за приставки $this->
>>444003 >А где код который напечатает таблицу? Сейчас напишу. Хотел чтобы ты проверил сначала, вдруг что-то не правило будет. А то так выведу таблицу как надо, а код будет неправильным. Обидно будет.
>>444020 Я спорю потому что не понимаю твоего подхода. Универсальность понятие относительное, и в конечном итоге гонка за ней приведет в тупик. С другой стороны, решение конкретной задачи экономит силы на том что не нужно придумывать все возможные нюансы. Твоя задача должна дать понимание о том как использовать ООП. Согласись, что я на практике почти решил её - она бы справилась с выводом таблицы, но на деле задача оказалось не универсальной, не смотря на то что у задачи были другие конкретные цели. И поэтому я не понимаю: почему от меня требуется универсальный код, если условия задачи сами по себе не универсальны.
Я не хочу жаловаться, так как ты уже бесконечно много делаешь для меня и для всех, и вообще в целом. Меня просто демотивирует это непонимание.
>>444020 >Задание: напиши программу для учета расходов и результатов работы всего дружного коддектива компании «Вектор». =__________________________________________________________________= Может ты сразу дашь задачу написать ИИ?
> $manager->multiple(13,1), Это не очень удачная идея, делать одного менеджера с зарплатой как у 13. Надо делать 13 объектов-менеджеров. Иначе, посмотри вот это дополнение к задаче: >>444020 — как ты будешь такое делать?
То есть удобнее и проще и правильнее сделать что один менеджер = 1 объект, 13 менеджеров = 13 объектов.
> $total+=$employee[3]; Это тоже плохая идея. Зачем хранить массив (в котром непонятно что значат ключи 0, 1, 2, 3) когда можно в Департаменте хранить массив объектов-сотрудников.
> public function rank($rank) Функции надо называть осмысленно, в стиле сделайЧтоТо,например getIncomeForRank(). Это же отноcится и к multiple.
Добавлять сотрудников в департемент лучше через метод вроде
$dep->addEmployee($employee)
или
$dep->addEmployees(array($e1, $e2, $e3));
> return $total = [$inc,$cof,$pap,$quan]; Не объединяй в одну строчку присваивание переменной значения и return. Пиши в 2 строки. Хотя тут можно вообще без переменной total обойтись и сразу возвращать массив.
> for($i = 0; $i < $length - $cl; $i++){ > $text = " ".$text; Есть str_repeat, цикл не нужен
Не выводится среднее по департаментам и «всего».
Ну и чтобы ты лучше понял принципы и преимущества ООП (и чтобы заставить тебя сделать код правильным), сделай дополнительно задание отсюда: >>444020 про антикризисные меры.
Для inline-block нельзя задать ширину в стиле «100% - 200px» потому он тут не годится для реализации колонок. Годится например float для колонок + обычный блок с margin-left и right для средней части. Почитай это например: http://softwaremaniacs.org/blog/2005/12/01/css-layout-float/
Ну и высоту ты зря фиксированную задаешь, это неудобно.
Насчет прибитого к низу футера, делается отнсительно просто. Обертываешь все в wrapper, ставишь ему min-height 100% (чтобы это заработало, надо на body/html разумеется поставить height 100%), а под wrapper ставишь футер и делаешь ему margin-top: -100px где 100px это высота футера. Это древний способ, может сейчас что получше придумали, но я не уверен.
Также можно попытаться сделать таблицу из 2 ячеек (за счет display: table) но там много подвохов.
Также, у нас есть хорошие задачи для изучения CSS и способов позиционирования элементов (в ОП посте), советую их решить если чувствуешь что есть проблемы в знаниях. А я проверю и дам советы.
Я не против того, что ты сомневаешься в чем-то или споришь. Но я все же должен объяснить тебе суть ООП, потому сделай дополнительное задание про антикризисные меры. С ним тебе придется чуть переделать свой код и сделать его более универсальным. Тебе надо предусмотреть изменение рангов, смену руководителя департамента, изменение базовой ставки.
> И поэтому я не понимаю: почему от меня требуется универсальный код, если условия задачи сами по себе не универсальны. Я придумал дополнительное задание, чтобы гнаться не за абстрактной целью, а за конкретной.
> Меня просто демотивирует это непонимание. Есть что-то вроде общепринятого подхода. Ну например если я вижу у работника свойство rank (тем более публично доступное) я ожидаю, что его можно менять (и получить при этом новую величину зарплаты). Логично? Зачем иначе делать это свойство общедоступным?
Если я вижу у департамента руководителя, я ожидаю что его можно поменять. А это сделать нельзя. Неудобно. Чтобы приучить тебя делать чуть более универсальные и соответствующие ожиданиям классы, я придумал дополнительное задание.
Процитированная строчка вообще-то из учебника. А дальше небольшое дополнение. В чем проблема его решить? По моему так оно решается элементарно:
Делаем 3 клона компании. В первом увольняем инженеров, во втором повышаем аналитиков, в третьем повышаем ранг менеджерам. После чего для каждой компании выводим таблицу (функция вывода ведь у тебя уже есть?)
Соответственно это надо строк 30-50 дописать. Совсем немного, согласись? Если твой код удобный и универсальный он легко позволит это сделать.
Насчет клонов: в php есть оператор clone для того чтобы склонировать объект (обрати внимание, если ты клонируешь департамент, работники не клонируются по умолчанию: новый департамент будет хранить ссылки на тех же работников. То есть клонирование у нас неглубокое и клонирует только один объект, а не его содержимое. Ты должен явно написать метод клонирующий массив работников).
Также, советую тебе сделать в департаметне метод вида «выбрать N% работников нижних или верхних рангов определенного типа». C ним тебе легко будет выбрать работников и сделать с ними нужные изменения.
Ну и не забудь предумотреть метод для увольнения и метод для смены руководителя.
Спасибо что научил меня таким вот фокусам: <?=$variable;?> С Sublime Text я себя чувствую джедаем кода прям!!! Ну хотя бы не джедаем, но как минимум подаваном точно!
Дальше буду думать над следующем заданием что ты мне дал.
>>444020 >Получилась плоха функция, потому что непонятно, что вернет результат вызова calculateAvargeValue? Среднюю зарплату? Среднее потребление кофе? Упадет с ошибкой? Такого неоднозначного кода быть не должно. Ты должен либо сделать конкретные методы (посчитать среднюю зарплату, посчитать среднее потребление кофе и производство страниц), либо ни одного. По моему, проще не делать ни одного (так как среднее там считается сложением чисел по департаментам и делением на число департаментов). Не могу понять что не так с функцией. У тебя в задаче есть пункт: Посчитать средний расход тугриков на одну страницу. Я её немного переделал, но принципиальной разницы не увидел. Тебе название функции не нравиться?
>Твой вариант подходит, но ты знаешь что в php уже есть функция-автозагрузчик? Достаточно добавить папку Classes в include_path: Совсем не понял как этим пользоваться, но тут я уже сам ленюсь изучить. Я обязательно с этим разберусь самостоятельно, только чуть позже, потому что судя по всему это тоже какой-то крутой джедайский фокус.
Так как массив может быть пуст, и вообще непонятно что он содержит. Раз ты убрал этот массив то претензий больше нет (хотя функцию я бы переименовал в getPagesPerTugrik()).
> Совсем не понял как этим пользоваться, но тут я уже сам ленюсь изучить. Я обязательно с этим разберусь самостоятельно, только чуть позже, потому что судя по всему это тоже какой-то крутой джедайский фокус. Может оно тебе и не понадобится. Если будешь делать задание на регистрацию студентов, я посоветую использовать композер и там не нужен автозагрузчик.
> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> / в конце тега ставится в XML, XHTML но не в HTML. Ну и в html5 испльзуют более короткую форму: http://htmlbook.ru/html/meta/charset
>>444020 >Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга. Если инженер является боссом, вместо него надо уволить другого инженера, не босса. Здесь в класс Депортамента я добавлю метод подсчета количества сотрудников определенного типа. Далее, я создам класс Кризис в котором буду находить сотрудников которых необходимо уволить, и с помощью нового метода в Депортаменте увольнять их. Единственное что я не могу понять это как проверить всех сотрудников в каждом департаменте? Есть идея создать класс который будет хранить в массиве каждого сотрудника и вызываться каждый раз при создании нового сотрудника, но я сомниваюсь в её правильности.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Предыдущий тред был тут:
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в день, не жди его, решай задачки дальше.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Учебник дает основы языка PHP, но чтобы делать сайты, этого недостаточно. Если ты его прошел, то надо переходить в более серьезным задачкам, которые научат тебя как выдавать страницы в браузер, работе с таблицами в БД, работе с формами, MVC.
- Простая, но полезная задача сделать список студентов: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Yii2: https://gist.github.com/codedokode/8733007
- Если ты все их решил, переходи к Symfony 2/Doctrine 2
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP на сервере для отдачи странички в браузер: https://php.net/manual/ru/tutorial.php Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что, задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.github.io/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git:
Нужен ли ООП, фреймворки, MVC? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.net/45000175
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Где искать работу и заказы — hh.ru, geekjob.ru, brainstorage.me, fl.ru, odesk.com. Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.