24 декабря Архивач восстановлен после серьёзной аварии. К сожалению, значительная часть сохранённых изображений и видео была потеряна. Подробности случившегося. Мы призываем всех неравнодушных помочь нам с восстановлением утраченного контента!
Добро пожаловать в наш уютный тред. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме. ОПу ведь все это читать придется.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Еще предыдущие треды ищутся в гугле по словам "клуб php" или в архиваче. Еще есть такой архив тредов: http://phpclub.rf.gd/
Мейлач лежит? Есть запасной тред: доброчан-орг/s/res/23225.xhtml#i46467
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.
Платиновые вопросы
- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко. - Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета) - Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery - Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/. - Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев - Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm - Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию. - Что самое главное для программиста? Умение аккуратно оформлять код. - ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет. - Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults() - Название функции начинается с глагола, в стиле «сделайЧтоТо» - не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там - в именах классов используется CamelCase, первая буква большая, «_» может использоваться - мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек - мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?» Не годится: «В гугле забанили?» Не годится: «Твой код плохой» Хорошо: «Вот, как можно улучшить этот код: ...» Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского или русского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде» Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)» Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Привет, доброанон, шапку прочитал. Будет ли толк на пути становления веб-макакойпрограммистом в самом начале изучать C и идти по Гарвардским курсам CS50?
Работаю пхп жс скл за 40к, ООП не использую, знаю тоже мало, только процедурка только хардкор, посоветуйте курсы для повышения квалификации а не для изучения с нуля
>>988893 >изучать C эта дорога точно не ведет в веб. ЦС50 тоже, это достаточно общий курс по компутер-саенс, если новичок, то будет довольно интересно, может быть и передумаешь вкатываться в веб.
Поясните за Антипаттерн "Толстый контроллер", разве Presenter в MVP и ViewModel в MVVM не являются примером растолстевших контроллеров, переименованных пиар отделом в попытке скрыть позор?
>>988913 Ну по идее, толстым у тебя контроллер получается если ты слишком много всяких операций проводишь в контроллере. В таком случае подумай над тем, что бы распихать все эти операции по отдельным ф-ям/методам. В идеале у тебя контроллер должен только принимать данные от пользователя(http запросы, куки, сессии, формочки ну ты понел) и передавать их в модель с минимальной обработкой, ну там еще валидация всякая, ну и принимать от модели и отдавать вьюшке, как-то так.
>>988997 Делай по книге на юкозе из шапки. >>988868 (OP) Только вкатываюсь, по образованию - гуманитарий. Как же это охуенно сделать свой рандомнамбер генератор (первое задание с кубиком).
>>988980 Мельком поглядел. У тебя в классе с запросами в базу, много методов с почти похожими селектами. Можно сделать один метод, а запрос сделать сделать составным. К примеру, если в качестве условия ты ничего не передал, то строка "WHERE id = ?" не будет подставляться в запрос. Класс будет больше, и сложнее. Но, если грамотно сделать, то у тебя получится один класс, который делает одну функцию - делает селект в базу.
>>989133 Еще небольшой совет дам, хотя это вкусовщина. Чтобы избежать высокого уровня вложенности, вроде как в методе match роутера, можно использовать условия от обратного. То есть не "if (azaza) { чтото делаем }", а "if (!azaza) { return; } чтото делаем" как пример.
Привет, ньюфаг в треде, есть вопрос. PHP изучаю пока в приложении к WP, хочу иметь возможность делать в нем что-то кастомное и т.д. Собственно сейчас пилю сайт\тему, в которой, например, есть кастомный слайдер в шапке с определенным текстом, изображениями — задача сделать их редактируемымыми из админки. Как делать страницу в админке знаю. Собственно вопрос — как это лучше реализовать, ну или в какую хотя бы сторону копать? tx
>>988980 1. Хорошо что ты задумываешься о контейнере зависимостей, однако вряд ли ты до конца понимаешь как им пользоваться. Например, ты делаешь отдельный класс для соединения с БД, хотя по логике очевидно что это тоже зависимость. Сам контейнер - имхо далеко не лучшая идея возвращать зависимость как элемент массива, лучше сам объект и возвращай. Алсо, советую почитать про интерфейс PSR - 11 и посмотреть как устроен контейнер Pimple. 2. По части контроллеров пока заметил только одно грубое нарушение - ты не экранируешь данные. Нельзя просто принимать данные в виде $_GET["something"], это серьезная уязвимость. Почитай про XSS, ОП-а где-то было об этом. 3. В индексном файле советую автозагрузку и прочее распихать по отдельным файлам, так будет удобней редактировать. 4. В моделях ты тоже наговнокодил. Ты не правильно назвал класс для работы с таблицей студентов, из название выходит что это у тебя модель сущности студента, а по факту это шлюз к таблице, переименуй на StudentsTableGateaway. Исходя из того что я про контейнер написал - надеюсь тебе понятно почему твой класс Model не нужен. То как ты выбираешь студентов из базы - это вообще путь в никуда. Читай больше про работу с PDO и выбирай одним запросом всех студентов в специально созданный класс-модель с соответсвующими полями. И это, я так и не понял зачем ты прямо так делаешь пагинацию. 5. Дальше не читал, еще добавлю что стоит все таки комментировать свой код если ты собираешься его кому-то показывать, я вот на работе сижу и особо времени разбирать твой код нет. Прокоментируй и вечером еще посмотрю.
Данные в контроллере экранировать не требуется. И если экранировать, то для чего? для вывода? Для использования в SQL запросе? Экранировать данные надо там, где они используются.
Ты по моему плохо понимаешь, что такое экранирование. Ты наверно начитался плохих учебников, где учат, что данные от пользователя "опасные" и их надо "очистить" (пропустить через несколько случайно выбранных функций), чтобы они стали "безопасными" (ага, святой водой полить).
Но это неправильно. Данные сами по себе не "опасные" и их нельзя "очистить". Уязвимости возникают при неправильном использовании данных - например вставке их напрямую в SQL-запрос вместо использования плейсхолдеров. Или при выводе данных в HTML-коде без применения htmlspecialchars. Или при попытке подключить файл, имя которого задается пользователем.
Ну и я не понимаю, где тут логика - данные используются в одном месте кода, а экранируются где-то далеко в другом. А как тогда проверить, что они надежно экранированы? Изучать весь код и тщательно проверять, какая переменная куда передается? И это ведь не защитит от того, что завтра кто-то допишет вызов функции, передав ей неэкранированные данные.
>>989202 >Ты по моему плохо понимаешь, что такое экранирование. Ты наверно начитался плохих учебников, где учат, что данные от пользователя "опасные" и их надо "очистить" (пропустить через несколько случайно выбранных функций), чтобы они стали "безопасными" (ага, святой водой полить). Может быть, в данном случае я просто имел ввиду очистить от html-тегов, лол.
>>989205 >И это ведь не защитит от того, что завтра кто-то допишет вызов функции, передав ей неэкранированные данные. Тут как бы логика в том, что если у тебя одна точка приема данных от пользователя, т.е. контроллер, то лучше бы там хотя бы от тегов почистить, а то мало ли макак которая модуль пишет забудет это сделать.
Тут нет логики. Почему очищать именно от HTML-тегов (то есть по сути угловых скобок)? А что насчет других символов, вроде точек, запятых, вертикальных палочек, вьетнамской письменности и десятков других символов Юникода?
Ты невнимательно прочел мой пост. Я написал, что данные не могут быть "опасными" сами по себе и их "почистить" нельзя. Можно только создать видимость безопасности таким образом.
>>989210 >Тут нет логики. Почему очищать именно от HTML-тегов Самый общий случай же. В БД сомнительно что бы кто-то сейчас вставлял данные без подготовленных запросов
>>989112 Понял, спасибо. Сейчас попробую переделать. >>989133 >Получение параметров запроса в модели? Да, совсем не заметил. То есть обязательно надо передавать параметры запроса из контроллера в модель? >>989177 >Сам контейнер - имхо далеко не лучшая идея возвращать зависимость как элемент массива, лучше сам объект и возвращай. Так я же вроде объекты и возвращаю. >return new \src\models\StudentsModel($container['db']); Или я тебя не так понял? >посмотреть как устроен контейнер Pimple. Я как раз с него и пытался делать. >По части контроллеров пока заметил только одно грубое нарушение - ты не экранируешь данные. Нельзя просто принимать данные в виде $_GET["something"], это серьезная уязвимость. Почитай про XSS Но ведь потом я эти данные вывожу через htmlspecialchars в шаблоне. >Ты не правильно назвал класс для работы с таблицей студентов Да, с моделью все совсем плохо вышло. Увидел ошибки, спасибо. Только я сначала хотел через сущности сделать, но не понял, как вывести, например, список всех студентов. Там же под каждую запись в таблице отдельный класс нужен.
>>989284 Отдельный класс не под каждую запись в табилце, а под каждую таблицу ты хотел сказать. Ну так со шлюхом так же. А вот инстансы класса под каждую запись, это да в AR. Например список записей таблицы должен быть представлен в виде коллекции объектов AR. А вообще AR тема не сложная.
>>989284 >Так я же вроде объекты и возвращаю. Я посмотрел, ты там юзаешь ArrayAcces, тогда все норм должно быть. > Там же под каждую запись в таблице отдельный объект нужен Так и должно быть.
Поставили такую задачку. Есть база данных человеков (сорт оф кадровое агентство, человеки - соискатели) с адресами их проживания. Для этого дела есть самописная админка, с которой работают сотрудники агентства. Ситуация - поступает заявка от работодателя, в которой есть его адрес. И нужно, чтобы сразу были видны ближайшие соискатели в некотором радиусе. Как лучше это реализовать? Вкатываться а япи кких-нибудь яндекс карт?
>>989357 При ничье выбивает это: Игрок бросает кость. Выпало: 6. Игрок бросает кость. Выпало: 3. Компьютер бросает кость. Выпало: 5. Компьютер бросает кость. Выпало: 4. Сумма очков игрока: 9. Сумма очков компьютера: 9. Очки игрока и компьютера равны. Счет - 9.
>>989295 >А вообще AR тема не сложная. В теории не сложная, а на практике реализовать ее новичку довольно непросто. Для меня сразу пару непонятных моментов появилось по теме active record, которые я смогу понять только на реальных примерах. Я вот сел сейчас переделывать и понял, что лучше сначала попробовать изучить пару фреймворков и сделать на них 2-3 сайта, а уже потом свои ошибки будут очевидны.
Что блядь за задание с "Напиши программу, выводящую таблицу умножения чисел от 1 до N на самих себя, используя цикл. Программа должна вывести примерно такой результат:
1×1 = 1 2×2 = 4 ... 9×9 = 81 Ты можешь взять пример кода с картинки ниже за основу." Хули оно такое сложное?
>>989419 ideone.com/LDqB9c "произведение", я ебу что это? Прохожу по гайду из шапки >Требуемые знания: умение включать компьютер и пользоваться браузером. Ноутбук/айпад/планшет/смартфон тоже подходят, если в них есть интернет.
>>989444 Где ты оправдания видишь то? Я лишь посетовал на то, что подсказка была не особо ЛЕГИТИМНА, и несла в себе ошибку решил за тебя, впрочем, ничего нового. Единственная помощь, полученная от подсказки - использовать переменную в к-ве производной. И решение мне не нужно было, мне нужен был лишь толчек в нужном направлении. Решения оставьте для школьников, пусть они радуются что их проблему кто-то там решил, потом дойдет что важность знания - научиться решать эту проблему, а не готовое решение.
>>989450 Никто ничего не критиковал, просто показали как можно сделать лучше, значит увидели потенциал, иначе не тратили бы время на анализ и на стену текста
>>989564 Я когда сам его решать пытался, сделал все тоже самое практически, только буквы по другому брал. Думал, что нужно взять с первого символа по середину $halfLength и с последнего до середины и сравнить их. Но в итоге хуйня выходила. Я надеюсь это была одна из самых сложных задач в пхп ?
>>989627 Даже вчитываться не могу. У тебя есть сумма и есть год - все это считай за один ход цикла. Больше миллиона - стоп. Потом к 16 прибавь года получившиеся и усе. >>989626 За щооо !?
В цикле фор, соответственно с гайдами и прочей хуйней. Start - со скольки стартует. Действие 1, выполняется разово. Начинается с 10000. Условие - пока startXperc не дойдут до миллиона. Действие2 - пока условие не выполнено - должен умножать стартовые 10к на 1.1. Но оно не хочет лупить. Что за хуйня?
>>989092 Скоро ты будешь рыдать. Говорю тебе как 33летний редактор в издательстве, который вот уже два года бьётся во всём этом. Но у меня мечта (одна из), к которой приближаюсь с каждым днём, - свой проект. Сейчас в нём треть частично реализована программистом за деньги, частично мной самим. Такое окрыляет, придаёт силы.
>>989652 Это пройдет за несколько лет работы и множество реализованных проектов, как своих, так и чужих. Вот не спеша для души поковырять код - это дело. А въебывать это, конечноо, изматывает даже в этом деле.
>>989653 Да, полностью согласен. Но имею в виду, что нужно очень хотеть научиться, без этого никак. Я вот только пару месяцев как не вижу фигу, когда смотрю в чужой код, начинаю довольно быстро соображать, что к чему. Практика, постепенное освоение, пропускание через себя всех задач - это всё нужно.
>>989663 В 2012-м изучил HTML+CSS на достаточном уровне, потом освоил Wordpress. Сделал с тех пор кучу сайтов, часть из которых продал, а часть по-прежнему приносит какую-то копейку на партнёрских программах. Так что именно в программирование не совсем с нуля вкатился, получается, общие представления имел.
>>989675 Пару братишек помню и старше меня, только потом отсеялись куда-то.
Ну а так можно ещё и в нашей уютной конфе сидеть: https://t.me/PHP_club (только я вряд ли на выходных смогу).
А мне вот 26. 5 лет опыта. Работаю одновременно над 4 проектами в данный момент. Очень многое на ноде параллельно с пхп, знакомые еще в питон пытаются утащить. Фронтенд - ангуляр/реакт/вуе, но это не то, чем нравится заниматься. Верстку только под антидепрессантами могу, уж слишком уныло. Так же в андроид хуярю, изичная тема, для расслабона самое оно. В целом ничего сложного на самом деле с бекендом, главное понимание, внимательность, аккуратность и терпение. Своих 3 заброшенных проекта, 1 сейчас в разработке затянувшейся. В данный момент допиливаю один из проектов на бету, чтобы хоть немного с чистой совестью потом поебланить (сроки уже на неделю всрал, заказчик ворчит). По деньгам выше среднего в моем городе, с фрилансом и подработками раза в 3 повыше наверно, но ничего заоблачного, черную икру не жру. Работу менять лень сейчас, сила привычки. Вордпрессы всякие даже не видел никогда, брезгую. Выговорился. >>989681 А че у вас в конфе интересного происходит?
>>989686 Конечно. Там есть опытные люди, ну и так своими силами что-то думаем обычно.
>>989698 Ну отлично же, если есть работа и возможность развиваться. В конфе есть Карасик, который с 1С перешёл сейчас для разнообразия на РНР, иногда бывает. В целом там у нас больше по существу разговоры, чем за жизнь, но никто не против и просто поболтать.
Еще один престарелый-вкатывальщик-вниманиеблядь пришел отметится. Через 2 месяца 27 годиков, автор дно-поделок https://github.com/grigoryMovchan и труднообучаемый.
Словил макконахи и опустились руки. Чем больше узнаю, тем больше себя чувствую на дне, но даже там слышу, как снизу стучат. Иногда думаю, что я создан только сидеть под деревом и созерцать, а не заниматься интеллектуальным трудом.
Хуй знает, может перерыв надо сделать и вообще к пеке не прикасаться месяц другой, хотя бы дома, ведь я на работе 8 часов за пекой, после неё все за пекой, заебался столько инфы через себя пропускать. Но с другой стороны, пока я отдыхаю - двадцатилетний делает то, что я за год не успеваю.
>>989740 Я вам прямо завидую. Вы вроде нуфаги, но вам норм, гитхабчиками светите. Я не нуфаг, но у меня на гитхабе такая параша, которую просто жалко выкидывать (архив кода мой по сути), что я его сам с дрожью открываю. Ну а про дно - границы познания это.
>>989745 Работаю на фулл-тайм работе за еду 5/2. Подумаю об этом, когда изучу пик, допилю AphorismCMS и еще какую-нибудь поделку, сделаю задачи из оппоста. Есть риск сдаться раньше. Считаю, что пока не выхожу на уровень джуна, к тому же живу мухосранске (Краснодар), пытаюсь копить деньги на перекат. Фриланс не потяну.
>>989749 О, я начинал читать эту книгу, но не осилил в итоге. Некоторые моменты показались слишком непонятными и оторванными от реальности (но я месяца два всего изучаю пхп, поэтому все дело во мне). >Считаю, что пока не выхожу на уровень джуна Но ты же отлично понимаешь, что уровень джуна у тебя уже давно есть. Зачем принижаешь себя?
>>989747 Вроде, тут только я один такой социоблядь, больше не видел чтобы кто-то светил. Да и у меня тоже это архив кода. Без гитхаба все превращается в свалку, которую только удалить хочется.
>>989751 >О, я начинал читать эту книгу, но не осилил в итоге. Так я её с января изучаю, по моему, и только 2/3 прошел. Очень медленно, прерываясь на свои поделки. Я до неё еще пытался вкатится в ООП и MVC. Каждый раз, когда возвращался к своим поделкам, то юзал что-то оттуда. Мне она дается тяжело, главу про шаблон Интерпретатор 10 раз перечитывал.
Возможно, мой уровень достаточен для двадцатилетнего джуна на третьем курсе, но не двадцатисемилетнего лба с заборостроительным дипломом.
>>989817 Условие цикла неверное, хотя тебе это пока не принципиально. Условие внутри цикла не верное, из-за него все и ломается. Почему то 3000 вместо 5000, 3% вместо 103%, да и вообще не то.
>>989954 Условие лучше. Еще раз объявляеть $leftToPay не нужно. Условие < 5000 должно быть внутри цикла, а не за ним. Само условие тоже поправить. Добавить внутрь логики. Если ты пошел путем $month*$monthlyPayment, то лучше это сразу в конец цикла пихать (перед бриком) с соответсвующей надбавкой, чем считать каждый раз.
Вывод окончательного результата можно сделать уже после цикла.
Компилятор тебе черным по белому написал, что ты использовал break вне цикла или свича, что должно было заставить тебя обратить внимании на его положение в коде. Учись слушать ошибки.
>>988870 >Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492 >PhpStorm — жми Ctrl+Alt+L Он переводит открывающую конструкцию скобку { после класса и функции на новую строку, а после условий не перевод. ЛИБО ПЕРЕВОДИТЬ, ЛИБО НЕТ. Нахуя совмещать?
Заебала блядь руснявая хуйня. НУ ЧЕ ОПЯТЬ? КОДИРОВОЧКА? Засунул Собакину в $_SESSIONS['last_name'], достал Собакину на другой странице $last_name = $_SESSIONS['last_name']. И ПОЛУЧИЛ ВОПРОСИКИ))) Я просто за сегодня порвался с таких нелепых проблем. Кругом выставил header("Content-Type: text/html; charset=utf-8"); Даже маме своей позонил и сказал: "ХЕАДЕР ЧАРСЕТ УТФ-8". Скачал нотепад, проверил BOM, НИГДЕ НЕТ ЕГО, НИ НА ОДНОЙ БЛЯДСКОЙ СТРАНИЦЕ. Пхп-сторм не даёт удалить BOM, потому что его НЕТ. СТАРТ
<?php session_start();
В самой первой строке, самого первого файла, фронт-котроллер, что бы ты не делал - всё начинается с него.
Ты успокойся и проверь, в какой кодировке сохранен файл с исходным кодом программы - должно быть utf-8 без BOM.
И при чем тут русский язык? utf-8 он не для русского языка придуман, а вообще для всех языков. Это ненормально в наше время ограничивать себя латинницей, когда есть прекрасные письменности с тысячами иероглифов.
>>989968 >Ты успокойся и проверь, в какой кодировке сохранен файл с исходным кодом программы - должно быть utf-8 без BOM. > >И при чем тут русский язык? utf-8 он не для русского языка придуман, а вообще для всех языков. Это ненормально в наше время ограничивать себя латинницей, когда есть прекрасные письменности с тысячами иероглифов.
У меня приступ, потому что я 3 час а убил на поиск решения и не нашёл его.
>>989972 Да проблема в том, что он не готов, осталось чуть-чуть, как будет готово - всё на гих вывалю или вообще на бесплатный хостинг залью, что бы нагядно. Это всё студенты ебучие. Осталось поиск сделать(кодировку выебать) и сортировку, на пару часов дел(mySql даётся не очень).
Продолжаю пилить админку. В процессе оказалось, что дополнительно требуется писать кучу функций. Например, нельзя просто взять и добавить новую цитату в БД, надо указать автора, для этого получить список всех авторов, чтобы сделать выпадающее меню, если автора нет, нужна страница, где его можно добавить, при добавлении убедится, что нет повтора. А еще неплохо, чтобы вместо списка форма на ходу предлагала варианты... А еще...
Ну и у тебя опять видна проблема с непониманием MVC и неумением разделять ответственность. Ты все пишешь одной функцией authorAdd(), но гораздо удобнее сделать отдельную функцию валидации и отдельную функцию сохранения в БД. Ты берешься за сложное приложение, но при этом ты пишешь код в том же стиле, как пишут простые скрипты на 20 строчек. Это нужно исправлять.
Понятно, что можно и с плохим кодом сделать что-то работающее, но я не понимаю, какая в этом выгода. Ты ведь наверно хочешь научиться чему-то, но делая кое-как, ты в итоге ничему не научишься. Лучше остановиться и разобраться.
> чтобы вместо списка форма на ходу предлагала варианты берешь плагин вроде Chosen или Select2 и прикручиваешь к нему получение вариантов дополнения через аякс либо через заложенный в коде список (если у тебя мало вариантов, то лучше просто список в HTML коде заложить).
>>990176 Я ценю твои советы, много полезного почерпнул и подтянул уровень. Но вот бомбит меня от того, что ты меня каким то дауном неоубучаемым выставляешь.
Действительно, так же пишут простые скрипты на 20 строчек? В том же стиле, серьезно? В прошлый раз я вообще прожег стул от ПОЛНОЕ НЕПОНИМАНИЕ MVC. Я, конечно, тоже считаю, что прогресс измеряется не количеством просиженных часов за доками, но вот я вижу как писал раньше https://github.com/grigoryMovchan/appsForStore и как пишу сейчас и считаю, что это небо и земля. До твоего уровня как до Луны пешком, но развитие, не без помощи в этом треде, определенно прослеживается.
Я и так понимаю, что хуйней какой-то донной занимаюсь. Зачем специально то еще дизморалить. Кому от этого польза?
>>990200 Я тут мимо пробегал, но хотел спросить по этому коду 1) возможен рейс-кондишон, всем похуй? 2) что там с обработкой исключений в пыхе, можно хуй класть?
Зачем обрабатывать исключения в этой функции? Если в SQL запросе синтаксическая ошибка, что ты можешь сделать? Ничего, только ждать пока программист придет и исправит ее.
Вообще, по моему опыту в 95% случаев исключения ловить не надо. Надо только в редких случаях - например, когда мы хотим сделать повторный HTTP-запрос при ошибке или что-то такое.
>>990214 При чем тут транзакции, когда тут два отдельных запроса? >>990215 Что при этом увидит пользователь? Думаю что-то совсем некрасивое, но если на верхнем уровне это как-то отлавливается, то наверное норм.
Тебе надо не спешить делать новые фичи, а остановиться и разобраться с существующим кодом. Какой смысл в том, что я тебе указываю на ошибку, а ты продолжаешь писать код с этими ошибками? Больше исправлять ведь придется.
Ты мой урок по MVC читал? Вот видимо невнимательно читал.
Вот есть допустим задача - добавить нового автора. Вот у меня переменная с его именем.
Есть ли у тебя функция в модели, которая решает эту задачу? Фактически нет, твой код непригоден для решения этой задачи.
И это говорит о том что никакого MVC у тебя нету. Ты не прочел внимательно мой урок про MVC, не сделал разделение кода, а просто сделал классы "Модель", "контроллер", "вид" и думаешь что теперь у тебя MVC код. А по факту в твоей "модели" обычная стена кода, где все вперемешку. И которую нельзя ни тестировать нормально, ни повторно использовать.
Прочитай урок, серьезно, прочитай. Там ведь даже пример кода есть. Чтобы твой код соответствовал MVC, нужно, чтобы у тебя была функция, которая позволяет добавить автора. Чтобы можно написать, например:
$something->addAuthor('Лев Толстой');
При добавлении автора может произойти ошибка (например, такой автор уже есть). Раз так, то нам конечно хочется еще иметь функцию, которая бы сказала нам, можно добавить такого автора, или нет.
Также, ты используешь неудачный подход для возврата результатов (в функции addAuthor). Вот смотри, есть какая-то функция, которая что-то возвращает. Ну например, сумму 2 чисел:
$result = sum(2, 2); // вернет 4
А у тебя сделано по сути так:
sum(2, 2); $result = getSumResult();
То есть ты вместо того, чтобы вернуть результат функции через return, используешь какие-то обходные пути и изобретаешь велосипеды.
И смешиваешь в одном классе функцию добавления автора с функцией хранения уведомлений пользователю. Каждый класс должен заниматься своей задачей. Класс, который работает с таблицей авторов, не должен заниматься накоплением сообщений для показа пользователю.
>>990218 Ну так в этом и суть. Рейс кондишн конкретно в пхп в данном случае - невозможен. На уровне базы и разных процессов пхп возможен. В конкретно данном случае очень вероятно, что невозхможен вообще, ибо все происходящее атомарно просто и достаточно было не проебаться при создании бд. Ну или я тебя в чем-то не понял. В большинстве случаев такие ситуации решаются транзакциями. Про исключения не согласен с предыдущим, я их не сторонюсь использовать, ловить и обрабатывать. Но в целом это не маст хев, если работаешь с фреймворком, который сам это все умеет и выводит в виде ошибки пользователю.
По идее должен быть обработчик непойманных испключений, который залоггирует его и покажет страницу 503. Но в PHP талантливые архитекторы вместо этого сделали показ белой страницы с кодом 200, а если включен display_errors - еще и с выводом текста ошибки, которую радостно проиндексирует Гугл.
Потому обычно приходится писать свой обработчик непойманных исключений.
Чтобы исключить race condition при вставке существующего автора, можно поставить в БД UNIQUE KEY по полю "имя", тогда попытка вставки существующего автора вызовет исключение.
Транзакция тут никак не помогла бы ибо она группирует запросы на изменение данных, а на SELECT-запросы почти никак не влияет (кроме случаев блокировок SELECT ... FOR UPDATE/LOCK). Вот если бы он вносил несколько изменений то да, желательно использовать транзакцию, чтобы в БД не было частично вставленных данных.
>>990219 >Вот есть допустим задача - добавить нового автора. Вот у меня переменная с его именем. >Есть ли у тебя функция в модели, которая решает эту задачу? >$something->addAuthor('Лев Толстой'); Вот с этим просто не согласен. Нет у меня такой задачи. Я целенаправленно её решил так. Этот "велосипед" конкретная рекомендация из Зандстра и похожим образом сделано в ларавель, только там Request передается не один раз в конструктор, а персонально каждой функции, где он может потребоваться. Захотел попробовать - попробовал. Может потом поумнею и признаю, что был не прав, но пока так.
>>990200 Пока ты не поработаешь с классами в 900 строк и 30 - 40 методов не поймешь. И переубедить никто не сможет. И писать комменты на англе дурной тон ( к стати если тебе нужны коменты в приделах одного метода - значит ты где - то что то сделал не так )
>>990226 Нет, скорее если в бд есть автор Джон, то Джонсон - это тоже самое, т.к содержит "Джон". В регулярке нужно добавить ограничители ^ начало строки & конец строки.
>>990202 Не рань мне душу, негодяй. >>990237 > И писать комменты на англе дурной тон Не понел. Я как раз стараюсь на ангельском все писать, вдруг свалить повезет.
> Этот "велосипед" конкретная рекомендация из Зандстра Какая глава?
Думаю, что Зандстра не будет советовать возлагать на один класс несколько разных задач.
На мой взгляд ты просто делаешь код более неудобным в использовании, сложным в понимании. Посмотри на мой пример с вычислением суммы - какой смысл делать как у тебя, если можно просто вернуть результат?
> и похожим образом сделано в ларавель, только там Request передается не один раз в конструктор, Ларавель - своеобразный фреймворк, но мне кажется, даже там такого нет. Можешь дать ссылку?
> Вот с этим просто не согласен. Тогда у тебя не MVC. А ты просто сделал класс с названием "Контроллер" и "Модель". В MVC используется разделение на компоненты, а не пишут все в одном месте. Тогда тебе надо убрать слова вроде "контроллер" или "модель", чтобы не сбивать читателя с толку.
> Нет у меня такой задачи А задачи реализовать архитектуру MVC тоже нет? Или допустим ты захочешь из командной строки импортировать авторов - как ты будешь делать. Или протестировать, что функция работает - как ты напишешь тест?
>>990244 А еще нахера ретурнить true или false если можно ретурнить массив с ключами? и строить ответ? Или можно вообще выбрасывать исключение, ловить их в контроллере и на них него 500 кодом отвечать с текстом ошибки?
Я считаю, что ничего плохого в нескольких ретурнах нет, наоборот, попытка сделать единственную точку выхода может ухудшить код (например, придется ставить огромные ифы и повышать глубину вложенности).
>Какая глава? Сейчас искать не буду. Там смысл был в том, чтобы суперглобальные переменные обрабатывались в отдельном классе, потому что может понадобится сделать с ними что-то спецефическое, и напрямую не передавались в модель.
Ок, я могу получить id из Request в контроллере и передать его в метод модели. А как тогда быть со вторым пиком? Неправильно написан Request и для данных из формы должен быть свой массив, который я должен получать из Request в контроллере и передавать в метод модели?
>>990260 Ну если так рассуждать то у каждого метода будут свои за и против. И об этом спорить можно вечно просто кому как удобней. Но допустим сколько я не общался с программерами > 5 лет опыта все стараются этого избегать >>990261 Ну если ты определишь чёткую грань между запутанным и не запутанным кодом то можем и сказать
>>990264 Но ты реально мог бы сделать имя автора уникальным индексом - тогда бы просто лишился проверки и метода. Пытался бы вставить автора а там уже еxception разруливал если он упал по индексу
>>990268 Там отдельный уровень абстракции для MySQL. Да, ОП его обоссал и я с ним согласен, но это пока мой уровень. Я его вообще спиздил из урока по авторизации, он был в виде одной функции, на mysqli и без подготавливаемых запросов.
"разруливать" exception довольно неудобно, так как там кроме кода проверять нечего. Ну и вдобавок тогда нельзя будет без попытки вставить запись сделать валидацию.
>>990263 На самом деле у него тут простой, пусть и кривоватый, пример того, чем множество return в методе лучше к примеру if {} else if { } else. Чисто мой вкус мне это нравится визуально, приятно посмотреть, но это чисто визуальщина. А вот чем такой код чище можно представить исходя из его примера и пресловутого массива errors, потому что для ошибок вообще отлично подходит и находит наиболее частое применение. Допустим у нас две возможных ошибки в методе, одна следует за другой. Вариант с ретурнами if (чтото не так) { $this->errors[] = 'Something wrong'; return;} if (еще что-то не так) {$this->errors[] = 'Fucking error'; return;} //тут начинается реальный полезный код
И то же самое без этого подхода. if (все ок) { if (и тут все ок) { //полезный код } else { $this->errors[] = 'Fucking error'; } } else { $this->errors[] = 'Something wrong'; }
Просто из-за вложенности нужный нам код оказывается гдето в дали, что может хуево сказаться на непросредственной практичности - место на экране по сторонам не резиновое.
Хочу ворваваться во фриланс к 2018. Хотя бы 200уе верстая сайты. В этом поучить (портфолио желательно сделать небольшое) Посоветуйте годноты по HTML/CSS, JS, jQuery Гайдец мануал. как начать что учить.
А там мб и в создание сайтов можно перекатиться в будещем
Сотирую список студентов, подкиньте идею как по нажатию на одну и ту же кнопку делать сортировку сначало по возрастанию, по второму нажатию - по убыванию. Пока ничего кроме нагромождения сессий и кучи переменных отслеживающих нажатия в голову ничего не пришло. <td class="firstStr"> <?php echo "<a href=\"http://students/list/{$page}/name\">Имя</a>"; ?> </td> Ссылка для сортировки по имени выглядит вот так. Контроллер получает текующую страницу $page и тип сортировки "name", по нажатию сортируется, но как сортирнуть в обратную сторону по нажатию на эту же кнопку? Без жс.
Блядь, что не так с сортировкой? Отобрали 10 записей и отсортировали - вернули результат. По факу получается - отсортировали всю таблицу и отобрали 10 записей. Т.е на не важно какие записи были выбраны для 1 страницы, при попытке отсортировать выдаёт первые 10 строк из БД по типу сортировке. Лимит срабатывает, но только в виде ограничения выданных строк(10).
>>990362 Там после 60 до 100 страницы ничЁ не понятно, сложнА. Но потом вроде бы лучше становится, сейчас читаю про сами конкретные шаблоны - всё более-менее пока.
>>990372 Когда знаешь, допустим, про массивы, уже с ними повозился нормально, то если будешь читать, то ведь не будет нужды запускать этот код, всё ведь и так тебе понятно? Вот так и тут. После "Вектора" (до антикризисных мер, правда) там всё понятно в общем и целом. У Зандстры вот эти instanceof, ещё куча чего-то специфического очень долго объясняется перед шаблонами, я вот эту муть имел в виду.
Анончик, прощу на помощь. Мне нужен пример простого сайта где на стартовой странице несколько наименований товара и при клике по ним открывается подробное описание и все. Подскажите где код взять.
Идея такая, что даже если js отключен, то прилжение всё равно будет работать. Наверно, это не совсем js, но всё-таки мы всё равно обрщаемся к php через ajax.
Как остановить setInterval, который был вызван в предыдущем событии? Вообще я правильно ли делаю динамическую подгрузку? С этой функцией очень много проблем, например, она меняет контекст this на вызываемой функции и его нельзя поменять с помощью call.
$('.contact').on('click', function() { ... setInterval(controller.refreshMessages, 500, ...); //Выводит сообщения и из предыдущего диалога. });
Ничего то что я называю методы отображения одним словом, например, $view->index()? Я имею ввиду, мы же всё равно пишем $view, писать $view->viewIndex() похоже на тавтологию.
Как организовать конференции? Это же не совсем пользователи, к которым можно отправить сообщения, хоть и можно их так представить. Я имею ввиду, как проще было бы получать все контакты пользователя и его конференции один запросом, чтобы было удобно было сортировать или искать в базе данных? Или лучше отдельно получать контакты и отдельно получать конфернеции, при условии, что оптимизация нагрзуки на бд не имеет значения?
Как сделать уведомление о том что пользватель набирает сообщение? Нужно обнавлять какую-нибудь запись в БД об этом? Наверно, для нужно сделать отдельную таблицу conversations. Вместе с этим, отпадает вопрос как лучше организовать конференции.
Как лучше сохранять не отправленные сообщения? Сохранять их в куках или в бд, или же это тоже можно как-то реализовать с помощтю js?
>>990621 Такая себе идея делать чат через обычные пхп-скрипты и автообновление аяксом. Я бы лучше вебсокеты взял, они надежнее и проще в реализации таких вещей. Ну и для вывода сообщений можно было бы использовать какой-нибудь шаблонизатор, погугли, их достаточно много.
Чет бесит официальная документация. Неудобно пользоваться. Непонятно, нажимать мне на ссылку, уводяющую хуй знает куда (вдруг там чето важное), или нажать на ссылку в правой колонке, чтобы перейти к следующей статье (уебанская навигация, не сразу заметил). И вот это: >В данном руководстве мы предполагаем, что ваш сервер имеет поддержку PHP и что все файлы, заканчивающиеся на .php, обрабатываются PHP. Откуда у ньюфага сервер?
>>990692 Делаю сейчас как раз в заказе чаты на vue. Использую сокет.ио, пхп для апи (почти все сделал закрытым). Функционал похож на вк, местами чуть больше, местами чуть меньше. Я ебнусь короче. В чатах столько мелочей ебучих, ппц просто. Хотя уже немного осталось. Сокеты маст хев конечно, но вот стабильности там кот наплакал, хорошо что я взял свою готовую архитектуру с других проектов, а то это только на еблю с неочевидными особенносятми сокетов пару недель ушла бы.
>>990718 Жаль его. В 16 он "умнее" 99% остальных сверстников, просто потому что дрочит на какую-то левую хуету, на которую в его возрасте всем тупо насрать. А в 25 он уже спившийся неудачник, просто потому что маня-мир это одно, а реальность - другое.
>>990730 Прикольно кстати то, что я годам к 20 перестал себя считать умнее среднего гражданина прямо, а если оно и так - мне наплевать. Чего и вам желаю, будущие программисты. Я свой ум только по работе использую, чего он мне еще дает - хз. Скорее мешает, много рефлексирую.
>>990736 Ну это у многих так происходит. Сначала ты в 16 идеалист-максималист, и вокруг как будто тупое быдло, а к 20-25, понимаешь, что всё не однозначно в этом мире, и скорее сложно, и поэтому всем скорее похуй, ну и тебе уже тоже.
Дальше, ты не засовываешь верные номера в массив, а выводишь совпадения найденные в строке. То есть, если написать preg_match("Hello World", '/^Hello (World)|(Cat)$/', $matches), то $matches будет равен array('Hello World', 'World').
https://secure.php.net/manual/ru/function.preg-match.php >matches >В случае, если указан дополнительный параметр matches, он будет заполнен результатами поиска. Элемент $matches[0] будет содержать часть строки, соответствующую вхождению всего шаблона, $matches[1] - часть строки, соответствующую первой подмаске, и так далее.
Очень плохо.
Тебе первым делом нужно итерировать массив $number, и, затем, на каждую итерацию выполнить проверку на твоё регулярное выражение.
Сап аноны. Я пока недавно пишу на ООП и до сих пор не понял одно - зачем везде использовать объекты? Именно объекты а не статические свойства и методы, ведь в большинстве задач используется не больше одного экземпляра класса, зачем тогда нужны все эти копии? Какой смысл?
Вот тут https://habrahabr.ru/post/13726/ статья "Безопасный метод авторизации на PHP". Я его попробовал на своём сайте, всё работает. Но при некотором усложнении страницы, начинаются глюки. Такое ощущение, что POST срабатывает при обновлении страницы, причём регистрирует последнего пользователя, которого регистрировали, даже если все поля пустые.
В общем, не хочу даже разбираться, что это за НЁХ, а хочу просто переписать этот код следующим образом: Вместо <form method="POST"> и <input name="submit" type="submit" value="Зарегистрировать"> поставить просто кнопку, при нажатии которой срабатывает джава-скрипт и собирает данные из инпутов, а затем отправляет их аяксом в отдельный php-скрипт, в котором практически тот же самый код, что и в статье. Ну и потом он возвращает ответ успешно/не успешно. Так вот - как это выглядит с точки зрения фен-шуя? Я не слишком усложняю?
(У меня в одном php-файле, отвечающем за отрисовку страницы, есть два дива: на одном одна вкладка, а на втором другая. И две кнопки, которые меняют display:block; для них, чтобы юзер мог открывать их, как вкладки. На второй вкладке и стоит форма для регистрации первого пользователя, плюс список существующих, с кнопками удаления и смены пароля.)
>>990944 1. \s - это не только пробел, но и табуляция, и переход на новую строку. 2. В первой скобке - зачем + и 7 в квадратные скобки взял? + просто экранируй, 7 - и в Африке 7. 3. [0-9] можно заменить на \d при желании. 4. А если бы 100 было цифр в номере, ты бы сто раз копипастил? Сделай нормально, а то нечитабельно же совершенно.
Доделал сейчас игру анона с компом в кубики. И что я могу сказать? Просидел 20 минут исправляя все. То есть сам я верно с самого начала все написал. Но где то забыл $ добавить, где-то ; и так далее. И это сейчас еще малый объем работы. Что же будет дальше? Надо срочно улучшать внимательность
>>988855 Спасибо за понятный и доходчивый ответ по индексам. А можно ещё задачу, где нужно подумать над проставлением индексов? Ты вроде раньше кому-то предлагал БД для борды проектировать, но я, к сожалению, не смог этот пост найти c полным текстом задачи.
>>990295 Недавно это делал, но на шарпе. В классический mvc это делается через методы, которые принимают на вход get-запрос. А в самом вью вместо статики передается вызов этого метода.
Зачем в моделях определять её свойства? Допустим в TDG я делаю отдельный класс для работы с базой, но саму модель я не трогаю, но свойства определены и никак не задействованы, а класс модели использую как хелпер в контексте этой модели, что я делаю не так?
Формирование ссылки явно стоит вынести в отдельную функцию, а не писать прямо в шаблоне. Соответственно в эту функцию будут передаваться аргументами все значения, от которых зависит содержание ссылки:
- фраза для поиска - название колонки - выбранная колонка и направление сортировки
Ну а уже функция должна сравнивать текущую сортировку с названием колонки и выбирать нужное направление сортировки.
Если свойства никак не задействованы, зачем их делать? не нужно копировать то, что ты где-то увидел, нужно думать, зачем в коде та или иная строчка.
Твоя проблема в непонимании слова "модель". Там, где стоят свойства, модель предствавляет собой объект, который хранит информацию о какой-то сущности и у которого есть все описанные свойства. А TDG такой "моделью" не является, это объект для выполнения запросов к БД и ему конечно эти свойства не нужны. Но когда ты например запрашиваешь список студентов, тут как раз хорошо использовать модель для представления студента и возвращать список таких объектов-моделей.
Не путай "модель" (сущность) студента с компонентом "модель" из MVC. Это не одно и то же.
> Допустим в TDG я делаю отдельный класс для работы с базой, Как-то странно написано. "в TGD"? Ты наверно имел в виду, "я сделал класс, который реализует паттерн TDG".
> а класс модели использую как хелпер в контексте этой модели, Вот это не понял.
>>991228 >А TDG такой "моделью" не является Так я не называл её моделью, а в моём понимании модель это отдельный класс для свойств сущности. Вот я создал класс модели и задал свойства (1 пик), также в нем есть какие то методы которые относятся к ней. Второй класс для работы с бд (2 пик) , там я реализую функционал работы с бд и только его. Вопрос в том, как можно использовать свойства в модели (1 пик), и нужны ли они вообще?
Насчет борды, задача такая: есть борда, нужно сделать таблицы для хранения постов/тредов на ней и нужно сделать SQL запрос(ы) для постраничного вывода тредов, причем для каждого треда выводится ОП-пост и 3 последних поста. Треды отсортированы по дате последнего сообщения. Позже при желании можно прикрутить бамплимит (после X постов тред перестает подниматься) и сажу (посты которые не поднимают тред).
Также, если хочется задачу посложнее и пореалистичнее, в одном из старых тредов была задача про БД для сервиса вроде itunes: http://arhivach.org/thread/117571/#568993
А как у тебя первый класс Abiturient используется? Зачем он вообще нужен?
Обычно его используют для представления информации об абитуриенте. Например его можно передать в функцию сохранения абитуриента в БД, а функция поиска абитуриентов может возвращать результат в виде таких объектов.
У тебя же по сути в качестве модели класс TDG использует массив, а не объект.
она очень странная. А зачем тебе внутри TDG хранить одну пустую модель абитуриента? Зачем TDG вообще что-то сохранять? Это же просто не нужно. Если ты хочешь вставить абитуриента в БД, ты его передашь как аргумент в функцию вставки.
else = "иначе, если ни одно из условий сверху не сработало, выполнить этот блок" elseif (условие) = "иначе, если условия выше не сработали и если выполняется условие, выполнить этот блок"
То есть else всегда идет самым последним и в нем не указывается условие.
Плохо, что ты не хочешь разобраться в проблеме, а убегаешь от нее. Лучше найди в чем была причина ошибки.
> Такое ощущение, что POST срабатывает при обновлении страницы если страница загружена методом POST то конечно при обновлении он отправится повторно. Погугли про Post/Redirect/Get а еще лучше прочти мой урок про формы https://github.com/codedokode/pasta/blob/master/forms.md
> На второй вкладке и стоит форма для регистрации первого пользователя, плюс список существующих, с кнопками удаления и смены пароля. А они защищены? Неавторизованный злоумышленник не сможет отправить такой запрос, который поменяет пароль другому пользователю или удалит его?
>>991239 >У тебя же по сути в качестве модели класс TDG использует массив, а не объект. Ну точно, можно в качестве аргумента и модель передать, я кажется понял все спасибо тебе.
А еще вопрос такой, вот в контроллере я могу кроме как обработки шаблона, делать методы нужные для конкретных шаблонов, то есть правильно ли так делать? Или же все нужно в отдельные классы хелперы выносить?
В статье есть много вещей которые копировать не стоит. Например не стоит использовать MyISAM, стоит ставить внешние ключи, не стоит использовать устаревшие функции вроде mysql_select_db.
- в регулярке нет разделителя в конце и нет флага u (хотя он тут ни на что не влияет, но все же) - внизу выводятся ошибки - переменной $number не существует, а ты ее пытаешься использовать -preg_match работает только с одним номером за раз, а не принимает на вход массив номеров
Конечно ты делаешь неправильно. Во-первых, единственные публичные методы у контроллера - это обычно методы вида "вывести страницу такую-то/обработать запрос".
Метод форматирования даты лучше всего сделать статическим в отдельном классе-хелпере реализующем паттерн Utility Class (класс с статическими методами).
Непонятно зачем в контроллере свойство date. Это свойство контроллера?
Неправильно выбрано название datamodel. Оно должно называться abiturientGateway.
Неправильно что ты используешь одну переменную $date для хранения строки и объекта.
Неправильно называть переменную dataArr так как это название ничего не значит: любая переменная хранит данные.
>>991281 >Непонятно зачем в контроллере свойство date. Это свойство контроллера? Да, это свойство выводит текущую дату, и её наверно тоже в отдельный класс насколько я понимаю
>>990941 Что ты пытаешься сделать во втором цикле?
Во-первых count() считает сколько элементов в массиве. В php строка это строка, а не массив символов.
Во-вторых, в цикле for ты сравниваешь переменную $i с 0, а не присваиваешь его ей. Оператор ==, это сравнение а не присваивание. Почему ты решил что должно быть сравнение? Затем ты сравниваешь $i <= $len, и цикл обойдет $len + 1 раз, потому что ты начинаешь с 0. Цикл будет выполняться пока значение второго аргумента истинно, то есть в твоем случае $i <= $len, цикл будет выполняться от 0 до и включая $len. Вот пример https://3v4l.org/EPLQc посчитай сколько раз выполнился цикл. Если ты хочешь чтобы цикл обходил ровно $len раз, то тебе нужно либо начинать цикл с 1, либо выполнять этот цикл пока $i меньше $len $i < $len.
Я тебе уже говорил, что ты делаешь из $CorrNumb не массив правильных номер а массив совпадений. Если ты хочешь получить массив правильных номеров, то лучше сначала создать еще массив $matches и затем поместить его в preg_match обычно так и делают. И далее уже добавлять в $CorrNumb >строку, соответствующую вхождению всего шаблона
if (preg_match($regexp, $number, $matches)) { //добавляем строку в $CorrNumb }
Перечитай как работает функция preg_match.
Для чего нужна переменная $regexpRepl?
Ты нарочно делаешь такое форматирование кода? Перечитай второй поста треда. >- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
>>991281 > в отдельном классе-хелпере реализующем паттерн Utility Class (класс с статическими методами). Зачём всё подряд из Java тянуть? В PHP ведь можно поместить функции в неймспейс, а Composer подгрузит (правда, не без пинка). Нет ничего плохого в чистых функциях: https://nikic.github.io/2012/08/10/Are-PHP-developers-functophobic.html Всякие Utils лишь утяжеляют код ненужными приставками, когда можно написать use function namespace\foo;
>>991264 >Если строго говорить, то \d это любая десятичная цифра из любого алфавита, а не только арабские цифры 0-9 Ты чо дохуя умный штоле еба?777 Ща как уебу нахуй спасибо, не знал
>>991276 >не стоит использовать MyISAM Воу-воу-воу! Можно, пожалуйста, поподробнее, почему? Я для своего проекта выбрал ее, потому что пишут что она быстрее при определенных условиях (которые у меня соблюдаются), транзакции мне тут не нужны. Какие подводные?
>>991320 Он даун просто. Форыч норм, единственное чем он сбивает, что работает с копией массива, а если хочешь менять значения перебираемого массива inplace - то нужно явно передавать значения по ссылке. Но вообще лучше так не делать вовсе.
>>991224 Проблема в том, что сохранить текущий тип сортировки можно только в сессию, ведь при вызове новой страницы - программа выполняется с нуля. ->в адресную строку попадает адрес с типом сортировки->FrontController получает ссылку, разбивает, запускает нужный контроллер и переадаёт ему параметры...
Не подгрузит. PSR-4 работает только с классами, функции использовать (и импортировать) неудобно. Да и я не вижу большой разницы между статическим методом и функцией. Удобнее сделать именно класс.
Дело тут не в боязни, а в том, что просто с функциями менее удобно работать. Да и они не вписываются нормально в неймспейсы. Ведь в PSR-4 неймспейс соответствует папке, и непонятно, как хранить функции? Каждую в своем файле? В одном файле? Удобнее все же сгруппировать их в класс, а ностальгирующие по Го, Питонам и Руби могут отправиться писать на этих языках.
Кстати в Го примерно та же проблема: там модуль соответствует папке, и просто непонятно как раскладывать функции по файлам в этой папке. Ужасно сделано.
Нагугли сравнение MyISAM и InnoDB. Во-первых, InnoDB умеет блокировать отдельные строки, а не всю таблицу при записи (то есть параллельные операции записи в MyISAM будут выполняться последовательно, что медленнее), не поддерживает транзакции, внешние ключи. Это просто более старый движок.
Насчет производительсности в каких-то редких случаях - предложил бы померять, скорее всего разница там незначительная и никак не оправдывает отсутствия внешних ключей и транзакций.
php7 тут не при чем. Работа с копией массива это правильная вещь, так как это значит, что цикл работает предсказуемо даже если по ходу выполнения менять массив. Иначе как ты поймешь, как этот цикл будет работать, если сам массив меняется по ходу выполнения?
Если страница не найдена, то надо отдавать ошибку 404. Это поможет во многих случаях, а то, что ты делаешь, например запутает поискового бота и твой сайт получит низкий рейтинг в поисковых системах. Также, бот, который проверяет целостность ссылок не сможет обнаруживать битые ссылки. То есть так делать не надо.
Получение соседних id я бы советовал сделать отдельным методом.
В контроллере у тебя встречаются длинные выражения вроде
Текущий тип сортировки может быть указан в query string-параметрах:
/index.php?sort=-name&page=2&query=Ivan
Ты мыслишь не в парадигме REST. REST говорит о том, что параметры отображения страницы указываются в URL, а не спрятаны в каких-то сессиях, куках и тд.
То есть в REST мы сортировку указываем в URL.
Если сортировку хранить в сессии это только вызовет проблемы, так как куки и сессия общие для нескольких вкладок браузера и они будут влиять друг на друга.
Соответственно сессия тут не нужна. Определяешь тип сортировки в контроллере и передаешь переменную в шаблон.
Вместо $this->dbh->query лучше сделать методы queryAssoc, querySingleValue, querySingleRow, queryColumn и тд. Посмотри, как сделано в Doctrine DBAL (англ):
>>991559 КАК ОПРЕДЕЛИТЬ ТИП СОРТИРОВКИ? СКАЖИ ПРЯМО, хватит повторять - "засуть тип сортировки в адресную строку", параметры всегда там! Все там! Но нажатием на ОДНУ и ту же ссылку НЕВОЗМОЖНО передать разные параметры.
Нужно генерировать разные ссылки в зависимости от текущей сортировки. То есть если у нас включена сортировка +name, то ссылка на колонке должна содержать -name.
Для начала, как попробуй зайти на сайт фриланса и изучить имеющиеся там задания. Там есть категории, изучи их. Там есть faq и помощь. Изучив, можешь уже задавать вопросы.
>>991691 >Нужно генерировать разные ссылки в зависимости от текущей сортировки. Как запоминать текущую сортировку? >То есть если у нас включена сортировка +name, то ссылка на колонке должна содержать -name. Что? Нажимаю на name - контроллер получает параметры /name/asc Нажимаю снова на name - контроллер получает все те же параметры /name/asc КАК запомнить и переключить ASC в DESC?
>>991740 Ты совсем необучаемый, тебе уже разжевали ответ донельзя. Генерируешь ссылку /name/asc, кликаешь по ней, контроллер получает /name/asc. При выводе шаблона меняешь asc на desc и получаешь ссылку /name/desc. Тыкаешь опять по этой ссылке - в контроллер уже прилетает desc.
Алсо, есть сейчас разница какую кодировку выбирать для своей БД? Например если я планирую хранить только русский-английский текст и цифры, всё равно брать utf8_unicode_ci?
Вроде же понял, что из себя представляют циклы. Ничего сложно же. А вот в задачах на них просто ступор. Что-то пишу, а это не работает, переделываю и это тоже не работает. Гуглить и спрашивать помощи тоже не хочу. И уже времени нет чтобы дальше решать. Завтра просижу весь день, но решу эти задачи
Ребят, а возможно ли сделать сайт в онлайн конструкторе, скачать его и вручную (оффлайн) сделать обычным, будто ты сам его делал? Или в таких сайтах всегда много подводных камней?
>>990840 >Именно объекты а не статические свойства и методы, ведь в большинстве задач используется не больше одного экземпляра класса, зачем тогда нужны все эти копии? Какой смысл? А ты можешь, например, изменять состояние статических свойств?
Приветствую, господа программисты. Нужен совет. Хочу написать сайт-энциклопедию. Грубо говоря у каждой статьи в ней должна быть своя категория, группа, дата и многое другое. После чего хочу организовать по всей энциклопедии удобную группировку по датам и т.д. Изучил HTML, CSS и так понимаю, дальше надо копать в сторону MySQL, PHP(Ведь нужен, да?) и что еще? В общем, что нужно еще для сайта-энциклопедии?
Ты скорее всего сидишь на stable версии - а туда включают только пакеты, которые какое-то время оттестированы и в которых большинство багов выявлено и исправлено. php7 пока не считается "стабильным" разработчиками debian.
Соответственно, выхода 2:
- апгрейдиться на более новую версию дебиана, testing или даже unstable (если это виртуальная машина то в принципе тебе терять особо нечего) - подключить сторонний репозиторий вроде dotdeb, который содержит нужную версию php: https://www.dotdeb.org/
Помни, что подключая сторонний репозиторий ты добавляешь его цифровую подпись и автоматически начинаешь доверять его авторам. Они могут при установке php или любого другого пакета одновременно заменить любые программы и библиотеки в твоей системе, например, установить бекдор, если захотят, и выполнить любой код от имени root (по умолчанию бекдор могут установить только разработчики дебиан).
Почему-то про это никто не пишет. Кругом только люди, которые бездумно копируют инструкции, не понимая, что они делают.
>>992123 В первом случае для наглядности, наверное. А в остальных, чтобы не рвать строку типа: "блаблабла это", $значениеблаблабла, "продолжение текста"
>>991903 Да я упорот был когда спрашивал, после 12 часовой смены идти учить пхп вообще плохая идея. Щас сел бодрый, за 15 минут решил проблему с сортировкой. Класс не будет называться студент, это ошибка. Условия не прозрачные и запутанные, i know. Условия здесь для нормального отображения когда сортировка пользователем не задана, а то начинают в строку запроса попадать лишние слэши, да типы сортировок по умолчанию.
>>992123 Первый случай - для наглядности. В целом по приоритету операций умножение и так будет первым. Однако я сам всегда руками скобки ставлю от греха подальше, и для лучшей наглядности, притом на любых языках. Второе опять же для удобства, можно и без этого, но лучше не надо, не будь говном.
У меня при больших кусках кода на всех сайтах, где можно потестить код выдает ''превышено время ожидание, бла бла бла'' и тд. Это значит надо переходить на программу? Или там тоже может быть такое, а вся проблема в моем коде?
Это значит твой код выполняется дольше 3-5 секунд что довольно много. Может там вечный цикл? Попробуй уменьшать код и опытным путем найти тормозящее место.
Также можно мерять время выполнения через microtime(true).
Чтобы снять ограничение, надо установить на компьютер PHP и запускать код у себя, инструкции в ОП посте.
>>992206 Cпасибо большое! Я думал сойду с ума уже, но не решу задачу с айфоном в кредит. Час все проверял, а оказалось, что всего лишь лишняя фигурная скобка поставлено и сайт как на зло не говорил об этом. Но и php на комп поставлю. Все равно потом придется
Почему это не работает? Если не хеадерить и вывести на экран, то получаем закодированную строку, но если хеадерить - то получаем нихуя, как буд-то и не кодировали, в адреснюу строку попадает та же кириллица из $_POST.
Браузеры иногда отображают адресную строку в декодированном виде. Также они иногда декодируют punycode в доменах. Попробуй кликнуть в адресную строку или скопировать УРЛ - может он выведется как есть.
Также, содержимое Location можно увидеть в отладчике на вкладке Network.
>>992229 Годный ответ, действительно в отладчике увидел, что ссылка закодирована, в итоге ошибка оказался не в том, что строка не кодируется, а совершенно в другом. thx.
>>992215 Ты задачу-то покажи - инфа 99%, что там не всё идеально, поскольку можно улучшить. Либо вообще неправильно работает, хотя ОП вроде указал всё сейчас в учебнике для ориентира.
В общем, есть один абстрактный класс. Назовём его Animal. У абстрактного класса есть некий порождающий этот же класс метод. Допустим, что там просто return clone $this; Как мне в PHPDoc-блоке отметить, что этот метод возвращает не просто Animal, а для class Cat extends Animal {} этот метод возвращает Cat, ну и для собаки соответственно Dog?
Док вида @return static @return self @return $this
Идеей не кушаются. ___________________- Аналогично как мне задать в phpdoc-блоке некое виртуальное свойство, допустим $__clone_shit, которое тоже возвращает именно конечного потомка (static::class), а не Animal.
Это нужно только для того, чтобы я нормально видел ссылки на используемые поля и чтобы мне Идея сразу подсвечивала методы/поля наследников, и мне не приходилось через phpdoc писать @var Cat $cat
Само собой я знаю, что есть метод лоб и можно просто писать у каждого наследника свой phpdoc-блок и переопределять функцию, которая просто будет делать return::parent(... но можно ли это сделать автоматически, без извращений?
>>992457 Код стрёмный. По первому скрину: Выносить действия конструктора в отдельный метод init смысла нет, код от этого не становится легче (на Yii не смотри, у них много сомнительных практик используется). Ну и ответь на вопрос, чем вообще характеризуется "Запрос"? Как минимум типом (GET, POST и т.д) и путём (/user/1). Без этих вещей запрос существовать не может, поэтому логично потребовать их в конструкторе. Класс Request у тебя неудобный, я не могу из консоли создать объект вот так: $request = new Request('/path', 'GET'); Такие реквесты удобно использовать в юнит-тестах, чтобы "эмулировать" запрос программно, а не руками вводить в браузере. В Symfony ещё используется статический конструктор: $request = Request::createFromGlobals(); // Создаёт объект на основе глобальных переменных. Это вообще я основы ООП рассказываю.
По второму скрину: Почему заголовки проставляются в обход класса Response? Или у тебя Request есть, а Response нет? Ну и название класса Errors неоднозначное, я вот подумал, что это класс, представляющий список ошибок, например валидации.
По третьему: - PDO незачем в кишки прятать, что если я захочу в конфигурации БД указать PostgreSQL, а не MySQL? Мне нужно лезть в твой код и править, а такие вещи должны настраиваться вне класса, в конфиге. Если захочу использовать SQLite, то там вообще юзера и пароля не будет. Используй DI. - ConfigModel читается как "модель конфига", странное название. И зачем синглтон для конфига?
Основные проблемы c ООП, DI, MVC. Обо всём этом написано у ОПа хорошо, особенно про DI.
>>992497 >Это вообще я основы ООП рассказываю. Интересно, почему программисты такие токсичные. Ведь, наверняка, искренне уверен, что не пытается быть тщеславным и унизить другого. А получается именно это.
Синглтоны, внедрение зависимостей и статические конструкции, это не основы. Основы, это наследование Котов и Собак от класса Животные.
Я спросил одно, а в ответ весь код стали критиковать, хотя я этого не спрашивал и мне выше тоже самое уже написали, я просто не успеваю все читать и переделывать. Смешно, что бессмысленными называются конкретные примеры из Зандстра.
Просто бомбит. Собственно, отвечать на этот пост не надо, я лишь получу еще один ушат говна в мой адрес в абсолютно таком же стиле. Это просто черта характера с которой ничего не поделать.
>>992504 Еще вспомнил, что когда я откровенное говно полгода назад постил, где ни классов, ни архитектуры ни намеков на ООП, даже коннект к БД через mysql(), то желающих обосрать не было.
>>992095 >Помни, что подключая сторонний репозиторий ты добавляешь его цифровую подпись и автоматически начинаешь доверять его авторам. Они могут при установке php или любого другого пакета одновременно заменить любые программы и библиотеки в твоей системе, например, установить бекдор, если захотят, и выполнить любой код от имени root (по умолчанию бекдор могут установить только разработчики дебиан). Это важно иметь ввиду, что сторонние репозитории могут установить бекдор, но почему вы посоветовали dotdeb.org в качестве доверенного, а не зеркала debian.org, с которого скачивают сам дистрибутив?
>>992486 В опенсурс проекте на гитхабе юзается. Я немного не понимаю нахуя, но то что видно какой-то key в исходнике страницы -- меня пугает. Объясни что за мета джсон данные и как они важны?
>>992593 Блииииин, хочухочухочу! Отлично, если обычный человек зарабывает 300к/сек, то такой гений как я сможет заработать все деньги этого мира! Вкатываюсь через 5 минут, ждите!
Есть тут желающие изучившие в шапке пхп от корки до корки и думающие себя чем-нибудь занять? Есть легкое задание, немного поковыряться в бутстрепе 4 твиттера, получить немного знаний и $. Пишите контакты.
dotdeb это сторонний репозиторий, который не является заркалом debian.org. В нем выложены пакеты, которых в дебиане нет (иначе зачем он был бы нужен).
Дело кстати не только в бекдорах (dotdeb вроде известный), но еще и в том, что что-то могут случайно сломать, например, они могут обновить какую-то библиотеку, которая используется и другими программами, и нечаянно что-то сломать. Так как это сторонний репозиторий и никто в дебиане не тестирует свои пакеты на совместимость с ним.
Я сам им впрочем пользовался и вроде ничего не сломалось. Но важно понимать, какой уровень доступа к системе ты даешь авторам репозитория.
>>991269 >Плохо, что ты не хочешь разобраться в проблеме, а убегаешь от нее. Уже четвёртый месяц пишу небольшую систему и хочется её, наконец, выпустить, хоть тушкой, хоть чучелом. Плюс, у меня там вообще почти все вызовы пхп-кода так оформлены. Единообразие полезно. >если страница загружена методом POST то конечно при обновлении он отправится повторно. Погугли про Post/Redirect/Get а еще лучше прочти мой урок про формы https://github.com/codedokode/pasta/blob/master/forms.md Не, страница просто грузится. А урок прочитаю. >А они защищены? Сложный вопрос. С одной стороны, страница, с которой идут вызовы кода, который работает с бд, защищена. Но если рядом положить другой пхп-файл без защиты и вызвать с него, то действия будут произведены. Это дыра, но на неё я, опять же, плюнул ради ускорения релиза.>>991276 >mysql_select_db Знаю. Потом заменю на PDO. >не стоит использовать MyISAM, стоит ставить внешние ключи Запишу в to do list, потом погуглю, что к чему.
>>992524 Лолчто? Если под функциями ты имеешь в виду встроенные функции по работе с массивами (count, array_search, array_slice, implode), то НЕ могу, яж новичок. Чтоб вот так просто, как в твоем примере — нет. Это какая-то высшая магия. Сорре.
Кто-нибудь сталкивался с проблемами кодировок win-1251? Установил Atom, установил расширение Remote-FTP. При открытии файла с ftp в кодировке win1251(CMS Bitrix): http://joxi.ru/RmzYLDgIWXZokr. Смена кодировок не дает результата. Установил VS Code. Установил расширение FTP-Simple. Тоже самое. VS Code автоматически определяет кодировку как UTF-8. Повторное открытие файла в кодировке Windows-1251 ничего не исправляет. ОС Windows 10 Pro
Atom был для сравнения установлен на Kubuntu 16.04 с расширением Remote-FTP. Кодировка применяется и все работает отлично. ЧЯДНТ?
Так как у нас учебный тред, то для нас самое важное - это научить людей писать правильно.
>>А они защищены? > Сложный вопрос. С одной стороны, страница, с которой идут вызовы кода, который работает с бд, защищена. Но если рядом положить другой пхп-файл без защиты и вызвать с него, то действия будут произведены. Это дыра, но на неё я, опять же, плюнул ради ускорения релиза.
Мне кажется, тут кто-то кого-то не понял. Злоумышленник имеет возможность отправлять любые HTTP-запросы к сайту. Соответственно, проверки должны стоять в том скрипте, который выполняет действие.
Ну например, у тебя есть скрипт 1, который выводит форму с кнопкой удаления пользователя и есть скрипт 2, обрабатывающий POST запрос, который отправляется при нажатии кнопки и допустим скрипт 2 в ответ на этот запрос удаляет выбранного пользователя. Проверка должна стоять в скрипте 2, он должен проверять, что запрос отправлен администратором, а не злоумышленником без прав. А если отставить скрипт 2 без проверки, а защищать скрипт 1, то это лишь видимость защиты.
> Но если рядом положить другой пхп-файл без защиты и вызвать с него, то действия будут произведены. Это не уязвимость так как такой файл злоумышленник загрузить не может.
>если страница загружена методом POST то конечно при обновлении он отправится повторно. > Не, страница просто грузится. Действия, которые меняют состояние сервера (удаление, изменение, добавление информации) должны делаться только через POST-запросы (то есть в форме должен стоять method="POST"). GET-запросы только для случаев, когда информация не меняется, то есть для получения информации с сервера.
Если тебе непонятны слова вроде POST-запрос, то может быть стоит почитать где-нибудь про основы протокола HTTP.
>>992681 >е в Windows-1251? Если его скопировать и открыть с диска, та же проблема? VS Code: с диска он открывается сначала в utf-8 затем принудительно указываю открыть в Win-1251 Atom: в обоих случаях открывает в UTF-8 Кодировка Win-1251, т.к. при установке CMS Битрbкс была указана она. Два ПК проверил на Win10 - одинаковые ошибки. Один ПК на Kubuntu - ошибок нет и кодировка пменяется.
Чтобы не обманули, можно использовать escrow-сервисы вроде тех, что есть на fl (безопасная сделка), но для маленьких сумм там наверно слишком много возни.
Вряд ли, мало кто может за месяц изучить все нужное. Месяцев 6-8 уходит. Если твоя цель - зарабатывать 6000 р в месяц (меньше МРОТ?) то может тебе проще дворником устроиться и пару часов в день дворы подметать? Программисты за 100 долларов в месяц не работают.
Где токсичность-то? Запостил код в тред - получил комментарии. Там же код комментируют, а не твою личность. Это ты по моему как-то резко воспринимаешь критику своего кода.
Да и тем более может он первый раз твой пост увидел. Откуда он должен знать что тебе уже писали эти замечания?
Если тебе кажется что что-то пишут неправильно, так дай аргментированный ответ. Вспомнил Зандстру - так хоть главу или номер страницы напиши, чтобы можно было найти и сравнить.
А ты вместо этого начинаешь переходить на личности и обвиняешь людей в "токсичности".
Тебе ведь пишут, почему лучше так или иначе сделать, а не просто предлагают верить на слово.
А что касается твоего вопроса, то я уже писал, что тебе для начала надо определиться, что ты будешь называть "моделью" и только после этого можно сказать, правильно ты назвал класс или нет.
Никак. Более того, если у тебя в методе написано @return Animal, и ты получаешь из этого метода объект, то ты не должен додумывать, что будет возвращен именно объект Cat и должен использовать только имеющиеся в Animal поля и методы.
@return Animal значит что будет возвращен объект Animal или любой его наследник, в том числе Wolf, который может еще даже не написан.
Можно в Cat и Dog впрочем переопределить этот метод и сделать, чтобы они возвращали не Animal, а конкретного его наследника.
При этом надо соблюдать принцип Лисков, что объект-наследник можно подставить в код вместо предка, и метод-наследник должен возвращать объект Animal или его наследника.
>>992710 Однозначно. Совсем все не так сделал. Если коротко, алгоритм должен быть таким: в цикле идешь по одноклассникам, каждую итерацию сравниваешь рост анона с текущим одноклассникам, если он больше, то инкрементируешь счетчик, а после цикла выводишь счетчик свой.
> Аналогично как мне задать в phpdoc-блоке некое виртуальное свойство, допустим $__clone_shit, которое тоже возвращает именно конечного потомка (static::class), а не Animal. Никак, и есть ощущение, что ты там что-то переусложняешь. Также, имена, начинающиеся с 2 подчеркиваний, зарезервированы для использования разработчиками PHP и ты не должен свои поля называть так.
Сами "виртальные" свойства, создаваемые через __get, можно описать с помощью @proeprty, но магических методов по возможности лучше избегать. Лучше сделать реальное свойство.
Я бы советовал не заморачиваться с вставкой сортировки в URL, а просто использовать аргументы ?sort=.... (то есть у нас есть одна страница списка студентов, и разные параметры ее отображения), а если ты вставляешь аргументы в URL - то обеспечить чтобы каждая страница была доступна ровно по одному URL. С точки зрения поисковиков в общем это плохо, что есть куча страниц с разными URL, но с одними и теми же данными, просто выводящимися в разном порядке (это однако можно исправить добавлением метатега canonical).
А что такое "энтерпрайз"? Это большие, сложные проекты, которые обычно развивают годами, соответственно нужно чтобы фреймворк был пригоден для их написания.
Также, предполагается что в хорошем фреймворке есть какие-то готовые решения для часто встречающихся задач. Ну например, роутер. В некоторых фреймворках нет произвольных роутов, а используется схема вида /контроллер/экшен/параметры/параметры/. Эта схема позволяет сгенерировать много УРЛ для одной страницы, что негативно отражается на индексировании поисковиками.
Ну вот самый простой пример: допустим в фреймворке все контроллеры лежат в одной папке. В этом случае за несколько лет там может набраться сотня контроллеров и будет тяжело ориентироваться. А Зенд и Симфони позволяют разбить код на отдельные модули, в каждом из которых будут свои контроллеры.
Или неймспейсы: если фреймворк не поддерживает неймспейсы, то работать с кодом из множества классов будет неудобно.
Другой пример - поддержка DI. В зенде 1 кстати было много проблем, связанных с архитектурой, для DI там ничего не было, модели создавались где попало и по всему коду было разбросано new Model_Users.
Или более сложный пример: понадобилось сделать сайт двухязычным. С этим справится не любой фреймворк.
Плюс, предполагается что у авторов "энтерпрайз" фреймворка есть опыт работы с большими проектами и они знакомы с проблемами, которые возникают при их написании.
Еще для "энтепрайза" важна поддержка "стандартов" или чего-то похожего. Ну к примеру, стандарт на автозагрузчик, логгер, итд, чтобы не было такого, что каждая библиотека использует свой логгер и непонятно как их объединять. В Яве, которая считается "энтерпрайзным" языков, есть определенный формально процесс принятия стандартов JSR и самих стандартов довольно много:
У тебя форматирование очень странное, что за лестница?
Также, проверка на дабл стоит в конце и до нее выполнение просто не дойдет - раньше сработает одно из 3 предыдущих условий. В группе if/elseif/else сработать может только один блок.
Попробуй вместо mt_rand поставить даблы и посмотреть, что выйдет.
Здесь нужно выполнить расчет кредита, но для 3 разных комбинаций начальных условий. Здесь нам помогут функции. Мы создаем свою функцию расчета кредита, которая на вход получает его условия, а на выходе например возвращает сумму выплат. И вызываем эту функцию 3 раза, получаем 3 суммы выплат, которые и выводим на экран.
Урок в ОП посте читал про установку PHP? Ставишь PHP на компьютер, после чего ставишь IDE ("среду" как ты называешь) вроде Netbeans, Eclipse PDT (беспл), PhpStorm (платно) и в них настраиваешь расположение интерпретатора, чтобы они могли его запускать.
Лучше брать utf8, так как завтра у тебя встретится какой-нибудь хитрый символ в тексте, и не получится его сохранить. Также utf8 самая популярная кодировка и менее популярные кодировки могут какими-то функциями просто не поддерживаться. Хотя сейчас ситуация противоположная - регулярки (RLIKE) в MYSQL не поддерживают utf-8.
>>992664 https://ideone.com/PusPco Получилось нихуя не элегантно. Разучился думать уже. Если он имел совсем без функций, то как-то так. Если еще и форич убрать, то там немного по другому.
>>992712 Я просто не понимаю, где я не верно мыслю. Сейчас ход моих мыслей такой 1)Делается массив с данными всех одноклассников 2) Перебераю массив с помощью foreach 3) if рост анона < одноклассника, то прибавляю к количеству высоких +1
>>992734 Думаешь ты правильно. Вижу ты реализацию поправил - больше похоже на правду. Вернее правда и есть, ты ошибся в написании кода. Обрати внимание, что у тебя условие сразу же точкой с запятой закрывается.
>>992697 >Где токсичность-то? Запостил код в тред - получил комментарии. Одно дело просто код прокомментировать, а другое дело подчеркивать, что я основы ООП не знаю. Это как раз переход на личности.
По поводу его замечаний я ничего не сказал. С чем-то согласен, с чем-то нет, а что-то еще не изучал.
>Тебе ведь пишут, почему лучше так или иначе сделать, а не просто предлагают верить на слово. Да в том то и дело, что он просто пишет как считает лучше и мне вопросы задает, как будто я в Синагогу пришел.
Вот в голове не укладывается, почему когда я постил говнокод, его никто не комментировал, а когда стал более-менее что-то читаемое писать, то у меня вдруг все плохо стало.
Я согласен, на некоторую критику так же токсично реагирую, как пишут мне, я тоже человек и иногда у меня бомбит.
> if ($anonHeight < $height); Что делает этот if? if пишется в виде if (условие) { действия; } , а у тебя действия не указаны, и он ничего не делает в итоге (увы PHP позволяет такие кривые if писать).
В итоге у тебя $number++ выполняется на каждом шаге и просто считает число учеников.
То есть идея решения правильная, но написано неверно.
Ответ тоже неверный так как там по моему не 9, а 8 человек которые выше.
Путь надо указывать от корня проекта, то есть не models, а App/models. И кстати в PSR-4 неймспейсы (models) обычно пишутся с большой буквы (хотя в PSR это не указано).
>>992737 >я основы ООП не знаю Все верно, не знаешь. >переход на личности. Не льсти себе, какая из тебя "личность" >почему когда я постил говнокод, его никто не комментировал Потому что безнадежные дебилы никому не интересны. >а когда стал более-менее что-то читаемое писать А не совсем безнадежные - уже другое дело. >иногда у меня бомбит. >иногда Какие мы оптимисты.
> Вот в голове не укладывается, почему когда я постил говнокод, его никто не комментировал, а когда стал более-менее что-то читаемое писать, то у меня вдруг все плохо стало. Ну может некогда было, может не интересно, я не знаю, почему. Может я тогда просто устал каждому второму новичку разъяснять про устаревшие функции. Нельзя из этого сделать вывод, что код был лучше или хуже.
Тебе бы надо работу с массивами подучить. Не используешь готовые функции
- для поиска индекса элемента можно использовать array_search, а чтобы элементоы в массиве шли с правильными индексами - array_values. - для нахождения границ диапазона - min, max - для взятия куска массива - array_slice
>>992742 >Тебе бы надо работу с массивами подучить. Не используешь готовые функции Ты хоть смотри, что в треде происходит. Суть была в том, чтобы без функций это сделать.
>>992742 >Может я тогда просто устал каждому второму новичку разъяснять про устаревшие функции. Да понятно, что это дело добровольное дело, я ни от кого ничего не требую.
Я стараюсь уважительно общаться, не всегда получается, так что в конкретном случае извините, если кого-то обидел.
А индексы и элементы массива имеют названия сами по себе? То есть например : $num - это индексы, а $b - это массивы? Или им только самому переменные давать надо? И если так, то какой командой это сделать? foreach - это цикл, а он мне не нужен
>>992765 А оп у нас не тролль? Постоянно замечаю, что оп очень многого не знает, возможно он вообще почти нихуя не знает за пределами своих уроков и какой-то отдроченной теоретической базы, черт его разберешь, либо притворяется, но продолжает как заведенный бубнить одно и то же, даже если это уже к теме не относится. Прямо не оп, а дешевый бот для телеграма. Тут либо он тролль, либо не понимает действительно нихуя.
Массив состоит из элементов, у каждого есть индекс и значение. Индекс может быть строкой или целым числом, значение - любым типом данных. Массив оптимизирован для быстрого получения значений по индексу.
>>992775 Так я тоже гордый пхпдаун и жсодебил, джавапетух, шарпоотсос. Что делать то теперь, переходить на оскорбления опа каждый раз, как он теряет нить разговора? Просто игнорирую по итогу, но тред от этого в моих глазах скатывается все больше и больше.
>>992819 Вообще с командой вывода массива. То есть если я хочу в ответ содержание, то мне надо брать команду в фигурные скобки. А если хочу индекс, то не брать?
Всем здрасти! И как быть новичку,который алчет вкатиться (есть 4 месяца спереди для этого) и потом найти работу?возьмут ли?на фрилансе ль смогу немножечко заработать?
Поясните пожалуйста про дату, вот я создаю объект DateTime или функцию стандартную вызываю для получения времени, время текущее берется локально у каждого загрузившего скрипт? Или с сервера?
>>992769 Не гони, я охуел, когда он мне помог разобраться с SRP. А говно одинаковое разгребать тред за тредом - ты бы нашел в себе силы? Никогда не переходит на личности, не оскорбляет, за одно это ему респект. Да блядь везде где я работал если кто-то был чуть выше остальных - обязательно ЧСВ. Так что nice try, hommie.
>>992742 >Тебе бы надо работу с массивами подучить. Оххлол. >>992731 Вот и я думаю, нахуя? А представь, что это его тестовое задание для приема в говноконтору, так это вообще лол, что творится у вас, погромисты?!
>>992769 Оп хорош, не пиздите. Кроме ОПа тут со сколько-нибудь сложными проблемами никто помочь обычно не в состоянии, все выебистые мимокрокодилы предлагают какое-нибудь говно для хипстеров или накатить новомодную технологию, о которой дрочат в твиттерах. В проблематику не вникают, глубоких знаний нет, все пиздец поверхностно, оверхайпнутые решения от васянов, понты одни. Бесите, суки.
>>993098 >>993013 У опа тут чсв больше всех как раз, и вы дебичи его подкормливаете еще. В итоге сидите и жрете с восторженной рожей то, что он вам вываливает. И похуй, когда он дело говорит, но он и хуйню полную нести может и практикует. Охуенная тайна - оп не все знает и понимает. Но вот по факту главного авторитета этого треда он может даже в том, чего не понимает нести откровенную ересь, за которую не грех и штраф на работе въебать, и ему насрать на все будет, потому что вы поверите ему. В итоге выпустится вас таких полудурков под руководством опа на рынок допустим рыл 10 через годик, и каждый из вас будет получать смачного леща на этих прекрасных усвоенных от опа без оглядки вещей. Пусть учит, пусть советует что-то, но вот в том и дело, что он уже просто охуел пользуясь авторитетом, а с этими кадрами в том числе мне потом работать. Не все так подробно и терпеливо объясняют, как оп, когда пытаются нубам чем-то помочь. Как умеем - тем помогаем, тем не менее в ваших силах и такие советы принять, а не рожу воротить и выебываться. Допустим у меня 6 лет опыта, я могу ответить на большинство вопросов, которые тут задаются, притом в моих силах статьи писать по этому поводу, но я отвечаю коротко, так как сам привык по работе так разговаривать и кроме того не стоит подробнейший ответ потраченного времени. При желании можно понять, что я советую или переспросить, а не ждать когда вам абсолютно все разжуют и в рот выплюнут, как это оп делает. Вы его сделали каким-то ебучим идолом, пиздец тут из-за этого атмосфера нездоровая.
>>993211 Не умеешь развернуто отвечать, не стоит это твоих времени и усилий, но ответы других, кто так не считает, тебе не нравятся - проходи мимо, или оставайся, продолжай дальше выглядеть агрессивным, обиженным, неустроенным плебеем.
Аноны, объясните пожалуйста. Сделал вчера задание на генератор имен чуть с ума не сошел пока пытался слоги в одну строчку запихнуть. И я просто методом тыка скорее всего нашел как делать, но кое-что не понимаю: 1) Я сделал пустой массив $line[] и туда поместил $randomText, так? Но почему я не могу сразу сделать массив $line[$randomText]? Потому что $randomText уже часть другого массива? 2) Не понимаю как можно все написать в одну строчку с помощью точек, а не команды implode
>>993211 У тебя одни голословные утверждения, поэтому твои слова неубедительны. Хуже того - ты оскорбляешь анонов, но при этом что-то говоришь про нездоровую атмосферу. Алсо, раз ты с опытом, ответь на мой вопрос, с которым я сам пытаюсь разобраться: должны ли сущности всегда быть в валидном состоянии? Допустим, Comment всегда принадлежит какой-нибудь Article, это значит, что в ООП мире мы пишем вот так: class Comment { constructor(Article article) { this.article = article
Всё логично, комментарий не может существовать без статьи, к которой этот комментарий относится. Но я постоянно натыкаюсь на такой код: $comment = new Comment(); $comment->setArticle($article);
Проблема здесь в том, что Comment после создания находится в невалидном состоянии, нужно вызывать дополнительно какие-то методы, чтобы не получить комментарий, который непонятно к чему относится. Хуже всего то, что даже в Symfony формы маппят информацию на объект через сеттеры. Типичный пример использования форм: $form = $this->formFactory->create(CommentFormType::class, new Comment());
Какие ты можешь предложить пути обхода, компромиссы? Я вот нашёл ужё один у Фаулера и понял, что проблема не в формах симфони, а в людях, которые маппят формы сразу на сущности. ОП, если читаешь, отпиши пожалуйста тоже, что об этом всём думаешь.
>>993295 >Там видно, что "is not valid a uploaded file" вываливается, если не проходит проверка is_uploaded_file Точно. Но как мне узнать почему файл не загрузился?
У нас тут тред про программирование. Зачем тут обсуждать личность ОПа? Вам дали ответ - хорошо. Не дали ответ, или ОП что-то в спешке перепутал - напомните или уточните.
Пишите по теме. Не нравится ОП - сделайте свой тред или игнорируйте его посты.
Когда файл отправляется на сервер в POST запросе, PHP до выполнения скрипта сохраняет его во временную папку под именем вроде /tmp/xyz. Если ты или Слим его после этого куда-то переместили, то это уже не "временный" файл и к нему применять move_uploaded_file нельзя. Соответственно, если ты используешь объект Слима, внутри которого путь к файлу, то попробуй проверить, что это за путь и сравнить его с путем в $_FILES (где хранится первоначальный путь к временному файлу). То есть сдампь $_FILES и содержимое объекта с файлом.
В твоем примере в общем-то невалидное состояние кратковременное. Единственный риск там, что при модификации сущности где-то произойдет исключение и часть изменений не внесется, и сущность останется невалидной:
$comment = new Comment; $comment->setAuthor($author); // происходит исключение, следующая строчка не выполняется $comment->setArticle($article);
впрочем, если этот код внутри функции и исключение выходит из нее, то объект $comment будет уничтожен и проблемы нет.
Возможно, было бы "красивее", если бы изменения вносились как-то атомарно (код на псевдоязыке):
но это сложно реализовать, так как внутри modify скорее всего будет какой-то цикл который по очереди меняет значения свойств и мы возвращаемся к той же проблеме.
Потому проще признать, что сущность может быть иногда в невалидном состоянии, и проверять валидность в каких-то определенных точках, например, перед сохранением в БД. Это можно делать явно или через обработчики событий Доктрины.
Если какой-то код, работающий с комментарием, что-то делает с автором, то можно добавить дополнительную проверку:
if (!$comment->getAuthor()) { thrown new RuntimeException("Author must be non empty"); }
или
assert(!!$comment->getAuthor());
Если ты будешь изучать Доктрину дальше, ты там еще немало подвохов обнаружишь. Полезно их знать, чтобы до использования Доктрины в том или ином проекте оценить будущие трудности.
Что касается вопроса, если бы у нас сразу были все 4 слога, нам массив был бы и не нужен. Тот же проблема в том, что у нас слоги генерируются в цикле, по одному за раз. И надо где-то их сохранить до конца цикла. Для этого хорошо подходит массив - перед циклом создаем пустой массив (класть в него пока нечего), на каждом шаге генерируем и добавляем в него слог, а после цикла склеиваем содержимое массива в строку.
У тебя кстати код не совсем правильный, так как implode стоит внутри цикла. Зачем его делать несколько раз? Достаточно склеить слоги один раз.
> Потому что $randomText уже часть другого массива? $randomText это строка и ее можно сохранить в любое число массивов. Нет такого правила, что содержимое переменной можно скопировать только в один массив.
> Не понимаю как можно все написать в одну строчку с помощью точек, а не команды implode Для этого нужно перечислить все слоги явно. Например, так:
$result = $line[0] . $line[1] . ... $line[3];
Но не очень понятно, чем это лучше implode. Ведь если мы захотим сделать не 4, а 8 слогов, нам руками придется переделывать эту строчку.
Что-то сейчас sqlfiddle не открывается, показывает белую страницу, я может потом еще гляну.
По твоему вопросу: это задача на джойны, и она решается примерно так:
- джойним несколько таблиц, получаем все возможные комбинации записей из них - отсеиваем ненужные записи условиями ON, WHERE - группируем если надо - считаем аггрегатные данные для групп
Ну тут очевидно, что надо взять таблицу пользователей и к ней приджойнить статистику лайков. Сгруппировать по пользователям, чтобы в каждой группе были лайки, относящиеся к одному пользователю. Дальше возникают довольно сложные вопросы, вроде "если у нас есть группа, как посчитать число уникальных пользователей-получателей-лайков в ней, при условии что они могут повторяться" или "как посчитать число взаимных лайков (то есть записей, где 2 поля равны) в группе".
Для ответа на первый вопрос надо изучить возможности MySQL:
Что касается взаимных лайков - дам такую подсказку. Как посчитать число записей в группе, соответствующих определенному условию (например x < 10) ? Примерно так:
x < 10 вернет 0 или 1 SUM(x < 10) найдет число записей, где условие выполняется
Вот такая штука у меня получается. У меня несколько классов с зависимостями через создание объектов в конструкторах, и по логам видно что подключение происходит 3 раза за каждый проход всего скрипта, это ненормально ведь. Неймспейсы и компосер решат эту проблему? Или же DI? Я новичек, прошу сильно не пинать
Каждый раз, когда ты создаешь объект PDO (или объект-обертку над PDO), устанавливается новое соединение. Конечно, это неправильно. Нужно создать единственный объект и использовать его везде. И желательно без глобальных переменных и синглтонов, это описано в моем уроке по DI https://github.com/codedokode/pasta/blob/master/arch/di.md
В простейшем случае можно просто создать объект PDO через new, а затем создать все объекты, которые его используют и передать в них этот объект.
В более сложном случае нужен DI контейнер.
composer - это менеджер зависимостей (зависимостей другого уровня), он только помогает установить сторонние библиотеки и настроить автозагрузку.
>>993404 Спасибо. Забыл поменять название на что-то более хорошее прежде чем показывать. Это я для себя по быстрому делал. Я просто еще не мог разобраться, потому что думал, что можно вписать array_flip($cipher) и мне все станет как раньше, лол
>>993295 Мы работаем с бекендом, а значит в первую очередь нас ебет состояние базы. У тебя создается проекция сущности (комментария), но только после сохранения сущность реально будет существовать. Это - дополнительный слой абстракции, как мы его испjльзовать будем - другой разговор. Перед сохранением/изменением можно (и даже нужно) добавлять валидации, в данном случае на существование артикла. Не очень эффективно выглядит, но если параноя не дает покоя - самое оно. Совсем отбитый вариант - валидировать при вызове сеттеров (все свойства закрыты, сеттер проверяет наличие валидатора на нужное поле и проводит валидацию до установки поля вообще). Это совершеннейший психоз. зато поможет во время установки поля с невалидным артиклом узнать, что его в базе нет например. Практической пользы, на мой взгляд, это вообще не несет. Внешний ключ защитит от невалидного инсерта/апдейта на уровне базы, правда потом ты можешь нарваться на проблемы с сетевыми внешними ключами. Все это должно обеспечить тебе достаточную уверенность в целостности данных. Таким образом невалидное состояние у нас существует только во время создания/модификации проекции сущности во время исполнения скрипта, в базе в свою очередь все хорошо. И я думаю, что ты это знаешь, раз такие вопросы задаешь, но на всякий случай все карты на стол. Еще один момент. По большому счету установка полей в конструкторе и через сеттеры отличается почти ничем. Пока конструктор исполняется сам инстанс класса как бы уже существует и доступен из этого самого конструктора, включая его методы, включая жизненный цикл. Особой разницы тут нет, пока поля не будут установлены как планировалось комментарий считай невалиден какой бы ты способ не использовал, и если нагандонить будет ошибка, разница только в том, что конструктор скрывает этот процесс от пользователя и явно дает понять, какие зависимости имеются, что есть хорошо. Так что если хочешь - делай именно так. Можно так же создавать статичный метод типа create, занимающийся созданием объекта, или даже билдер, чтобы из внешнего кода все выглядело максимально наглядно (мой вариант для сложных сущностей). Относительно форм. Можешь попытаться как раз мапить формы в билдер сущности, если получится, из которого потом уже вызовом метода build создавать саму сущность, предварительно все проверив. Мы будем как бы заочно иметь все точно те же самые проблемы, но из кода все будет вгылядеть так, будто мы контроллируем все от а до я за счет еще одного слоя абстракции. Вот мы молодцы то, да? Но на мой взгляд это излишний код почти всегда. Нужно сказать, что проблемы это все по большей части философские. Любой из вариантов в действительности дает достаточный уровень контроля за счет валидаторов и внешних ключей, то есть получить невалидную сущность при качественно спроектированной модели будет непросто. Плюсы и минусы у них касаются только многословности реализации, твоего удовлетворения кодом и легкости его чтения. Должен сказать, что вариант с
$comment = new Comment(); $comment->setArticle($article);
на практике оказывается наиболее наглядным для большинства разработчиков и именно поэтому ты его и встречаешь часто.
>>993553 >>993548 Ну мне не полноценный фреймворк нужен. Я поставил https://medoo.in только для работы с бд. Один файл, 30КБ и запросы выглядят теперь нормально: $row = $db->select('content', '*', ['id' => 3200517]);
>>992701 > ты не должен додумывать, что будет возвращен именно объект Cat Если я использую метод класса, который всегда конструирует мне объект этого класса, то я могу быть уверенным, что get_class(Cat::get_instance()) === 'Cat' >>992715 > начинающиеся с 2 подчеркиваний Ты докопался до реализации, забив на суть.
Мдэ, надо стандарт для php-блоков дополнять и добавлять его в Idea. Мне правда нужен @return static и @property static $_blahblah
>>992504 > почему программисты такие токсичные Потому что профа такая. Чтобы быть хорошим программистом надо иметь много времени, потраченного на программирование. Для этого надо иметь много свободного времени. А для этого надо не иметь девушку. А это тащит за собой неудовлетворенность, агрессивность и последующее желание самоутвердиться за счёт кого-то другого. Ну и сублимация, куда уж без нее?
>>992710 Есть два варианта решения: 1. за линейку проходишься по списку и сравниваешь, увеличивая счетчик = O(N) 2. за логарифм сортируешь функцией sort, потом за линейку проходишься до первого элемента выше нужного. Вычитаешь из кол-ва элементов позицию этого элемента. От O(log N) до O(log N + N), но тут как повезёт
лол, апдейтнул одного студентика в базе, так забыл указать WHERE id = 3, так теперь в базе 31 студент с одним и тем же именем..как мне вернуть всё в зад? Я и так запарился придумывать имена этим мифическим существам. В гугле что-то про бинарные логи, нахуй так сложно? В 2017 году до сих пор не придумали CRTL+Z для баз данных?
ОП, я допилил студентов. Весь функционал реализован, но с ООП проблемы. В методичке сказано - все SQL запросы вынести в отдельный класс, но что тогда останется в классе Student/Абитуриент? Весь вся работа программа - это сохранение/вывод данных из базы. Сейчас имею такои методы в Database.php(раньше они висели в студенте) >connectDb() >addInfo() >updateInfo() >loadInfo($user_id) >getInfoAllStudents() >getInfoOnID() >foundUserId() >getFullName($user_id) >searchID($search_query)
Класс Student просто хранит информацию об одном студенте. А класс для работы с БД - содержит методы для записи и загрузки этих студентов из БД. Хотя, есть паттерн active record, когда обе этих задачи совмещаются в одном классе.
Нет, ненормально. Если в файле определяется класс или функции, то кода на верхнем уровне (не внутри функций) там быть не должно.
Ну и с точки зрения логики это ведь неправильно. Почему сессия должна создаваться в тот момент, когда подключается этот класс? тут логики нет. А если я подключу класс, но не буду создавать объект? сессия все равно запустится.
>>993871 Потому что ты видимо опечатался и вместо $word5[$text5] например $word5[$text4]. Там длины массивов разные у 5го и 4го. >>993874 Что-то у тебя не то с архитектурой.
>>991459 Готово 3/4. Делать админку сложнее всего. Пока код прошу не рейтить, там дохуя косяков, я еще не все исправил, что нарейтили раньше и накопились новые. Добью комментарии и буду рефракторить. Какие же уебищные названия у методов, все в разном стиле. Ну хоть папку с представлениями в порядок привел.
>>994062 Ошибка была из-за того, что, во-первых, я перед загрузкой проверял, что код ошибки равен 1, который означает, что файл превышает размер допустимый настройками php, а не 0. Вот я дубовая голова, перепутал индексы! И во-вторых ещё, загружал файл с размером больше допустимого.
Господа, столкнулся со слудующей проблемой. Просматривал один сайт и наткнулся на следующий код: <a href="#listOfBonusBlock" data-url="/main-page/json/bonuses/DEPOSIT/" class="jsonBlock btn btn-xs m-b-xs btn-default " title="">Бонусы за депозит</a> Конкретно не понимаю, что делает: data-url К слову сказать не нашел и доки по данному атрибуту. А на странице http://ru.casinoglobal.info/main/#listOfBonusBlock происходит очень интересная магия: при переключении кнопок. Как это возможно реализовать.
>>994193 >И смысл тогда этих постов? Мне интересно кто что сейчас пилит. А с точки зрения экзистенциализма, надо делать так, как хочешь чтобы все поступали. А я не прочь почитать чужие отчетики. Программирование, это не только абстрактные сущности, но и люди, мотивация.
Мне, например, не интересно в очередной раз читать как у кого-то массивы или циклы в голове не укладываются, но я им ничего не пишу.
>Вот в нофап-тред и кидай свои ежедневные отчёты и скрины. Обязательно, держу в курсе.
Собственно, вот моя позиция, ничьи права я не нарушаю, за сим уведомляю, что буду продолжать. Можете жаловаться модератору, ваше право, если забанят меня - тогда другой разговор.
Алсо, можете скрывать посты, которые только лично вам не нравятся, есть такая кнопка. Анон, будь терпимее.
>>994224 Я возмущён постом того анонимуса. От лица всех анонимусов ссу ему в ебало приношу глубочайшие извинения. Ну а кроме шуток, мотивируй, это интересно, такое нужно. В конфу нашу еще пропишись, там нужны такие замотивированные, как ты.
>>994246 >мотивируй Я акцентировал на том, что меня мотивирует, когда кто-то пишет о своих поделках. А то без этого создается впечатление, что только задачки про циклы решают или рокетсайнс занимаются, а по середине ничего.
Скачал свой же проект на Гитхабе. При переходе на любой линк кроме главного выдает Error 404. Apache/php 7.1. Фреймворк Laravel. В чём может быть проблема?
Ребят, у меня вопрос. Как можно реализовать что-то подобное бару нотификатии. Т.е. выдыется несколько сообщение, и нужно как-то их помечать прочитал их юзер или нет. Пока идея такая, смотреть находиться этот нотификайшен в области видимости и ajax'ом посылаем в базу запрос, чтобы там утановить read_date в значение не null. Нормальная идея или нет?
"массив совпадений с регулярным выражением" - я думаю, это массив, который заполняет функция preg_match. Если она нашла в тексте совпадение с регулярным выражением, то она сохраняет в массив такие элементы:
- под индексом 0 сохраняется часть строки, совпавшая с регуляркой - под индексом 1 - часть строки, совпавшая с первыми круглыми скобками в регулярке, если они есть - под индексом 2 - со вторыми круглыим скобками, если они есть
>>994668 В первой функции ты $.ajax вызываешь, а не свой метод ajax(). Член юпитера, какой же это омерзительнейший код, гори ты в аду, если не перепишешь
>>992681 >Мне кажется, тут кто-то кого-то не понял. Расписываю подробно. Есть файл manager.php, который первым делом проверяет, залогинился ли юзер. Если нет - редирект на login.php. Если да, то отрисовывает страницу, на которой есть кнопки управления. Допустим, одна из них "Показать таблицу". По нажатии на неё срабатывает js-скрипт, хватает введённые данные и отправляет их аяксом (type:"POST") в show.php. Там проверки на правомочность запроса нет, он просто выполняется. В начале скрипта стоит только header("Content-type: text/plain; charset=utf-8"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); Нужно поставить проверку?
Ты сделал неправильно. Ты защитил страницу, которая просто выводит кнопку, а обработчик запроса, который и выполняет действие - никак не защитил. Что мешает злоумышленнику сразу отправить POST запрос к скрипту show.php?
Важно представлять как работает веб-сайт, как взаимодействует браузер (клиент) и сервер. Все, что происходит за пределами сервера - полностью контролируется злоумышленником и он может слать любые запросы.
Попробуй сам нарисовать схему взаимодействия и ты увидишь слабые места:
клиент сервер
GET manager.php -> проверка -> вывод формы POST show.php -> выполнение действия
Я советую попробовать изобразить сеанс работы в админке с помощью такой диаграммы, и слабые места увидишь, и заодно правильно рисовать такие вещи научишься. На диаграмме можно сделать 2 вертикальных линии (браузер и сервер), браузер отправляет GET/POST запросы, а сервер проверяет авторизацию, выполняет какие-то действия, возвращает HTML страницы.
Там html-код выполняется только если авторизация пройдена. Но так вообще можно его оформлять? Обычно строки выводятся через эхо или принт. У меня работает.
Наверно, наилучшем решением будет хранение файлов на отдельном сервере, но поскольку это учебное задание, можно обойтись и одним, и просто переименовывать php\html файлы. Значит, нужно будет иметь в бд как и оригинальное имя, так и то которое храниться на сервере?
Чтобы получить оригинальное имя при скачивании можно добавлять в ссылку атрибут download="...", но это, наверно, не очень надёжно. Лучше при скачивании самому выставлять заголовки с помощью php. Это хорошо тем, что можно выставить в заголовке filename оригинальное имя файла, я прав?
>борьба с загрузкой HTML-файла: можно загружать файлы на отдельный от основного домен, можно при скачивании выставлять правильные заголовки, которые заставят браузер скачать файл, а не открыть его как веб-страницу (Content-Disposition: attachment, Content-Type не содержащий text/html) >Content-Type не содержащий text/html Почему нельзя содержать такой тип? Страница будет открываться в любом случае?
Я затрудняюсь на этом моменте потому, что чтобы выставить заголовки нужно вызвать отдельный контроллер, который будет это делать, вместо того чтобы давать прямую ссылку на файл. Здесь нету, какой-то серьёзной проблемы, просто я не хочу делать отдельный контроллер. Может здесь можно что-нибудь посоветовать? Хотя конечно вряд ли.
Генерацию директорий к файлу можно сделать проще - независимо от всего генерировать новую директорию для файла, и если файл с таким именем уже существует в директории, то рекурсивно заново вызвать эту функцию. Искать в ручную файлы, наверно, будет не удобно, но в любом бы случае пришлось бы первым делом смотреть путь в бд, если какой-то файл понадобиться.
Я правильно делаю, что передаю роутер в шаблон, чтобы сгенерировать ссылку?
А как делается мультиязычность? Это, наверно, делается с помощью middleware - сначала определяется какой язык должен быть, а потом передаются данные на нужном языке. Где эти данные лучше хранить? В бд или константах прямо в коде (например EN_TITLE, RU_TITLE)?
Вообще, код плохой. Ты пишешь большой сложный скрипт не пытаясь разбить его на функции, сделать более читаемым. У тебя там гигантские вложенные ифы.
Надо это переделывать. А то сейчас чтобы просто понять как это работает, надо долго вчитываться. Код должен быть проще:
проверить авторизацию; если (нет авторизации) { редирект и завершить скрипт; } если (параметры верные) { выполнить действие, отдать ответ и завершить скрипт; }
Сука, теперь придется MVC админки выносить в отдельную папку /admin, чистить модели /app от методов /admin, дрочиться с неймспейсами, чтобы юзать в /admin методы из модели /app
Пиздец, это еще на неделю. Ну все лучше чем в доту играть.
Тут лучше для каждого раздела админки сделать свой контроллер. Контроллеры можно поместить в отдельную папку и например унаследовать от какого-то общего предка, если надо.
Насчет моделей - не уверен, что с ними что-то надо делать. Обычно не требуется делать отдельные модели для админки, но если у тебя не соблюдается MVC и модели это на самом деле контроллеры то конечно возможно варианты.
Чуть переписал роутер, чтоб он искал контроллеры в другой папке, если первый элемент пути в ссылке будет 'admin'. Осталось раскидать этот жирный контроллер. А модели и правда нет смысла разделять, только сильнее запутаю.
Чет я просто сначала запаниковал и расстроился. Теперь не все так плохо выглядит.
>если у тебя не соблюдается MVC и модели это на самом деле контроллеры то конечно возможно варианты Оп говорит, что я там хуйни наворотил и вообще не шарю, но вроде модели и контроллеры не перепутаны, методы моделей инкапсулировал как мог.
Есть таблица с 50 колонками и пару тысячу строк. Что лучше, загрузить большой объем данных и обрезать его в пхп, или делать много запросов и получать маленький объем данных?
>>995060 Слушай, я по случаю тоже сижу в ноуфап треде. Может сверстаем ОПу годный сайт на бутстрапе? Будем его поддерживать вводить новые фишки, такой-то опыт командной работы.
>>994741 Переделал. - Перешёл с простого mysql на PDO. - Перенёс отрисовку страниц в отдельные файлы шаблонов, типа manager.html. - Переписал скрипт проверки, убрав вложенность условий. Работает теперь так: если нет куков - отфутболить. Если есть, проверить соответствие в базе, не прошло - отфутболить. Если всё ок - ничего не делать. - Сам скрипт перенёс в отдельный файл protection.php https://jsfiddle.net/3v48dsgo/
В управляющих скриптах страниц мало что осталось. Например, manager.php: // Скрипт проверки include('./protection.php');
// Это используется при отрисовке шаблона $user_id = $userdata['user_id'];
>>995123 >сверстаем Я сейчас не собираюсь в верстку углублятся, освоил азы бутстрапаи и пока хватит. После цитатника надо Зандстра добить, а это надолго. Да и личного интереса нет, не цеплет меня идея.
Алсо, смотрел исходники его сайта, там класов и пространства имен нет, каждая функция в отдельном файле. Первый раз такое вижу. Я особо не пытался разбираться, но вроде, с бэком у него все норм раз работает https://nofap.ru/files/nofap-28.02.2k17.tar.bz2 Да и дизайн пойдет, менять его голый бустрап, что шило на мыло.
>>995201 Собственно схуяли? Работа сдалана вот и заебись. Я щас сайт для заказа шлюх сделаю и в портфолио он у меня будет красоваться повыше остальных из-за сложности.
>>995201 Я свой в гитхабе собираюсь оставить, то в очередь платформа для коллекции любых цитаточек. Да и если название достойное придумтаь, то можно и цитатки оставить, благо там нормальные авторы.
А нофа да, спецефический ресурс, случайному человеку даже объяснять будет стыдно нахуя он нужен. Хот видно, что работы там дохуя проделано.
>>995206 >Я свой в гитхабе собираюсь оставить Правда, я там почти все оставляю, чтоб прогресс было видно, а его видно. Только в ридми пишу, что говно, но переделывать не собираюсь
>>995259 >Постоянно показывать всю таблицу пользователям? Один раз обработать данные? Ну смотри, у меня на сайте есть несколько хтмл таблиц, разбитые по категориям. Я могу сделать один запрос к БД и уже в пвп разрезать всю огромную таблицу на несколько мелких. А могу сделать несколько запросов с выборкой только нужной категории под каждую таблицу на сайте. Будь у меня таблица в БД не такая большая с кучей текста, я бы сказал, что мне абсолютно похуй. Но теперь я хочу знать, что лучше один запрос, который возвращает дохуя, или штук десять разных, которые возвращают каждый 1/10 всей таблицы.
Не знаю, где лучше спросить, спрошу здесь. Пишу код (пхп, цсс, жс) и копирую каждый раз его по фтп на веб сервер (на хостинге, там вся начинка сервера принадлежит хостеру и я о ней не парюсь), а потом проверяю в браузере, чего получилось. И мне таки надоело каждый раз делать это копирование с подтверждением замены. Да ещё фтп каждые 10 минут отваливается. Вижу стулья: 1) У нас в конторе в качестве шлюза используется виндовс сервер. На нём стоит iis7. Настроить на нём сайт так, чтобы он был виден из интернета (по ип) и редактировать код прямо на нём. Плюс доустановить пхп, майскул и т.д. 2) Поставить там же Топ сервер или Денвер и получить всё это из коробки. 3) Поднять вируалку в сети, воздвигнуть на неё ЛАМП, сделать проброс портов (или что там нужно) и таки получить доступ из интернета к тестовому сайту.
Эти стулья - действительно стулья, или всё делается как-то иначе? Мне нужно избавиться от лишних действий при разработке.
>>995669 В шторме есть возможность работы с проектом, находящимся на удаленной машине. К примеру через SFTP. Минусы - синхронизация на локалке (выкачка) может быть долгой. В остальное же время сидишь и работаешь, как с локальным дерьмецом. Лучший вариант все же развернуть виртуалку (глянь в сторону вагранта кстати) у себя с шаред папкой под проект. Настройки окружения, конечно, с тебя. Можно еще прямо на локалке все ебенить, это уж если тебе так нравится.
Я обычно пишу скрипт для выгрузки на сервер на bash, чтобы не надо было вручную ничего делать. В случае с FTP, есть консольная программа lftp, которая умеет синхронизировать файлы с учетом даты изменения, единственный ее недостаток - она всегда возвращает нулевой код ошибки независимо от результата копирования.
Если ты не лобишь консоль то может можно найти или купить программу, которая копирует файлы одной кнопкой.
Копировать файлы на удаленный сервер довольно неудобно и конечно лучше развернуть копию проекта локально. Если он не работает под виндой, можно попробовать поставить линукс без GUI в виртуалбокс.
Насчет IIS - я с ним не работал, но как минимум htaccess в нем не поддерживается и тебе придется писать конфиг аналогичный тому что на линукс-сервере.
Аноны, вот такой вопрос. Есть скрипт, который загружает на сервер файлы и их имена записывает в БД, и в итоге оповещает об успешной загрузке, либо же об ошибке. Сейчас, файлы ни как не загружались и на выходе было лишь сообщение об ошибке без указания причин. Display_errors выставлен в on, error_reporting E_ALL. Как оказалось, размер файлов всего лишь немного не умещался в upload_max_filesize и post_max_size. Так вот, должны ли приходить оповещения о причинах, при подобных проблемах, или я что-то упустил?
Превышение размера не вызывает генерацию ошибки, просто в поле error проставляется соответствующий код. Это уже твоя задача его проверять и выводить сообщения.
> preg_split('/\r\n/iu', Вот здесь проблема. Конец строки может обозначаться по-разному в зависимости от ОС и настроек редактора. В блокноте на винде он обозначается как последовательность 2 символов \r\n, но в том же линуксе или маке по умолчанию используется только \n. Соответственно твоя программа может работать некорректно если используется не тот формат конца строки. Лучше разбивать строки по \n, а символ \r (если он есть) вырезать с помощью trim().
Определить самую длинную строку можно короче, если использовать array_map: сделать массив длин строк и взять максимальное значение в нем.
> for ($j = 0; $j < count($sentences); $j ++) { Тут лучше использовать foreach
shared folders (когда на хосте поднимается NFS- или SMB-сервер, а в виртуалке - клиент) могут работать намного медленнее обычных папок. Я исопльзую скрипт, который находит изменившиеся файлы с помощью find, создает список и копирует их через rsync.
Хотя может на быстром железе разница не так заметна.
Один запрос наверно быстрее, но я не очень понимаю, зачем тебе столько данных, ведь пользователь вряд ли способен просмотреть 50 000 записей на одной странице, да и браузер будет тормозить наверно.
Теперь тебе надо осваивать функции (вспомогательный код надо писать в виде функций, которые можно вызвать), и конфиги (чтобы не копипастить данные подключения к БД).
Вообще, ты неправильно учишься. Вот зря ты спешишь браться за базы данных и делать сайт, когда ты не освоил функции и не научился разбивать код на кусочки, а не писать стеной. Я бы тебе конечно посоветовал почитать комментарии к задаче про студентов из ОП поста, там очень много советов. А пока ты пропустил много важных тем и берешься за сложное, не выучив основы.
Я как-то видел большой проект, написанный человеком который как раз не выучил основы, там был адский код, огромные стены кода, в которых просто разобраться нереально. Потому что человек не научился писать читаемый, понятный код, а писал как умел. Есть кстати книга "Совершенный код", если захочется, можешь почитать, хотя она не про PHP написана, но большинство советов подойдут и к PHP.
Я кстати всем анонам советую посмотреть эту книгу. Есть разница между написанием простых скриптов из 20 строчек и больших приложений, и книга вам про нее расскажет. Там есть хорошая аналогия - нельзя строить небоскреб теми же инструментами, что и собачью будку, нужен другой подход.
> header("Location: status_codes.php?result=401"); exit(); Это тоже что-то ненормальное. Редиректить надо на страницу логина. А если ты хочешь выдать ошибку с кодом N то ее надо выдавать сразу, а не через редирект, так как редирект это код 302. Это ошибка, если ты например вместо выдачи страницы с кодом 404 редиректишь на какой-то URL вроде /not_found.php.
Что значит "загрузить картинку на URL"? Отправить POST-запрос с картинкой по протоколу HTTP? Тогда нужен HTTP-клиент, например curl, который встроен в PHP, или библиотека Guzzle, которая сделана с использованием ООП.
> можно обойтись и одним, и просто переименовывать php\html файлы. Значит, нужно будет иметь в бд как и оригинальное имя, так и то которое храниться на сервере? Переименовывать надо в любом случае, так как могут быть файлы с одинаковыми именами, с нечитаемыми символами, файлы с названием .htaccess которые переопределяют настройки веб-сервера, .gitignore которые влияют на git и тд.
> Чтобы получить оригинальное имя при скачивании можно добавлять в ссылку атрибут download="...", но это, наверно, не очень надёжно. Лучше при скачивании самому выставлять заголовки с помощью php. Это хорошо тем, что можно выставить в заголовке filename оригинальное имя файла, я прав? Нельзя, так как в HTTP заголовках можно использовать только символы ASCII (не так давно добавили возможность указывать кодировку и вставлять символы не из ASCII). атрибут download работает только в относительно новых браузерах. По моему в комментариях к задаче написано, что самый надежный способ, работающий везде - это поместить имя файла в конец URL.
Отдавать файл в идеале лучше всего веб-сервером, а не PHP, опять же это по моему описано в комментариях к задаче.
> Почему нельзя содержать такой тип? Страница будет открываться в любом случае? Не помню, почему. Может стоит проверить экспериментально? Если attachment не указан, то браузер смотрит на Content-Type и если тип ему знаком, пытается отобразить содержимое, иначе предложит сохранить. А если attachment указан, то по идее должен сразу предложить сохранить.
Может это защита от какой-нибудь уязвимости, когда злоумышленник загрузит HTML-файл и попытается как-то с его помощью украсть например куки пользователя пользуюсь тем, что файл находится на том же домене что и сайт. Не помню.
> Здесь нету, какой-то серьёзной проблемы, просто я не хочу делать отдельный контроллер. Может здесь можно что-нибудь посоветовать? Есть такие варианты:
- отдавать средствами PHP - ставить заголовки и передавать отдачу серверу через X-Sendfile (Апач), X-Accel-redirect (nginx). Это обычно используется для учета и ограничения скачиваний, когда перед скачиванием запускается php скрипт. - написать правила для веб-сервера так, чтобы по определенной ссылке он отдавал файл с указанным в ней именем. Вроде такого: ссылка имеет вид /download/1.txt/название.txt и по ней отдается файл, хранящийся под именем 1.txt.
> я не хочу делать отдельный контроллер. Ну это слабый аругмент. Есть возможность скачивания файла, логично для нее сделать контроллер.
> Генерацию директорий к файлу можно сделать проще - независимо от всего генерировать новую директорию для файла На каждый файл свою папку генерировать - не очень эффективно, рекурсивный обход всех файлов будет медленнее из-за этих папок (хотя я не тестировал, у меня есть такое ощущение). Лучше всего по 100-1000 файлов в папку класть.
> Я правильно делаю, что передаю роутер в шаблон, чтобы сгенерировать ссылку? Так можно делать, но по моему опыту лучше сделать свой класс-генератор ссылок, это лучше по таким причинам:
- мы передаем в шаблон именно генератор ссылок, а не роутер, который содержит избыточные, ненужные функции - в своем классе можно дописать дополнительную логику, проверки. Без него эту логику придется размазывать по шаблонам. Явно нарущается какой-то принцип написания хорошего кода (DRY?)
Хотя может для маленького проекта это лишнее усложнение. Но мне все же кажется что полезно так сделать.
Вместо переменных для защиты от CSRF удобнее передавать сам объект в шаблон.
> А как делается мультиязычность? Это, наверно, делается с помощью middleware - сначала определяется какой язык должен быть, а потом передаются данные на нужном языке. Где эти данные лучше хранить? В бд или константах прямо в коде (например EN_TITLE, RU_TITLE)? Не, middleware тут не поможет, надо закладывать в архитектуру.
Стоит наверно сделать разные URL для разных версий страниц, иначе нельзя дать ссылку на страницу на определенном языке и они не будут нормально индексироваться. Википедия напримр использует на каждый язык свой поддомен. Можно использовать и папку в URL.
Насчет БД - есть 2 варианта: либо делать несколько колонок, либо выносить переводимые части в отдельные таблицы (например вида (fileId, language, description)). То есть либо располагать переводы "горизонтально" (в одной строке в разных колонках) либо "вертикально" (в разных строках).
Более того, бывает, что перевода нет. То есть есть статья на одном языке, а на другом языке перевод пока не готов. Или решено его не делать. Нужно решать, что делать в таком случае.
Далее, надо перевести интерфейс и сообщения в коде. Тут решение давно известно - gettext или аналогичный велосипед. Мы оборачиваем все сообщения в вызов функции, например:
echo message($language, 'File uploaded successfully'); // выведет фразу на текущем языке
Затем мы скриптом-сканером извлекаем список фраз и отдаем переводчикам. Они дают нам список переведенных фраз, мы его загружаем в программу и при выводе выбираем нужную фразу.
Как я написал выше, есть расширение gettext для этого. В нем есть функция перевода (с коротким именем _), сделаны форматы файлов для хранения переводов, и есть готовые программы для работы с переводами (например Poedit).
gettext используется не только в PHP, но и в других языках программирования. Советую его изучить.
Далее, в фразы иногда надо подставлять переменные. Например:
- Иван написал новый пост
Подход вроде echo $userName . message($l, 'написал новый пост'); не сработает, так как в некоторых языках имя "Иван" может оказаться в середине или конце фразы, и переводчикам неудобно работать с куском предложения.
Далее мы наткнемся на еще одну проблему. Фразы (внезапно) могут меняться в зависимости от пола, числа предметов:
- Иван загрузил 3 фотографии в альбом - Маша загрузила 5 фотографий в альбом
И, что еще веселее, формы слов и правила их использования в разных языках разные. Решается это с помощью введения синтаксиса для подстановки переменных в фразы, для выбора варианта слова в зависимости от условий:
Стандартный формат хорош тем, что переводчики могут быть с ним знакомы, плюс могут быть инструменты для работы с ним. Не вижу особой выгоды изобретать тут велосипед.
Ну еще из мелочей - в разных странах разные форматы вывода дат, дробных чисел (точка или запятая), денежных сумм и валют. Это решается созданием соответствующих функций, или использованием классов из расширения Intl: http://php.net/manual/ru/book.intl.php
Ну и стоит почитать про Юникод, может там еще какие-то подвохи по мелочи есть. ну например, если ты хочешь написать регулярку для проверки имени, надо учитывать, что имена в разных языках могут содержать символы разных алфавитов. Может тут стоит использовать символьные классы вроде \p{L}.
Еще есть языки, где текст пишется справа налево, а чтобы жизнь медом не казалась, иностранные слова там пишутся слева направо. Соответственно надо изучить возможности HTML/CSS (атрибут dir и соотв-е свойство), а также юникодные символы выбора направления вывода текста.
В общем, простор для изучения тут большой. Начни с gettext и Intl.
Кстати, я делал небольшой двухязычный сайт и участовал в интернационализации большого проекта. Там, я помню, даже была сделана отдельная админка для переводчиков.
Не очень, так как юзер мог переключиться на другую вкладку или отойти от компьютера. Хотя если уведомления неважные (Маша поставила лайк) то можно и так.
Привет. Решил к вам вкатиться в ваш уютненький добрый тред. Сам опыта имею только на делфи образца 2007 года и то всё забыл. Так что если будут советы, я буду только рад. Указывайте на косяки в коде и даже на форматирование, лучше я этому сейчас научусь, чем привыкну и стану писать всегда.
Пытаюсь учить SLIM. Допустим есть поле для ввода и кнопка, по нажатию на которую я хочу формировать новый URL вида site.com/entered_text Я знаю, что нужно вешать метод в контроллере на сабмит в форме, но как сформировать URL?
>>996038 >> Генерацию директорий к файлу можно сделать проще - независимо от всего генерировать новую директорию для файла >На каждый файл свою папку генерировать - не очень эффективно, рекурсивный обход всех файлов будет медленнее из-за этих папок (хотя я не тестировал, у меня есть такое ощущение). Лучше всего по 100-1000 файлов в папку класть. Чтобы посчитать сколько файлов в текущей папке нужно сначала определить есть ли текущая папка вообще (на случай если файл загружается впервые), затем посчитать сколько в этой папке файлов, и определить есть ли там файл с таким именем. Получается довольно большой блок условий. А если генерировать новую директорию в любом случае, то этот блок сократиться только до проверки существования файла с таким именем а если каждый раз ещё и переименовывать файл, то можно обойтись и без неё. Рекурсивный обход файлов будет долгим в любом случае.
>>996049 >>996051 >Пытаюсь учить SLIM. Допустим есть поле для ввода и кнопка, по нажатию на которую я хочу формировать новый URL вида site.com/entered_text >Я знаю, что нужно вешать метод в контроллере на сабмит в форме, но как сформировать URL? В форме ставишь action="/entered_text" и в контроллере обрабатываешь пост-запрос $app->post('/entered_text', ...).
>И еще поясните, как правильно в MVC - где строить запрос к бд, в модели или в контроллере? Зависит от архитектуры. Обычно всё делают в модели.
Во-первых, у меня вообще какой-то инфернальный пиздец в строке появляется после нажатия на энтер в текстовом поле. Да, в форме стоят невидимые поля CSRF, но я их не прошу выводиться нигде.
Во-вторых, если я сюда $app->post('/', 'HomeController:postHome'); в адресс поставлю какой-то текст (как вообще я этот текст из формы вытащу в файл роутов?), то этот пост уже будет обрабатываться не по моему изначальному адресу. Госпаде, ну что за пиздец накрутили, я уже полностью запутался.
>>996071 Что значит зачем? 99% сайтов со строкой поиска по своей базе так делают, чтобы было удобнее очевидно. Вот пример: в форме на сайте ввел текст - получил его в URL. Как сделать так же?
>>996072 Так а причем тут урл? Поиск осуществляется по базе, после чего пользователю выдаются результаты/результат, или редиректится на единственный результат например. А вообще тема поиска по сайту - больная мозоль у всех, нихуя не изич.
>>996073 >Поиск осуществляется по базе, после чего пользователю выдаются результаты/результат, или редиректится на единственный результат например. РЕЗУЛЬТАТА НА 123 НЕТ. Нет, понимаешь? Введи 321 или 927384658728346неп9арш7 и это все уйдет в урл. Так что дело не в поиске, а в том, как засунуть это в URL на подобие вот таких сайтов.
>>996072 Если уж хочешь урл, то это searchQuery или подобный этому параметр. Находится в урле по той причине, что по канонам форма поиска отправляется гет запросом и, как ты должен знать, все параметры в адресную строку для гетов и попадают. Судя по скринам у тебя post запрос, поэтому и нет нихуя. Хочешь получить - осуществляй из контроллера редирект по урлу с установленным параметров. >>996075 Все гораздо интереснее там. И чем обширнее база и критерии поиска - тем веселее.
>>996076 Согласен, пост не по канонам для поиска, поэтому я переделаю в гет, чтобы было не /name, а ?name=name. Но тогда вылезает другая проблема: какого хрена у меня в урл лезут эти скрытые поля и как их убрать оттуда, оставив при этом проверку CSRF?
>>996076 хз что там интереснее. Если ты делаешь поиск именно по контенту, то делается именно так. А контент весь обычно хранится в бд. В итоге всё сводится именно к этому запросу.
>>996080 Ну, мне было интересно. Как только перед тобой встает необходимость реализации полнотекстового поиска по сайту (будь то даже имена пользователей) база уже почти бесполезна, будет работать как дерьмо. Тащишь значит готовое решение, сфинкс например, индексируешь им свой терабайты данных, охуеваешь. Потом расширяются критерии поиска - расширяется индексация, добавляются новые индексы. Это все еще и обновлять своевременно надо, а то будет по устаревшему говну искать. В целом да, не особо тяжело, но проблем с ним много обычно. Ну это из моей практики, почти всегда с фултекстом нужно было реализовывать. А без фултекста я только по анкетам юзеров делал на сайте знакомств, там да, и без этого всего обошлось. >>996077 Честно не знаю. Могу только сказать, что если у тебя этот гет маршрут ни в коем случае не меняет данные на сервере и безопасен, то csrf там не нужен по сути своей.
>CountPage >showLinkPage >getLinkSort Куда этоти методы тулить в студентах? Ну не в класс студент же и не в контоллер, так как там вычисления производятся. Хелпер тоже не для этого.
>>995722 >>995672 Решил обойтись существующим винсервером. Запустил на нём OpenServer, прописал домен и алиас для него. С самого сервера сайты открываются. А с другого (в той же локальной сети) - нет. Блядь. Со вчерашнего дня настраиваю - не работает. Что там не так - в душе не ебу. Веб сервер должен хоть что-то показывать. Блядь, зла не хватает, заебало, блядь, блядь, блядь, как же заебало всё нахуй блядь.
Ответьте кто-нибудь, почему у меня ресурсы иногда тайпкастятся в integer? Два разных проекта. Два совсем разных куска кода. protected-поля, в которые пишется resource, через некоторое время по какой-то причине resource становится числом из id этого ресурса. Причем даже типы ресурсов разные. В одном месте это fopen, в другом месте это сетевые стримы из stream_socket_accept.
PHP 5.6 (7.0 есть, но на нём я не тестировал) Почему?
<?= $question->question_type_id == 7 ? '<i class="fa question-text" data-id="trq_<?= $number?>">': 'NON EXIST'?> В этом случае почему-то не срабатывает <?= $number?>. Как исправить? Нужно что-то как-то экранировать?
>>996037 >Вообще, ты неправильно учишься. Честно говоря, такой ответ сильно демотивирует. Я пытался учиться "классическим способом", когда берёшь толстенную книгу-кирпич и выучиваешь первую главу. А потом делаешь к ней упражнения. Потом выучиваешь вторую. И делаешь упражнения. Потом выучиваешь третью. И так всю книгу. Но вот нихрена у меня не получилось освоить таким образом. Это нужно иметь железную армированную жопу, чтобы всё проработать, понять и запомнить. Это нудно, бесконечно и требует конского терпения. И практического толка от этого никакого. Потому что выучил ты книгу - а тебе говорят "пошёл нахуй, у нас тут паттерны, фреймворки, гит и прочее, чего в книге нет. Вот ещё десять таких же кирпичей, выучишь - приходи".
Нужно, как минимум, параллельно работать над настоящими проектами. Иначе эти знания уйдут в песок и забудутся. После зазубренного "Идеального программирования" можно идти преподавать это программирование, но не работать.
Плюс, карьера вида "два года буду учить в вузе, потом подрабатывать стажёром, потом диплом, потом мидл, а через 10 лет, к 26 годам - тимлид" мне не грозит. Потому что возраст давно не тот и на работу программистом никто не возьмёт (на любую должность). Так что, пишу для себя.
У меня другой способ обучения: 1. Сформулировать, чего хочу и придумать, как это реализовать в целом. 2. Гуглить примеры и копипастить из них. 3. Хуячить код. 4. Когда программа начинает работать и делать всё, что от неё было нужно (по самому минимуму) начинаю переписывать, упрощать, делать "защиту от дурака", работать над дизайном. Параллельно почитываю всякие душеспасительные статьи и гайды.
Работая по этой схеме, каждый следующий проект получается лучше, чем предыдущий. Да, знаю, мой код - говно. Но по другому я не могу. Ну не могу я прочитать учебник английского и начать тут же шпарить на нём с выговором коренного жителя Бристоля.
>Это ошибка, если ты например вместо выдачи страницы с кодом 404 редиректишь на какой-то URL вроде /not_found.php. Не совсем понял. В скрипте проверяется наличие куков и совпадение их содержимого с содержимым базы. При отрицательном ответе редиректит на страницу, которая смотрит причину редиректа и показывает соответствующую ошибку. Ладно, может и не прав. Объяснять, где именно, не надо - это пока мне не нужно.
>>996473 >у нас тут паттерны, фреймворки, гит и прочее, чего в книге нет На самом деле нет ничего важнее, чем хорошо наработанный базовый навык кодинга, а все остальное уже прикладывается. Есть у меня один чувак, он дохуя технологий типа знает, но написать нихуя не может по итогу, спотыкается на любой простейшей вещи. >Нужно, как минимум, параллельно работать над настоящими проектами. Это да. Нужен баланс между настоящими проектами и повышением скила. Притом не только во время начального обучения, а всегда.
Сегодня начал делать задание по файлообменнику, и сразу появилось много вопросов. >злоумышленник загружает свой php-скрипт, вызывает его через браузер (http://example.com/uploads/script.php) и получает контроль над сервером То есть надо как-то делать папку uploads открытой? Или можно сделать маршрут (test.ru/{w+} например), который будет вести на определенный контроллер, и тот уже будет обрабатывать запрос и отображать соответствующий файл? Мой тупой мозг только такую схему понимает. И можно ли сделать на изображения и остальные файлы две отдельные таблицы в базе данных?
>>996518 Я бы сделал отдельную модель от которой бы унаследовал другие модели, где нужны перечисленные тобой методы. Ну или можно передать её в конструктор, вместо наследования, забыл как этот паттерн называется.
Поставил LAMP, импортировал sql таблицу с винды, в итоге ее вывод на сайт дает вопросы вместо русских букв.англоввод в порядке Если смотреть в phpmyadmin то все с таблицей ок. Чяднт?
>Есть массив. В нем N+1 чисел. Все числа принимают значения от 1 до N. Нужно указать, какой элемент в массиве повторяется. Повторений может быть сколько угодно. Нужно это сделать за линейное время и константу памяти.
Я так понял условия:
1. Каждый элемент может быть от 1 до N 2. Только один элемент имеет повторения, которых может быть сколько угодно (от 0 до N?) 3. Линейное время https://ru.wikipedia.org/wiki/Временная_сложность_алгоритма получается, мы можем обратиться к каждому элементу только один раз? 4. >Константа — некоторая величина, не изменяющая своё значение в рамках рассматриваемого процесса. Мы берем некий кусок памяти перед началом и не превышаем его до конца работы алгоритма?
>>988868 (OP) Объясните по поводу вордпресс, вот допустим я хочу создать определённый функционал на отдельной странице, в котором будут использоваться формы и всё-такое. Как мне это сделать? Просто создать страницу в теме вордпресс, подключить к неё ядро вордпресс и начать писать там свой функционал? Но если так делать то адрес к этой странице будет кривой. А если сделать просто статическую страницу через админку, то на ней не будет работать ПХП код, как поступить?
А ты знаком с хуками в вордпрессе? Они позволяют изменять поведение движка и например добавлять выполнение определенных действий на отдельных страницах.
Также, в вордпрессе есть шорткоды - некоторые делают нестандартные элементы через них.
Наконец, еще по моему есть возможность использовать отдельный php-шаблон для отдельной страницы.
В общем, если ты еще не читал документацию для разработчиков, то самое время этим заняться.
> получается, мы можем обратиться к каждому элементу только один раз? Нет, ты не совсем так понял "O-нотацию". Эта нотация вроде O(1), O(N), O(N^2) задает ограничение скорости роста функции. Проще наверно объяснить на примере.
Допустим, время выполнения алгоритма есть O(N^2), где N - объем входных данных. Это значит:
- при больших N (больше определенного числа N0) - при увеличении объема входных данных в x раз время выполнения алгоритма вырастет не более чем в x^2 раз
Обрати внимание на первый пункт. Ограничение выполняется только при условии что N больше определенного числа N0, а если N меньше, то оно может не соблюдаться. Но если мы будем увеличивать N, то рано или поздно, это условие сработает.
Второй пункт обозначает что O-нотация задает не абсолютные значения (время в секундах в зависимости от размера массива), а как это время изменяется при увеличении объема входных данных. O(1) - значит что при любом объеме входных данных (и при N > N0) время не превышает определенной постоянной величины. O(N) - что время выполнения растет пропрорционально объему входных данных. И так далее.
Если у нас есть 2 алгоритма, со сложностью O(1) и O(N), и дано например N = 10 то нельзя сказать, какой из них быстрее. Можно только сказать что при росте N рано или поздно второй алгоритм окажется медленнее.
Потому сложности O(N), O(N + 1) O(2xN + 1) - это одно и то же. Так как они все растут линейно, и скорость их роста, хоть она и разная, но не меняется со временем. А вот у O(N^2) скорость роста увеличивается со временем, потому это уже другая сложность.
Я попытался это изобразить на графике. Видно что первая (синяя) функция ограничена горизонтальной линией, и при стремлении N к бесконечности она не превышает ее. Значит, сложность первого алгоритма ограничена O(1) (хотя сама пунктирная линия не обязательно соответствует графику функции y = 1, а вполне может быть y = 10, но O(10) и O(1) это одно и то же). То есть мы можем сказать, что при увеличении объема входных данных первый алгоритм будет работать примерно за такое же время.
Вторая функция со временем начинает возрастать почти линейно, и при стремлении N к бесконечности не пересекает наклонную линию. Это значит, что сложность алгоритма линейная, O(N) и время выполнения при больших N увеличивается пропорционально объему входных данных.
Возвращаясь к твоей задаче:
- ты можешь обращаться к элементу сколько угодно раз, но при увеличении объема входных данных время выполнения должно расти линейно.
> Мы берем некий кусок памяти перед началом и не превышаем его до конца работы алгоритма? При увеличении объема входных данных потребление памяти не должно расти (разумеется, массив с входными данными при этом не учитывается). То есть, если твой алгоритм например делает копию входрного массива, то это условие уже не выполняется. Но если твой алгоритм например создает массив из тысячи элементов - это допустимо, лишь бы его размер не превышал этой тысячи ни при каких условиях.
Господа, ебусь с отловом ошибок, чтобы поисковики и пользователи их не видели. Есть желание, чтобы вместо страницы с кодом ошибки я мог вывести свой текст. Пока вот что за говно получилось. Поделитесь своей мудростью.
Я правильно понял, что либо я страницу с кодом ошибки передаю, либо делаю редирект на страницу для пользователя где "Хуё-моё, администратор уже выехал...", но тогда никаких кодов а заголовке?
>>997033 Все что ни возьми - не подходит под хотя бы одно условие: встроенные функции использовать нельзя (время, память), сохранять в массив и проверять по ключу нельзя (память), нельзя решить короче вот... https://ideone.com/Y83B35
Также, оформление кода у тебя ужасное. Не придумывай свои правила, а оформляй по PSR-1/2. И давай нормальные имена переменным, не надо экономить тут байты.
>>997128 >Я правильно понял, что либо я страницу с кодом ошибки передаю, либо делаю редирект на страницу для пользователя где "Хуё-моё, администратор уже выехал...", но тогда никаких кодов а заголовке?
Так, пока понял, что заголовок отдельно - контент отдельно и можно передавать все что угодно после установки заголовка.
Тогда не очень понятно зачем ты придумал свое исключение. Обычно каждый класс исключения обозначает какую-то ситуацию. Ну например, ошибка работы с базой данных (PDOException), ошибка передачи данных по сети (NetworkException) и тд. Что обозначает твой класс?
Также, глобальный обработчик исключений наверно должен ловить все исключения, а не только одного класса. Иначе какой в нем смысл?
Вот ты по моему не понял, как должно это работать.
Также, ты читал мой урок невнимательно. Там написано, что должен делать обработчик исключений - и ты многое из этого не сделал. Например, пользователю не показывается никаких сообщений, информация не фиксируется в логи. Вот как ты будешь узнавать о том ,какие ошибки произошли на сайте, если ты не пишешь логи?
> либо делаю редирект на страницу для пользователя где "Хуё-моё, администратор уже выехал...", Зачем это нужно? Какой смысл в дополнительном редиректе? Это в каком-то учебнике так советуют?
Название класса тоже неудачное, класс обычно называют в единственном числе. Да и у тебя объект класса не представляет информацию об ошибке и называть его Error нельзя. Подумай внимательно, как он должен называться.
В проекте много что вызывает моё недовольство, что хочу изменить: - deployment. Автоматизация настроек и дополнений. Пока перемещал файлы со своего вина на линь хостинга, пришлось вносить кучу изменений, которые сложно запомнить. Стоит лучше отделить все платформозависимые вещи и настройки. - обработка инпута пользователя. Мой код был прост и красив, пока я не добавил больше кнопочек, каждая из которой (в виде проверки POSTа) увеличивает размер скрипта процентов на 15; этому должен придти конец. Я пробовал выдумать "контроллер", который бы сократил количество кода до минимума, но это, также как и попытка осмысления MVC, вышли неудачно. - обработка ошибок расползлась в трёх-четырёх разных местах, я собрал её в одном классе, но он делает лишь половину работы — исключения всё равно могут оказаться где угодно. - класс Registry. Уродливый, громоздкий, не ре-юзабельный, но всё равно лучше чем скопище глобальных переменных для общих классов. Краем глаза видел в фреймворках классы типа app — наверное, стоит брать с ним пример. Фреймворками не пользовался. - для работы с БД, возможно, стоит попробовать что-то специализированное типа doctrine2 (не пробовал). Классы генерации SQL исключительно доморощенные и не особо ре-юзабельные.
Я бы не советовал делать страницы ошибок через контроллеры. Ведь ошибка может произойти где-то в базовом классе контроллера или на момент ошибки какие-то компоненты могут быть недоступны. Лучше сделать страницу ошибки как можно проще, без лишних зависимостей, без проверок авторизации и прочего.
Название для исключения тоже неправильное, хотя бы с точки зрения грамматики, my пишется перед exception. Ну и в твоем случае нужно указать конкретно, что это за исключение (например AssertionFailedException). Также, обрати внимание, что в PHP есть готовые исключения: http://php.net/manual/ru/spl.exceptions.php
Название метода тоже неправильное. Ты его назвал "getErrorPage" но он ничего не возвращает - должно быть printErrorPage().
Есть "облако" (1cloud), где ты получаешь линукс-виртуалку, но там надо за все платить - память, процессор, трафик, диск. Выходит в самом минимальном раскладе рублей 250 в месяц наверно, из плюсов - не нужен номер телефона и личные данные, из минусов - платить надо за каждый чих, а трафик фильтруется роскомнадзором.
> То есть надо как-то делать папку uploads открытой? Это зависит от используемого способа раздачи файлов. Если ты хочешь их раздавать без использования PHP, веб-сервером напрямую, то да, надо. Если ты хочешь отдавать файл через PHP или расширение X-Sendfile то открывать папку не требуется.
Там в комментариях к задаче описаны возможные варианты:
- отдавать файл с помощью PHP - обрабатывать запрос на скачивание в PHP, но затем отдавать заголовок X-Sendfile и поручить саму отдачу файла серверу - отдавать напрямую веб-сервером
В любом случае, лучше не позволять создавать php-файлы, а также файлы вроде .htaccess, .gitignore и так далее.
> И можно ли сделать на изображения и остальные файлы две отдельные таблицы в базе данных? Можно, но в чем выгода? Если у обычных файлов и изображений разный набор свойств (колонок) то это пример наследования таблиц и есть 3 паттерна на такой случай: Single Table Inheritance, Class Table Inheritance, Concrete Table Inheritance ( http://design-pattern.ru/ )
Парадигма MVC описывает процесс обработки запроса, которым управляет Контроллер, вызывая при необходимости Модель и Вид. Но вполне могут быть какие-то вспомогательные классы, которые просто стоят сбоку и явно к чему-то не относятся.
Но класс, который генерирует URL, наверно можно отнести к Модели, так как это часть логики приложения, и этот класс можно вызывать откуда угодно.
>>Вообще, ты неправильно учишься. > Честно говоря, такой ответ сильно демотивирует. У меня тут, если посмотреть ОП пост, уже набралось что-то вроде большого курса по PHP. Начиная с основ, продолжая сложными вещами вроде ООП и заканчивая еще более сложными задачами, которые используют смесь технологий, не только PHP. Соответственно, когда человек берется сразу за сложную часть, мне тоже не очень охота объяснять то, что изучалось где-то раньше и что он пропустил.
Вот например у меня есть в ОП посте задача про студентов, на примере которой учатся писать приложения, работающие с формами и базой данных. У нее подробные комментарии, и конечно мне не очень хочется по второму разу их пересказывать тем, кто эту задачу пропустил.
Если и дальше спешить все сделать как можно быстрее, толком не разобравшись, то будет получаться плохой код. А плохой код обозначает высокий процент ошибок, потери времени при попытке вносить изменения. Другие люди будут всеми способами пытаться избежать необходимости в нем разбираться.
Насчет других книг - я их не писал, за их авторов отвечать не могу.
> начинаю переписывать, упрощать, делать "защиту от дурака", работать над дизайном Это так не работает, у тебя не будет ни сил ни мотивации переписывать большой объем кода и ты его так и оставишь.
> Вот ещё десять таких же кирпичей, Хороший программист должен много знать и стремиться расширять свой кругозор. У нас в IT нельзя быстренько что-то выучить и потом всю жизнь повторять одни и те же операции.
> На самом деле нет ничего важнее, чем хорошо наработанный базовый навык кодинга, Эта фраза ничего не значит так как ты не определил что такое "базовый навык кодинга". Базовый навык кодинга на PHP поможет сверстать страницу или написать SQL запрос? Поможет правльно давать названяи переменным?
> Есть у меня один чувак, он дохуя технологий типа знает, но написать нихуя не может по итогу, спотыкается на любой простейшей вещи. Возможно, он знает не сами технологии, а только их названия.
> $lines = preg_split('/\n/iu' хватило бы explode, тут мощь регулярных выражений не особо нужна.
> $char = mb_substr($line, $i, 1); > if ($char == TRUE) { Это неправильный код. $char это строка, а не булевское значение (true/false). Это если и работает, то за счет каких-то странностей преобразования строк в булевские значения при сравнении. Попробуй сам прочитать: 'если i-й символ в строке равен TRUE' - как такое может быть?
> $counter = NULL; > $counter++; Ты кладешь в переменную NULL (обозначающее отстутсвие данных) и потом пытаешься его увеличивать, как будто это число. В переменную надо класть значения одного типа, ноль, а не NULL.
Ты наверно где-то работаешь с ними как с числами. То есть берешь их значение, с чем-нибудь складываешь и записываешь обратно. Проверь все места в коде, которые что-то делают с этими полями.
Вообще, CSRF там не нужен (проблемы нет, если злоумышленник заставит пользователя сделать поиск). Более того, он может навредить, если пользователь возьмет и опубликует где-то ссылку на результат поиска, другой пользователь ее откроет и сработает защита из-за того, что у него нет нужных кук.
Сайты обычно делают это ради SEO оптимизации, чтобы сделать вид, что у них не одна страница с результатами поиска, а много отдельных страниц с уникальными URL. Не знаю, работает ли это вообще.
Также, возможен редирект, если найден единственный результат. Например, в Википедии, если ввести название статьи в поле поиска, то он на нее редиректит, если же такой статьи нет, то выдает страницу результатов. Попробуй на ней проверить, википедия в плане структуры сайта хорошо сделана (в случае википедии, там реальные страницы и это не имеет ничего общего с сайтами, которые на любое слово готовы сгенерировать отдельную страницу).
> Да, в форме стоят невидимые поля CSRF, но я их не прошу выводиться нигде. При GET запросе все поля формы добавляются в URL. Как иначе скрипт на сервере их получит? Он их берет из URL, в этом и суть GET запроса. При POST - другое дело, параметры постятся в теле запроса, но зато ты не можешь опубликовать ссылку на результат запроса. Вообще, это основы HTTP, который бы стоило подучить (справедливости ради, нормальных уроков по теме я не видел, а свой все руки не доходят написать).
> Чтобы посчитать сколько файлов в текущей папке нужно сначала определить есть ли текущая папка вообще (на случай если файл загружается впервые), затем посчитать сколько в этой папке файлов, и определить есть ли там файл с таким именем. Получается довольно большой блок условий.
Потому нужно решать задачу по-другому. Ну например, чтобы гарантировать уникальность имен, можно приписывать к ним id файла, который гарантированно уникален. Или генерировать GUID/UUID ( https://ru.wikipedia.org/wiki/GUIDhttps://ru.wikipedia.org/wiki/UUID ). Что касается распределения по папкам, если известен Id, можно вычислять папку из него, если нет, можно делать папки по дате/времени исходя из оценки, сколько у нас примерно загружается файлов за единицу времени.
> http://ideone.com/tMu8IN Кубики Тут еще возможна ничья, когда нет даблов, но число очков одинаковое - это не проверяется.
> http://ideone.com/P3xI5r Миллион в банке Верно, хотя я бы использовал += для увеличения $resultSum.
> http://ideone.com/xutDDU Айфон Интересно, что этой задаче уже несколько лет, а айфоны все еще не исчезли, и не подешевели даже, и текст не требуется переписывать.
Слишком большое решение, например формула $creditBalance x $percent + $servicePayment встречается аж 3 раза, попробуй избавиться от повторов.
> Как я понял, webpack не умеет грузить напрямую, зато есть режим watch, который обновляет сборку в режиме реального времени, и несколько видов карты файлов.
Вот эта идея что-то постоянно пересобирать при разработке - на мой взгляд, она только замедляет работу. Склейка в один бандл была придумана как ответ на недостатки HTML и HTTP/1. HTML требует останавливать парсинг HTML-кода до загрузки и выполнения скрипта, а HTTP/1 требует создавать новое TCP-соединение на каждый запрос, при большом пинге значительная часть времени уходит на обмен пакетами для установки соединения + установку шифрования в случае HTTPS. То есть если пинг 100мс, для установки TCP соединения надо 3 обмена пакетами + еще пару для установки SSL, получается что мы тратим 250мс на инициализацию соединения, по которому может быть за 10 мс мы скачаем один скрипт. Склейка позволяет частично победить эту проблему. Но она создает другие, например требует при разработке использовать маппинг (который должен поддерживаться отладчиком) для корректного отображения скриптов в исходном виде. Выглядит как борьба с проблемами, которые мы сами же себе и создаем.
Но со временем эти проблемы уходят в прошлое. Протокол HTTP/2 позволяет по одному соединению с хорошей скоростью выкачивать параллельно много файлов без задержек. И новые ES6 Modules решают проблему блокировки парсинга HTML и предоставляют удобный синтаксис. Поскольку они будут частью JS и будут встраиваться в браузеры, очевидно что это самый перспективный стандарт. Думаю, и нода на них перейдет когда-нибудь.
Нужна ли склейка на dev сервере? Даже на HTTP/1 проблем с пингом тут нет, HTTPS тоже нет, пересборка (на мой взгляд) лишь приводит к лишним затратам времени. Более того, функция watch в зависимости от версии ОС и ноды может потреблять процессор (можешь проверить). Мне кажется, что удобнее не создавать самому себе проблемы, а загружать исходные версии файлов.
Лучше всего было бы на dev использовать ES6 modules напрямую и новый браузер, а для продакшена, где есть много старых браузеров, не поддерживающих их и HTTP/2, делать склеенную версию. Но! http://caniuse.com/#search=es6%20module показывает что пока ES6 кроме Сафари (а также новейшего Хрома, Edge и ФФ с включенным флагом конфига) никто не поддерживает :(
Соответственно, мне кажется, перспективно делать так:
- модули пишутся в синтаксисе ES6 Module - разработчик с поддержкой ES6 Module просто грузит их нативно без помощи webpack - на продакшен собирается бандл в старом синтаксисе через webpack. Наверно, ES6 код придется транспилировать в ES5 (а лучше вообще в ES3, но не уверен, что это возможно). - разработчик без ES6 мог бы использовать загрузчик или polyfill, который загружает модули например через аякс запросы + eval. Вроде https://github.com/ModuleLoader/browser-es-module-loader . Но я не уверен, что это будет нормально работать, потому ему придется наверно использовать webpack.
Такие сложности нужны из-за того, что технология очень новая и мало где поддерживается.
По коду, я тут вижу сложное место:
> https://github.com/enotocode/minesweeper.mvc/blob/master/app/MinesweeperGame.js#L131 > MinesweeperGame.prototype.getMinesQuantity = function(x, y) { > return this._cells[x][y].surroundingMines; А где гарантия что к моменту вызова getMinesQuantity() поля surroundingMines заполнено? Не лучше ли было бы вычислять количество при первом вызове метода?
Также, у тебя там число 12 повторяется в коде, надо было сделать его свойством.
> А как делить файлы по папкам, View/Controller/Other ? MVC не значит что должно быть ровно 3 папки. В данном случае, можно например сделать такую структуру, группируя файлы по типу:
Есть также другой вариант, можно группировать классы, которые используются вместе:
- Browser - Console - Event - Modal - ...
Ну вообще, 15 файлов еще терпимо, но в более сложном приложении папки понадобятся.
> Вопрос про ModalView Тут можно избавиться от связи между попапом и моделью игры вообще. Пусть ModalController при нажатии кнопки не перезапускает игру, а просто генерирует событие вроде BUTTON_CLICK. То есть любой желающий может создать ModalController, дать ему текст попапа, подписи для кнопок, подписаться на его событие и открыть попап. Любой попап с любым текстом, не обязательно связанный с перезапуском игры.
Соответственно, game.restart() тогда надо вызывать в BrowserController. И там же, кстати, надо закрывать попап если мы перезапустили игру из консоли.
Также, у меня ощущение что тогда ModalContoller можно будет вообще выкинуть и работать с ModalView напрямую. То есть создаем ModalView, даем ему текст, подписываемся на событие.
Вот примерно так:
BrowserViewController.prototype.createModal = function() { var modal = new ModalPopupView(domElement); modal.setText('....'); modal.setButtons(....); modal.subscribe(EVENT_BUTTON_CLICK, function () { that._game.restart(); }); modal.show();
// Если игра перезапущена не через попап this._game.subscribe(EVENT_RESTART, function () { if (modal.isVisible()) { modal.destroy(); } }); }
Надеюсь, суть понятна. Мы полностью отвязываем попап от игры.
В моем коде кстати есть еще маленькая проблемка, утечка памяти. Мы каждый раз создаем новый объект modal, и добавляем в _game ссылку на него через новую подписку. Число подписок только растет со временем. Даже если попап давно закрыт, обработчик события RESTART удерживает ссылку на этот старый попап. Надо отписываться от события при закрытии попапа. Либо же надо подписываться на событие EVENT_RESTART где-то в другом месте и один раз.
В твоем коде эта проблема по моему тоже есть - subscribe вызывается при каждом открытии попапа но подписки никогда не удаляются.
> вопрос про вывод поля в консоли > И нужно будет перерисовывать поле каждый раз, при открытии каждой клетки, но за один ход могут открыться сразу несколько соседних, если рядом с ними нет мин. Сейчас так выглядит вывод поля в консоли браузера. Это потому что у тебя нет группировки событий (произошедших в течение выполнения одной функции). Я подумал, наверно проще всего было бы сделать аггрегацию событий на уровне EventDispacther:
this._model.eventDispatcher.subscribeAggregate(MinesweeperGame.EVENT_CELL_OPENED, function (events ) { // массив накопленных событий сгенерировать и вывести новое поле; });
Это можно сделать например через трюк с нулевым таймаутом. То есть мы кладем событие в массив и ставим нулевой таймаут, если он еще не поставлен. По таймауту вызываем обработчик, и он вызвается с массивом накопленных событий.
Агрегация событий часто нужна, иначе на каждый чих все будет перерисовываться.
> Т.к. я договорился что внутреннее хранилище с ячейкими не покинет модели, мне нужно сделать метод получения данных о всех ячейках, т.е. создать новый формат для передачи данных или клонировать массив со всеми классами внутри. А потом отрисовывать его?
Можно в цикле вызывать существующие методы для каждой ячейки. Просто ты поддерживаешь по сути вторую копию модели и синхронизируешь изменения, это сложно и легко допустить ошибку.
Хотя в плане производительности, может быть, поддерживать копию поля выгоднее. Только лучше сделать эту копию массивом строк или массиво символов и заменять символ лучше не через пересоздание строки, а через string[x] = N;
> 2. Можно добавить два статуса для метода модели openCell(), при запуске метода статус изменяется на OPENING, в самом конце выполнения статус на - WAITING. Функция входит в рекурсию до изменения статуса на WAITING, а в режиме рекурсии не меняет совсем. View должна иметь прямой доступ к модели или сделать этот статус свойством события открытия каждой клетки.
Это сильно усложнит код.
Вообще, мне кажется, стоит потихоньку заканчивать с этой задачей, и двигаться дальше. Мы и так на нее много времени потратили, а это всего лишь простая игра, и она не позволит нам изучить все аспекты создания SPA приложений.
Ну например, можно взяться за задачу на SPA из ОП поста. Хотя она сложная, может перед ней стоит сделать что-нибудь попроще, например, терминал кассира для оформления заказов в фастфуде с отправкой заказов на сервер, или терминал сотрудника ресепшена в отеле (забыл, как эта профессия называется) или простой мессенджер. Тут тебе пригодится и MVC, и что-нибудь из Angular/Knockout/React.
Но задачу на SPA хорошо бы сделать. Мало кто сейчас такие штуки умеет делать.
echo выводит только строки, все, что не строка, он приводит к строке. Массив он вывести вообще не может. А var_dump показывает тип переменной и данные, как есть. Он нужен для отладки программы.
А почему ты не хочешь использовать SQL? Он специально был придуман для работы с данными и вряд ли код на PHP с кучей кавычек и скобочек его превзойдет.
Может быть, да. зависит от объема данных, если их очень много, то может надо придумывать что-то более оптимальное. У MySQL есть еще вполне заметное ограничение на число вставок в секунду (из-за требований к надежности хранения данных), если у тебя тысячи сообщений в секунду, то конечно придется импровизировать.
Может есть какие-то более удачные хранилища, но я сейчас не могу их назвать. Возможно, что все возможности SQL для хранения сообщений и не нужны. Все же MySQL это хранилище общего назначения, не заточенное именно под хранение сообщений.
Я знаю, что вконтакте использовал написанное на Си хранилище, а что исплоьзуют другие сайты ты можешь поискать тут: https://www.insight-it.ru/highload/
Дамп БД лучше поместить в проект в формате sql. Архивировать не надо.
Описание структуры проекта можно поместить в файл structure.md и поставить на него относительную ссылку в README.
У тебя много библиотек в папке vendor, но почему-то их нет в composer.json. В репозитории как раз папка vendor не нужна, в нем по возможности должен быть только твой код. Идея в том, что тот, кто скачал твой код, запустит композер и он установит нужные библиотеки.
Для безопасности желательно сделать публичную папку, а весь остальной код разместить за ее пределами, чтобы он был недоступен веб-серверу.
>>997292 Мой код с трудом расширяется и почти не реюзабелен, поэтому не могу пока им гордится. Читал Мэтт Зандстра (не полностью, шаблоны мне пока не требуются), Совершенный Код Макконнела (он заразил меня перфекционизмом, от которого теперь страдаю, потому что вижу, что код не такой, какой должен быть, а сделать правильно не умею). Мне хочется сделать как в фреймворках, наверное, мне стоит сделать что-то на микрофрмврке как в оппосте.
>>997294 > Не открывается. Точно? Я проверил с другого браузера и телефона, открывается. Хостинг бесплатный, поэтому очень часто бывают ошибки 500, лучшего хостинга с php7 я пока найти не смог (если найдёте, киньте). Просто рефрешни несколько раз страницу.
>>997323 > А ты комментарии в задаче про студентов из ОП поста читал? Читал, но не все со стопроцентной эффективностью осмыслил. > По работе с БД Читал, на основе её и придумал Student|PasswordMapper'ы. > Описание структуры проекта можно поместить в файл structure.md Маркдаун не переваривает табы и игнорирует пробельные отступы. > У тебя много библиотек в папке vendor, но почему-то их нет в composer.json. https://packagist.org/packages/phpunit/phpunit requires Оставшиеся нужны были одной библиотеке, которую я затем выпилил ручками, т.к. не разобрался, как в phpStorm удалять что-то из композера. > В репозитории как раз папка vendor не нужна, в нем по возможности должен быть только твой код. Идея в том, что тот, кто скачал твой код, запустит композер и он установит нужные библиотеки. Понятно. Пересобрал у себя vendor, удалил папку из гитхаба (это, кстати, можно сделать только через git shell) > По работе с формами Читал, старался так и делать. Алсоу, предложенный там вариант с strval не работает с массивами, потому что строка конвертируется в Array и выбрасывается Notice типа: Notice: Array to string conversion in .php on line 4 string(5) "Array" Поэтому способа обезопасить себя от подстановки массива одной функцией в PHP нет, нужен is_array.
> По поводу Registry Займусь этим сейчас.
>Для безопасности желательно сделать публичную папку, а весь остальной код разместить за ее пределами, чтобы он был недоступен веб-серверу. Сделаю так, когда разберусь с другими проблемами структуры проекта. Для контроля доступности использую .htaccess, можешь попробовать вытащить из сайта волнительный файл типа xml. > Позже может быть еще напишу комментарии. Смотрел сайт? Попробуй потыкать кнопочки, напиши впечатление.
>>997570 Видимо, разрешение экрана маленькое, при том что размер шрифтов не менялся. Попробуй изменить отдалить в браузере (в хроме контрол + колесико мыши). Так, конечно, плохо, но хотя бы заценишь кнопочки. Не учился адаптивной верстке, тестировал на 1600-900.
>>997314 >Я бы не советовал делать страницы ошибок через контроллеры. Ведь ошибка может произойти где-то в базовом классе контроллера или на момент ошибки какие-то компоненты могут быть недоступны. Лучше сделать страницу ошибки как можно проще, без лишних зависимостей, без проверок авторизации и прочего.
>Название для исключения тоже неправильное, хотя бы с точки зрения грамматики, my пишется перед exception.
>Название метода тоже неправильное. Ты его назвал "getErrorPage" но он ничего не возвращает - должно быть printErrorPage().
Пофиксил.
Ну и в твоем случае нужно указать конкретно, что это за исключение (например AssertionFailedException). Также, обрати внимание, что в PHP есть готовые исключения: http://php.net/manual/ru/spl.exceptions.php
Глянул, потом углублюсь. У меня исключения только-только стали укладываться в голове.
Сейчас по другому попробовал, понятно что говно, но в принципе, решение то жизнеспособное? Получше хоть стало?
Но плохо понял как обмазать проект безопасностью. Что бы защититься от уязвимости sql - нужно санитайзить переменные непосредственно перед тем как он попадет в базу? Если например нет возможности удостовериться, что селекты и инсерты выполняются через плейсхолдеры где-то там в ядре фремворка, на котором написан проект, правильно?
Далее что касается js уязвимостей. То это уже во вьюхе при выводе инфы от юзеров в шаблон нужно обмазывать? Что бы потенциальный js код не поставился во вьюху и не выполнился вредоносно?
Что по поводу аплоада файлов, ни слова не сказано как защититься от загрузки pidor.php в папку с аватарками и дальнейшим доступом ко всему коду / в админку проекта.
Опрос: на какой системе вы программируете, как вы поставили php+apache+БД+ ... ? Кодю на винде, раньше использовал ручную сборку php-mysql-apache, потом поставил xampp. Удобно, что всё настроено, но с другой стороны — у него старая версия mariaDB, PMA и апач тоже не самый свежий; нужно что-то другое, такое же портабельное для кросс-ОС-овской разработки.
>>997323 > По поводу Registry, глянь этот урок, если не читал Прочитал, написал свою реализацию DIContainer: https://pastebin.com/qDiPiNYW (алсо, какое пастохранилище использовать лучше пастбина?) Сейчас начну пробовать избавиться от Реестра, и заранее видно затруднение: описание фабрик, как в примере: > // Описываем как создать объект работы с БД, зависящий от PDO > $container['userDataGateway'] = function ($container) { > return new UserDataGateway($container['pdo']); > }; всех нужных объектов и данных приведёт к большому куску кода, которому абсолютно нечего делать в index.php и тому подобных скриптах. Его нужно упаковать либо в отдельный скрипт (это тупо), либо придумать класс типа app или controller, который органично будет все эти фабрики заполнять и регистрировать. Думаю об этом, но пока не знаю, как сделать.
>>997702 Я виндоблядь. пхп+энжинкс+мускл+что еще угодно, похуй. На локалке есть все это, но использую редко, всю разработку веду сразу на сервере (убунту или дебиан). Там все точно тоже самое стоит, только нормально работает. Никаких пма и подобного, только консоль.
С чего начать изучение WebSocket? Вообще посоветуйте, что лучше всего использовать для полноценного чата с лайками, модерированием и общим сохранением сообщений в базе.
>>997702 Ставь всё по отдельности, это не сложно. У меня PHP7 стоит на локальном, которого ещё долго не будет в таких вот сборках, типа WAMPP. MariaDB - там так-то то же самое, но зачем.
>>997702 >Опрос: на какой системе вы программируете, как вы поставили php+apache+БД+ ... ? Сижу в винде, сервер там же на Virtualbox + Vagrant. Не ебу как это работает. Запускаю одной командой виртуалку с убунтой без гуя, она там где-то крутится, кидаю скрипты в папочку в винде и в браузере их запускаю, доступ к консоли сервака через SSH. Только phpmyadmin поставил.
>кросс-ОС-овской разработки Хуй знает что это, не сталкивался с проблемами из-за ОС.
Наверное, луче всего было бы перекатится на убунту полностью. Но мне у винды интерфейс больше нравится, он более аккуратный и миниатюрный что-ли, а скорее линукс в винде из коробки будет без всяких виртуалок. В удивительное время живем.
>>997712 >Вообще посоветуйте, что лучше всего использовать для полноценного чата с лайками, модерированием и общим сохранением сообщений в базе. Для портфолио пилишь?
>>997731 О, точно, не сказал, для чего нужно. На своём сайте хочу сделать просто чат. Если это будет готовое решение, то тоже нормально. Но мне нужна сложнота и неочевидность: чат и окно для лучших сообщений - которым больше всего поставили лайков. Чатятся, ставят лайки - если 10% от чатящихся поставили лайки сообщению - оно переносится в то окошко. Вот думаю погрузиться в ВебСокет и запилить сие.
Изучаю сейчас вордпресс, и хочу попробовать сделать что-то на нём. Может кто-нибудь дать задание приближённое к тем, которые бывают на фриланс-биржах? Например, вставить какой-нибудь функционал в тему или ещё что-нибудь.
Пока что натянул вёрстку на вордпресс, вёрстка сделана тоже мной из ПСД ОПа, правда она не адаптивная, но я исправлю это. Адрес сайта на прикреплённой пикче, извиняюсь за неудобство, но при попытке вставить ссылку в пост двач пишет что присутсвует слов из спам листа. Проверить натяжку на саму вордпресс можно через админку, доступ: Логин - Admin Пароль - admin
Контент сделал через записи, также есть страница настроек темы, зайти в неё можно по адресу Внешний вид->настройки темы
>>997702 >>997707 >>997712 >>997729 Странно что в треде столько виндовых "вебмастеров" и при этом никто не знает про https://ospanel.io/ Всем ньюфагам рекомендую. Несколько лет назад когда вкатился и 1 раз установил всё ручками "пушто так надо и тру", быстро понял прелесть денверов и всяких изипхп, но денвер давно мертв, а тут всё удобненько и актуально.
Ебать я тут ору с ГитХаба, ебучие линуксоёбы заставляют пердлоится в консоли, проще было изучить php, чем понять как нахуй удалить лишнюю папку из репозитория. Не надо ничего советовать, я просто продолжу гореть.
>>997707 > энжинкс Почему никсы, а не апач? В никсах не разбирался, читал лишь вкратце, что они попроще апача и победнее функциями, для статических сайтов. > только консоль. Дело привычки, или другая причина не использовать гуи? >>997783 > https://ospanel.io/ Видел эту штуку, но там много всего лишнего для моего уровня, + она только для виндовс, а хотелось бы папочку, которую просто копируешь из винды в линукс с минимумом переделок.
>>997786 > нахуй удалить лишнюю папку из репозитория. Я знаю как. > Не надо ничего советовать Ладно.
>>997783 У меня винда выступает в роли того, на чем я сам сижу и где ИДЕ запускаю. Существенной разницы нет, на работе с мака хваленого сидел, не принципиально, все одно и то же. Всего-лишь дело привычки. Если в нерабочее время я использую винду, то мне и для работы ее удобнее использовать, чтобы не переключаться лишний раз. Мне, как ни странно, гораздо проще руками все развернуть. На стандартный набор минут 10 отсилы уходит (энжинкс, пхп, перкона), под убунтой проще всего вообще в 1 команду все обернуть, собственно зачем на фоне этого какие-то готовые сборки? Хуево самому накатывать редис или необычную бд, и то не всегда, но мне этот процесс интересен, так что вполне доволен всем. Можно вагрантом пользоваться изи, но по причине наличия 3х тестовых серверов не имею потребности в нем. >>997800 >Почему никсы, а не апач? >Дело привычки, или другая причина не использовать гуи? Вкусовщина и то и другое. >для статических сайтов Энжинкс уже давно через пхпфпм отлично работает с динамическим контентом.
https://gist.github.com/codedokode/9424217 >для картинок, выводить информацию и превьюшку >для медиафайлов (аудио/видео), выводить информацию (ее можно получить с помощью библиотеки вроде gitId3, не руками же файлы расковыривать) Какую информацию обычно нужно выводить?
Для картинок, наверно, достаточно будет разрешение и её тип. А для видео и аудио что нужно?
Вместо PDO и mysqli использовал фреймворк Medoo(который на PDO работает).
При заливке на хостиг сразу вылезли ошибки моей молодости(абсолютные/относительные пути, где-то вообще написан сам сайт(Students\list), вместо пути, за это уже понял не ругай.)
Куки на 10 лет + привязка к IP-адресу.
Версия php 5.5 - залил на хостинг, где 5.4 - сразу отвалилась авторизация с чудесным методом password_verify();
Код отформатировал встроенный в phpShtorm форматировщий(кроме Helper.php).
Собирался ещё допилить проверку полей через js, но руки не дошли. А так довольно занимательно в выходные проводить 10ч к ряду за написанием кода, забывая поесть.
Счётчик накрутил 54+ часа работы над проектом, но пилися он больше месяца.
Напуствие ньюфагам - ЗАКРЫВАЙТЕ ФОРМЫ, ЗАКРЫВАЙТЕ ЭТИ БЛЯДСКИЕ ФОРМЫ, я убил невероятно много времени на поиск бага, оказалось </form> отсутсовал И ЗАКРЫВАЙТЕ ЭТИ ФОРМЫ НАХУЙ
>>997931 Брат, юзани пасс логин от татарина, на сервере осталый пхп, если авторизацию я мог быстро пофиксить, то с регистрацией там сложнее, не хочу перепиливать под старый пхп. Очевидно password_hash() и password_verify() из одной истории про пхп 5.5.
>>997318 >Тут еще возможна ничья, когда нет даблов, но число очков одинаковое - это не проверяется. Исправил, пикчу приклеил. http://ideone.com/tMu8IN >Слишком большое решение, например формула $creditBalance x $percent + $servicePayment встречается аж 3 раза, попробуй избавиться от повторов. Откорректировал решение. Формула с повторениями убрана. Можно убрать проверку на >0 и сокращение, тогда останется 20 строк. Но код будет менее универсальным. http://ideone.com/xutDDU >Тут можно обойтись без array_flip, просто взяв из массива значение по полученному индексу. Тут создал новый код http://ideone.com/Rvv9TQ и старый http://ideone.com/3YTUk6 Мне показалось второе решение менее громоздким. Но у тебя опыта больше, так что не спорю.
Из непроверенного и того что я сделал нового! л33т. Тут я честно взял из википедии буквы, и прочитать результат сложновато, но видимо кто давно так пишет, приноровились уже это всё читать. http://ideone.com/yvE1x7
Привет, тред. Думаю над Dependency Injection. Раньше для передачи зависимостей отправлял в параметры конструктора чего бы то ни было класс (service locator), теперь от него избавился. Допустим, неудобно писать в параметрах конструктора класса 6-10 переменных, которые юзер должен запомнить, особенно если в будущем разработки из число может варьироваться. Логично вместо этого подставить массив, содержащий новые объекты и данные; такой массив будет более versatible, чем service locator, но так ли сильно он будет лучше? Какой оптимальный вариант?
Для примера:
$object = new Class($var1, $var2, $variablewithlongname3, $var4, $var5, $var6, $var7, $varvarvarvariable8, var9, var 10); — плохо $object = new Class($parameters) — лучше, но разве мы видим так какие именно зависимости передаём? Ведь в отличие от класса в массиве нет на это указания или контекстной справки.
>>998809 Лямбда — когда лень создавать отдельную функцию для какой-то задачи. Функцию поддерживать надо, не разбрасывать по всему скрипту, имя выдумывать, а лямбду сделал — и забыл. Замыкание то же самое, это лямбда, которая использует переменную из более общего скопа. Если читаешь по-английски, вот тут разжёвано http://culttt.com/2013/03/25/what-are-php-lambdas-and-closures/
Другой пример: допустим у тебя есть функция поиска товаров на складе. Как передать в нее критерии поиска ("найди мне товары производителя X ценой не более 200 тугриков")? Тут-то и пригодится анонимная функция.
>>998842 Помоему лямбда в общем случае означает просто анонимную функцию. В пограмировании вроде больше принято лямбдами называеть стрелочный синтаксис (этакий апофеоз сахарной лени). Ну а замыкания проще всего понять на простом ооп без лишнего, например в джаве старенькой, чтобы прочувствовать все происходящее внутри дерьмо. Но это чисто мое мнение, не вдавался в академические термины, объяснял так паре чуваков на примерах.
Нужно различать веб-страницы и веб-приложения, а не бездумно повторять слова, увиденные в статье на хабре. И кстати в ОП посте есть задача на SPA, можешь попробовать сделать.
> namespace src\classes; src не надо включать в неймспейс. Его надо либо убрать либо вписать туда название приложения. Также, неймспейсы желательно писать с большой буквы.
> ADD UNIQUE KEY `id` (`id`); Первичный ключ уже является уникальным по определению и второй ключ по id добавлять не надо.
https://github.com/some-random-username/student-list/blob/master/.htaccess Чтобы сделать папку корнем, лучше в настройках сервера прописать ее как DocumentRoot, а не делать трюки с htaccess. Тем более что у тебя там аж 2 файла htaccess, и сложно оценить насколько они корректно будут работать во всех ситуациях.
> $code = $exception->getCode(); > http_response_code($code); Это вообще не правильно так как поле $code в исключении не обязательно соответствует коду HTTP. Это в общем произвольное число. При выбросе исключения логично ставить код 503, а для ошибок 403/404 лучше сделать специальные отдельные классы исключений. Или формировать эти страницы без использования исключений.
> echo "<p>Message: '" . $exception->getMessage() . "'</p>"; Если строго смотреть то нельзя в HTML код просто так вставлять текст ошибки, его надо экранировать чтобы спецсимволы вроде <x> в нем выводились как есть, а не воспринимались бы как тег HTML.
> const CONFIGPATH = '../src/config.php'; Тут плохо что указан относительный путь, непонятно относительно чего, а также то, что тут использована глобально доступная константа. Лучше наверно сделать переменную и передавать ее только туда, где нужно.
Вообще, мне лично не нравится когда делают класс с названием Application - почти всегда он либо неправльно назван, либо в него сваливают все подряд. Ну что, разве твой Application представляет все приложение? Нет конечно, он лишь создает и запускает фронт контроллер, это сделать можно легко и без него.
> public function offsetGet($offset) { Если запрошен неверный сервис то лучше выдавать ошибку, а не скрывать ее.
Также, в твоем контейнере проблема в том, что при каждом обращении контейнер создает новый экземпляр сервиса, а часто нужно вернуть ранее созданный экземпляр.
Также, наверно лучше было не включать registerDefaults в контейнер, а заполнять контйенер в отдельном скрипте, например в bootstrap-скрипте.
Код для добавления и редактирования похож и не надо его дублировать (например вызов validate продублирован 2 раза).
> $errors = $this->validator->validate($_POST); > $emailErrors = $this->validator->checkEmail($_POST['email']); Непонятно почему проверить email нельзя в validate()
Представлять студента удобнее в виде объекта, а не массива.
> public function findStudent($findParam) { Если список пустой то надо возвращать пустой массив, а не false. Иначе неудобюно работать с результатом функции.
Класс StudentsModel не должен заниматься авторизацией.
Работу с БД лучше делать в классе для работы с БД, а не в валидаторе. Каждый должен заниматься своим делом, иметь свою зону ответственности.
Шаблон редактирвоания и добавления - это почти копии друг друга, не надо дублировать код.
> <?=@htmlspecialchars($params['values']['lastname'], Не используй @ так как он скрывает любые ошибки (например если ты опечатаешься в слове params или values то не узнаешь об этом).
Вообще плохо что у тебя в шаблоне все данные в $params, лучше в отдельных переменных их хранить.
> if(isset($params['errors'])):? Плохо что переменная может быть, а может не быть.
не знаю как сформулировать $word1 $word2 хочу чето типо $i = mt_rand(1,2) $word$i только оно не хочет можно это сделать как-нибудь Без массивов из массивов?
>>998951 спс что-то через массивы массивов попробовал, тоже ничего не получает например $shlyapi = array ( array('fedora','ushanka'), array('vagina','nosok')) $shlyapi[1] получается выбирает полный массив с 0 = > fedora 1 => ushanka, а как выбрать еще из этого массивая только ушанку? как $shyalpi[1[1]] токо чтобы работало (-:
У меня есть несколько файлов php. В каждый (ну, почти каждый) из них вызывается аяксом и что-то делает. Там есть повторяющиеся куски кода, которые хочу вынести в отдельные функции, а сами функции в отдельный файл. Сейчас это сделал через include('./functions.php'); в каждом файле. Это правильное решение?
>>998997 Сложно сказать. Думаю, раз ты дошел до того, что у тебя какое-то дикое месиво из функций инклюдится в файлы, притом еще и в первый раз, чтобы код не повторять, значит ты совсем ничего не знаешь об архитектуре и ооп. В таком случае тебе тут по урокам опа учиться, потом задачки поделать и сам все поймешь. Если же ты знаешь про ооп, то почитай про автозагрузку и psr-4, ну и так же пасты опа про mvc и прочее. Не знаю, насколько тебе это актуально будет, но думаю что это оно. Как бы файлы с функциями подключать лет 15 как не дело вообще. Самому же проще будет в дальнейшем. Если же тебе, впринципе, не нужно ничего знать и ты не собираешься дальше продолжать работать над беком, то можно и так оставить. Мало ли, может ты верстальщик, которому 1.5 скрипта нужно было подключить и на этом твое погружение в тему закончится.
>>999001 >У меня есть несколько файлов php. Ок. >В каждый (ну, почти каждый) из них вызывается аяксом и что-то делает. Такого не может быть, но аякс может передавать данные файлу и получать данные от сервера обратно. >Там есть повторяющиеся куски кода, которые хочу вынести в отдельные функции, а сами функции в отдельный файл. Молодец. >Сейчас это сделал через >include('./functions.php'); В зависимости от того что тебе надо есть include require require_once смотри что тебе больше подойдёт.
>>999009 >Такого не может быть Почему же не может? Есть несколько элементов интерфейса пользователя, которые активируют соответствующие js-скрипты. А уже эти скрипты собирают данные отправляют их соответствующему php-файлу (вроде url:"./add.php",). Потом получают ответ через echo (ну или echo json_encode) и что-то там меняют на странице. >include >require Уже читал по ним документацию, >require идентично include за исключением того, что при ошибке оно также выдаст фатальную ошибку уровня E_COMPILE_ERROR. Разве что, действительно, заменить на require_once было бы лучше. >Выражение require_once идентично require за исключением того, что PHP проверит, включался ли уже данный файл, и, если да, не будет включать его еще раз. >>999007 >Если же ты знаешь про ооп, то почитай про автозагрузку и psr-4 Пока что не знаю. Вообще слабо представляю, зачем в php нужны классы. Изучение у меня идёт от проблемы к решению. Нужно сделать реакцию на действие пользователя без перезагрузки страницы - изучаю аякс. Нужен нативный календарь - изучаю jQuery. Изучение классов пока что не очевидно. Не вижу, куда прикрутить эту реактивную турбину к моей деревянной телеге. >у тебя какое-то дикое месиво из функций инклюдится в файлы Ну почему сразу "месиво"?
>>999017 Малаца, что подходишь к проблеме с практической точки зрения и не останавливаешься перед трудностями даже без знаний. Но, как я и сказал, лучше подучи, потому что будет самому же проще в дальнейшем. Достоинства от использования ооп и грамотного выстраивания архитектуры ты почувствуешь, когда твой проект начнет неприлично разрастаться. Можешь еще фреймворк какой-нибудь попробовать, там уже все готовенькое в этом плане, главное не нахуевертить самому. >>999021 Я ответил норм потом, отъебись.
> Вообще слабо представляю, зачем в php нужны классы. Если хочешь изучить, то читай учебник в ОП посте и решай задачи из него (ну или какой-нибудь другой учебник на свой выбор). Потому что без этого ты ничего серьезного не напишешь и в команде (использующей например фреймворк) работать не сможешь.
>>999027 >>999023 Значит, по итогу, если include заменить на require_once, то в первом приближении будет нормально, а если захочу улучшить, то изучать ооп и перепиливать проект согласно ему. Окей.
Есть запрос к MySQL на обновление данных в ячейке: $result = "UPDATE table SET `$column_in_db` = '$cell_value' WHERE `id` = '$id_in_db'"; В нём имя столбца задаётся переменной извне.
Если переписать его для PDO, то получится $stmt = $pdo->prepare('UPDATE table SET :column_in_db = :cell_value WHERE `id` = :id_in_db'); Но это не работает, потому что prepare переводит всё в строку и при вставке в запрос обрамляет кавычками. Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''klient' = 'jfdh' WHERE `id` = '541'' at line 1' То есть, должно быть `klient` или просто klient, а у меня получается 'klient'
>>999189 а есть какая-то разница? нужно 2 строчки одинаковых 1 делает до нумбера 3 и х 4 и типо elseif должен по идеи нумбер до 4 поднять чтобы не циклилось с первым и x обратно на 1 вернуть т.к. он связан с вордами и по итогу второй if должен то же самое делать что и 1
>>999152 В двойные кавычки не надо брать переменную саму по себе.
Если поставил elseif, то так и продолжай, зачем там дальше идёт просто if?
Сильно переусложнил, надо проще. Попробуй сначала добиться того, чтобы просто вывелось из массива одно случайное значение. Затем это удвой с помощью цикла и после цикла прибавь такой же случайный вывод последней строки.
Что будет если отправить XmlHttpRequest на страницу которая не возвращает данные, а перенаправляет на другую страницу после выполнения? Выполниться этот ридерект или ничего не произойдет?
>>999261 >Придется подставлять напрямую Это прямо так? $stmt = $pdo->prepare('UPDATE table SET $column_in_db = :cell_value WHERE `id` = :id_in_db'); Вроде же нельзя туда переменные пихать?
>>999261 >Проверь, открой отладчик (ctrl + shift + I) на вкладке network и посмотри. Уже проверил - мы получаем все ответы, и со страницы где происходит редерект, и со страницы на которую происходит редирект, но на самой странице, с которой мы отправили данные, ничего не происходит. Что лучше сделать после завершения транзакции? Самому перенаправить с помощью скрипта?
Ну так редирект относится только к аякс-запросу, он говорит что результат выполнения запроса надо искать по другому URL. С чего бы браузер должен переходить на другую страницу?
То же самое будет если например при попытке загрузки картинки будет редирект - браузер не перейдет на другую страницу.
Часик в радость, смузи в сладость. Сколько учить пхп, чтоб выполнять какие-то базовые задачи по бек-энду? Один анон из фронт треда мне сказал, что пхп учится чуть ли не за день, достаточно прочесть доку. Но я вижу, тут все серьезнее. Меня интересует не продвинутый уровень пхп, а такой, которого будет достаточно для устройства веб-макакой, т.е. какие-то базовые решения для обычных заказных сайтов. Html css и базовый js освоил, но отшивают, говорят, мол лучше бы ты без JS был, но с пхп. За неделю реально вкатиться?
>>999352 За месяц можно, если понимаешь алгоритмы, как использовать функции и прочую парашу. Я свой первый говноскрипт набыдлокодил за 3 дня, не зная что такое echo и var_dump скрипт юзал либу, парсил страничку на сайте и записывал строку в базу данных, из базы банных строилась таблица значений
Что будет лучше практикой good code, передать объект в метод и достать там свойство (id, например)... function bar(Foo $foo) { $prop = $foo->getProp() echo $prop; }
Надо смотреть, что делает этот метод. Ну например если есть метод "найти юзера по id" то нелогично передавать в него комментарий - логично именно id. Вообще, как правило, удобнее требовать минимум данных, то есть например только id, а не весь комментарий.
Почему в слиме при загрузке большого файла (больше ~50мб) метод getUploadedFiles() возвращает null?
Ошибка точь-в-точь такая же как и здесь http://discourse.slimframework.com/t/file-upload-error-handling/631/2 в точности до максимального количества байтов в логах: >[Thu Aug 18 09:12:45 2016] PHP Warning: POST Content-Length of 19022680 bytes exceeds the limit of 8388608 bytes in Unknown on line 0 >8388608 bytes
за исключением того что MAX_FILE_SIZE ничего не дает, потому что стоит значение такое же как и в настройках апача (2048MB)
>>999415 >post_max_size Я даже не знал что такая настройка может быть. Если бы не этот тред, я бы никогда не научился чему-то стоящему. Скорей бы освоить слим и жс, чтобы дописать архив тредов!
https://wiki.php.net/rfc/uniform_variable_syntax Эта статья про возможности php7 может вас заинтересовать, пусть она не самая лёгкая. Например, можно вызывать лямбды из полей класса с помощью скобок: ($this->callable)() (раньше нужно было передавать лямбду в отдельную переменную и вызывать $var() или пользоваться call_user_func).
Можно ли превратить строку в массив и обратно? Допустим, есть строка "1 2 3 4 5 6 7 8 9". Это всё считается за одну строку, а как превратить её в массив, дабы каждая цифра была отдельным элементом?
Не могу нагуглить. Есть два массива: [1,2,3,4,5] и [5,4,3,2,1] Как сравнить их так, чтобы найти соответствия числам в первом массиве числам во втором? И в этот момент выкинуть оповещение. Через двойной foreach только приходит в голову и с условиями, если $valueFirst из первого массива равно $valueSecond из второго массива, но есть ли что проще и быстрее работающее?
https://gist.github.com/codedokode/10539366 >Запустим наш файл. Теперь поиском убедимся, что поиск по слову «проверим» и «realtime» выдает нам результаты. Если ты ищешь через SQL, а не через api, не забудь указать в запросе оба индекса (SELECT ( FROM index_news, rt_news ... )). >(SELECT ( FROM index_news, rt_news ... )) Что-то я сбит с толку от такого запроса. Попробовал найти примеры, но ничего не нашел, и вообще мне не совсем понятно как делать поиск по нескольким таблицам одновременно. Как это лучше сделать? Мне нужно научиться функции JOIN?
>>999782 Ну так это уже несколько лет как не новость. А вот arrow functions и дженерики до сих пор не ввели, зато зачем-то голосуют за ИМХО бесполезный тайп-хинт: https://wiki.php.net/rfc/object-typehint
>>999836 Не совсем понятно, что ты хочешь. Если надо проверить равенство значений 2-х массивов без учёта порядка элементов, то самый простой способ это отсортировать оба массива через sort() а потом сравнить через ==
>>999858 >Не совсем понятно, что ты хочешь. Если надо проверить равенство значений 2-х массивов без учёта порядка элементов, то самый простой способ это отсортировать оба массива через sort() а потом сравнить через == Нет, не равенство. В одном массиве у меня ID обязательных тестов, а в другом массиве у меня ID выполненных обязательных тестов. Я сравниваю массивы: если совпадает - выкидываю "выполнено", а если не совпадает - выкидываю ID не сделанного теста. Почему так? Потому что это проще хранить в БД, проще управляться с этим.
>>999872 Нет, нет то. Там при любом несовпадении просто выкинет его - и все. То есть там будет true или false. Ну вот мне что нужно просто упростить: http://ideone.com/NVWmGu Думал, есть какая перда-функция, которая просто сталкивает два одномерных массива и выдаёт из несовпадающих значений массив. Походу, размечтался.
>>999890 А, точно, спасибо: http://ideone.com/QTimTG Да, надо бы навернуть мануал, да все нет времени. Мануал-то говно, вот и с аррай_дифф не понятно было, когда посмотрел.
break можно использовать только внутри цикла, а не после.
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!) - если остаток маленький, выплачиваем сколько осталось и уходим - иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Разница может быть из-за того что на твоей странице стоят какие-то дополнительные стили, которые применяются к элементам (например, может влиять box-sizing).
Чтобы проверить, ты можешь изучить кнопки в инструментах разработчика (ctrl + shift + I) на 2 сайтах и сравнить примененные к ним стили.
Что-то не понимаю я политику партии в плане защиты.
Вот, допустим, имеется веб-страница, на ней форма и кнопка сабмит. Нажимаем кнопку, данные из формы улетают пхп-скрипту. Скрипт первым делом проверяет, может ли юзер вообще это делать. Если да, то скрипт срабатывает. Если нет, то редиректит на страницу авторизации. Ну, тут вроде всё понятно.
А если мы работаем через аякс? Это же получится, что пхп-скрипт вернёт аяксу эту самую страницу редиректа, которую браузер попытается вставить в текущую. Аякс же для того и запиливался, чтобы без редиректов всё было. Как правильно такие вещи с ним организовать?
Аякс-запрос разумеется редиректить не должен, а должен вернуть сигнал об ошибке.
Если ты используешь JSON то можно вернуть объект вида
{"success": false, "error": "У вас нет прав, чтобы удалить пользователя"}
Если ты не используешь JSON то ситуация хуже. Ты можешь попробовать использовать код ошибки, ну например, 403 Forbidden - но это не очень хорошая идея так как непонятно как тут передавать сообщение об ошибке (JSOn-ом?) и эти коды легко спутать с кодами ошибок от веб-сервера если что-то не так.
По моему опыту, удобнее использовать именно JSON так как он позволяет возвращать несколько значений.
>>999926 Перезагружать страницу после каждого действия пользователя? Не уж. Чай не в 1997 живём. >>999928 >JSON Использую. Значит, пхп скрипт возвращает "НЕ ПОЛОЖЕНО", и уже на стороне клиента жаба скрипт рулит в сторону редиректа. Окей, логика мне понятна.
ОП, не ответил сюда >>997929 Запилил две новые функции, редикта и подключения шаблонов. Говори чё ещё переделать. Про DI пасту вообще не видел, надо почитать.
Сап пхпач. Хотел сначала освоить РНР по учебнику. Зашел на трекер, а там в комментах раскритиковали, мол в этом учебнике стандарты 2005 года, а это вообще катастрофа. Мол лучше всего учить по спеке, учебники и прочие материалы нинужны, ибо почти всегда устаревшие уже на момент публикации. Собственно у меня параноидальный вопрос: насколько актуальны материалы из шапки? Просто хочу быть спокойным по этому поводу.
Ещё, после обновления конфига ничего не меняется. Приходиться самому удалять rt-файлы и перезагружать(!) систему. И после перезагрузки ещё постоянно удаляется папка /var/run/sphinxsearch. Лучше перенести pid и все другие файлы сфинкса в другое место?
>>1000174 >Почему в Сфинксе при добавлении строки, в поле вставляется 0 заместо нужного значения? Я не знаю как это работает, но тут не было ошибки. Я просто допустил другие при поиске.
Кто давал советы по коду не буггуртите если не всё исправил. В этой поделке я уже не хочу что-то капитально менять. Все рекомендации взяты на заметку для следующих поделок.
Первый раз VDS с нуля настраивал. Так что там пиздец с безопасностью. За вечер более-менее настроил сервер и слава богу. Потом подробно буду разбираться.
Две трети ёбли в поделке было с админкой, но её не могу показать по понятным причинам. Откровенно говоря, я вообще эту хуйню, которую месяц писал, никому кроме анончика показать не могу lol
>>1000303 Выглядит красиво, в т.ч. описание на гитхабе. Как верстал визуальную часть? Где хостил? За месяц, на мой взгляд, не плохо. Только названия коммитом типа "make it better" это неинформативно, название должно давать кратко понять, что произошло, и желательно чтобы коммиыт на каждую переделку/фичу были разными. Алсо, папка vendor на гитхабе не нужна, достаточно composer.json и ненавязчивое напоминание о зависимостях в md. Откуда ты взял идею контроллеров и прочего?
Я помню, я написал, что неправильно в модель передавать запрос, а ты в ответ приводишь пример из документации Laravel. Но разница с твоим кодом в том, что в Laravel метод store создается в контроллере.
Задача контроллера - обработать запрос и выдать ответ. Вот тут контроллер и делает такие вещи:
- проверяет параметры запроса на правильность - если все ок, вызвает метод модели, который создает задачу и в который уже передаются параметры задачи (название), а не запрос - выдает редирект
Обрати внимание, что тут мы можем создать задачу (вызвать $tasks->create(..)) и без объекта Request. То есть модель отдельно, обработка параметров запроса отдельно. В модель сам объект запроса не передается.
Единственное, что мне не очень нравится, это то, что валидация сделана в контроллере, а не в модели, что не дает возможность ее вызвать откуда-то из другого места. Мне кажется, это неудачное решение.
Также, еще не очень хорошо, что они вместо сущности исопльзуют массив (и это же есть в твоем коде - параметры создаваемой цитаты кладутся в массив). Возможно тут лучше было сделать объект, так как у массива нигде не определен список полей, в него нельзя добавлять методы. А в классе все это есть и к нему можно писать комментарии. То есть разробраться в коде с массивами намного сложнее, особенно когда он станет побольше чем hello world. В реальных приложениях в таких случаях получаются массивы по 10-20 полей, из которых часть к тому же может отстутствовать и разбираться или вносить изменения в такой код сложно.
То есть в том коде Laravel можно было бы сделать сущность Task с свойством $name, и делать примерно так:
$task = new Task; $task->name = $request->name;
и далее уже объект $task передавать для валидации и для сохранения в БД. Конечно, класс требует написать чуть больше кода, но зато делает код намного понятнее (ну и конечно, с классами тоже не все так просто по мере развития приложения).
> Сейчас искать не буду. Там смысл был в том, чтобы суперглобальные переменные обрабатывались в отдельном классе, потому что может понадобится сделать с ними что-то специфическое, и напрямую не передавались в модель.
Ну это наверно к чему-то другому относится.
> Ок, я могу получить id из Request в контроллере и передать его в метод модели. А как тогда быть со вторым пиком? Неправильно написан Request и для данных из формы должен быть свой массив, который я должен получать из Request в контроллере и передавать в метод модели?
Нужно в контролллере создавать массив или объект, представляющий цитату, и этот объект/массив передавать в модель для валидации и вставки в БД. Так, чтобы код был разделен на части, чтобы мы могли и из какого-то другого места кода валидировать и добавлять цитаты.
У тебя там, я вижу, валидация делается в контроллере, а лучше было бы сделать это где-то в виде повторно используемого метода.
Это отдельный языкпрограммирования. К HTML он напрямую не привязан, но его можно использовать, чтобы генерировать HTML-код (или любой текст в любом другом формате разметки), который будет потом отображаться в браузере.
К сожалению, некоторые учебники это не очень хорошщо объясняют и люди почему-то думают что PHP как-то неразрывно связан с HTML, но они никак не связаны. Просто программа на PHP выдает на выходе HTML-страницу, которую потом отобразит браузер.
Я тут написал много текста, и что-то мне лень уже это переставлять и как-то структурировать. Тут очень много вещей, которые стоит посмотреть и изучить, если есть время. Потому что АПИ, да и JS-приложения, пишутся уже давно и тут много чего придумано.
> Как остановить setInterval, который был вызван в предыдущем событии? Есть clearInterval, но проще использовать setTimeout.
> С этой функцией очень много проблем, например, она меняет контекст this на вызываемой функции и его нельзя поменять с помощью call. Это тема (как можно задать this) разжевывается в учебниках по JS, например: https://learn.javascript.ru/objects-more
И может в моих задачах на JS что-то было такое, но я не уверен.
>Что нужно отправлять в ответ на успешный POST запрос? Обычно ответ возвращают в виде JSON, и в нем содержится либо информация об успешном выполнении запроса, либо об ошибке. Некоторые используют коды состояния HTTP (2xx/5xx) для индикации результата выполнения запроса, можешь посмотреть примеры в яндексовых АПИ:
>Как организовать конференции? Отправляешь запрос к АПИ на создание конференции, опционально передаешь список участников, в ответ получаешь id этой конференции и можешь в нее писать. Возможно, стоит сделать обычные диалоги тоже "конференциями" из 2 человек ради унификации кода.
> Я имею ввиду, как проще было бы получать все контакты пользователя и его конференции один запросом Я не думаю, что это обязательно, можно и не одним наверно. Хотя может быть как-то выбирать их вместе было бы удобнее.
> Как лучше сохранять не отправленные сообщения? Можно сохранять их в localStorage. Но тогда есть риск, если пользователь на каком-нибудь общем компьютере набирал сообщение, то потом его может найти и прочесть другой человек. Можно сохранять сообщение на сервер. Но тогда может человек сотрет сообщение, а на сервере оно сохранится. Тоже некрасиво. Также, сохранение не будет работать в оффлайне.
В общем, если заботиться о приватности, то лучше сообщение никуда не сохранять, если не заботиться, то на сервер и/или в localstorage.
Вообще, оффлайн-работа - интересная тема, но конечно она сильно усложнит твой код, возможно его придется целиком переделать. Ведь мессенджер по большому счету, вполне может работать какое-то время в оффлайне. Например ты переключаешь на контакт, история не загружается, но ты можешь писать сообщения, которые отправятся при восстановлении связи с сервером. Мессенджер без оффлайн-работы на мобильных устройствах, например, неудобно использовать.
Еще одна вещь - мне кажется, хорошим тоном было бы до отправки сообщения в чате писать информацию о том, куда сохраняется история этого чата. Чтобы пользователь знал, где будут храниться его сообщения. Никто почти так не делает, я только один раз видел это в каком-то линуксовом мессенджере, он спрашивал, надо ли сохранять историю. И это многое говорит об отношении разработчиков к приватности пользователя.
> Как сделать уведомление о том что пользватель набирает сообщение? Вообще, это как раз тот случай, когда на БД это реализовать неудобно. По идее да, клиент должен посылать уведомление на сервер, тот сохранять куда-то (в таблицу уведомлений?) и отдавать другому клиенту. Уведомление желательно сделать актуальным только на небольшой период времени, чтобы при отсоедиении клиента у его собеседника не висело это уведомление вечно.
В случае с использованием comet, вебсокетов или аналогичных технологий уведомление можно никуда не сохранять, а просто переслать от одного клиента другому (через демон-ретранслятор на сервере или может быть даже напрямую, если есть возможность установить peer-to-peer соединение между клиентами).
> Я правильно вывожу новые элементы? Вообще, нет, это очень плохой код, так как невозможно понять структуру HTML кода и невозможно там что-то править. Какая-то нечитаемая каша получилась. Тут нужно использовать шаблонизатор (тысячи их):
Условно к "шаблонизаторам" можно отнести еще knockout, react и часть фреймворка angular.
Вдобавок у тебя там по моему еще уязвимость XSS есть - что если имя пользователя содержит угловые скобки например?
> Ничего то что я называю методы отображения одним словом, например, $view->index()? Я имею ввиду, мы же всё равно пишем $view, писать $view->viewIndex() похоже на тавтологию. Вообще, плохо. Лучше называть методы начиная с глагола, например, showIndex.
Также, не очень понятно, почему ты для АПИ код контроллера пишешь прямо в файле, а для обычных страниц делаешь классы-контроллеры. Никакой разницы с точки зрения MVC между выдачей обычной страницы и обработкой АПИ-запроса нету.
Обрати внимание, что АПИ обычно версионируют, то есть URL выглядт как https://example.com/api/v1/something - это позволяет плавно мигрировать на новые версии АПИ, не ломая совместимость для старых клиентов. Ты не исплоьзуешь роутер, но можешь сделать это, просто создав папку v1.
Также, некоторые разработчики активно используют возможности HTTP (дополнительные заголовки, методы вроде PUT/DELETE, коды ответов), а некоторые не используют.
Также, перед проектированием АПИ, советую почитать про REST и HATEOS (и далее, стандарт про шаблоны URL https://tools.ietf.org/html/rfc6570 ), но тут конечно есть разные мнения, ну к примеру в иделогии REST одним запросом нельзя получить несколько несвязанных массивов данных, а HATEOS раздувает размер ответа.
Также, когда ты делаешь АПИ, возможно тебе захочется его документировать, и тут есть готовый инструмент http://swagger.io/ , который генерирует удобную документацию из JSON/YAML-описания API. Это JSON-описание можно писать руками, можно генерировать. Так как там описываются параметры запросов, то это описание можно использовать и для документирования, и для проверки входных параметров. Даже если документация не нужна, все равно его можно использовать для проверки данных.
И еще там упоминается JSON Schema, это стандарт для описания формата JSON-объектов (с возможностью проверки их соответствия схеме) и его тоже можно глянуть.
Ну и конечно, если ты все это изучишь и у тебя останется время, АПИ можно покрыть автоматизированными тестами. Урок про тестирование где-то в шапке.
> 'id' => $message->getId(), > 'author' => $message->getAuthor()->getName(), Может, это стоит хотя бы в функцию вынести (экспортирование данных из объекта).
Также, если ты отдаешь JSON, нужно выставлять (и проверять на клиенте) правильный Content-Type. Ну это же основы HTTP.
> $user->setId($result['id']); > $user->setLogin($result['login']); > $user->setName($result['name']); Возможно, тут стоит сделать метод для создания объекта из массива.
Также, нет SQL-дампа базы в репозитории.
Насчет проектирования БД - там тоже много тонкостей есть, можно делать нормальзованную схему, но лучше денормализовывать ради повышения производительности. Ну например, возьмем то же сообщение. Можно хранить его в одном экземпляре, а можно в двух - в inbox получателя и в outbox отправителя. Это может облегчить выборку последних N сообщений, так как твой запрос с OR вряд ли хорошо ложится на индексы (вдобавок у тебя еще и сортировки там нет).
Вообще, SQL базы не очень хорошо подходят для таких задач, насколько я знаю, все нагруженные чаты в итоге пишут какие-то свои хранилища, заточенные именно под хранение сообщений. Но это конечно долго и сложно.
Также, у тебя система никак не оптимизирована для работы с большими объемами данных. Что, если у пользователя тысячи сообщений - ты все их разом загружаешь? Что, если у него тысяча контактов и чатов? Тут надо предусматривать частичную выборку данных.
composer.lock лучше не убирать из репозитория, так как он содержит конкретные номера версий библиотек, на которых код протестирован, и будет лучше, если пользователь поставит те же самые библиотеки. Обычно composer.lock не выгружают в случае библиотеки (так как это может вызвать конфликты с другими библиотеками), но у тебя приложение, и в нем вполне нормально использовать composer.lock.
Модель ведь по задумке должна хранить данные и реализовывать логику работы приложения, а не считать величину отступа где-то на странице. У тебя тут не MVC, а просто часть кода случайно помещена в классы с названиями Controller и Model.
> $('.contacts-not-found').remove(); Вот вместо постоянного копирования этих кусков кода, обычно удобнее найти элемент и сохранить ссылку на него в переменную и далее работать с этой ссылкой. Это сделает и код аккуратнее, и заодно и ускорит работу, так как $(..) имеет сложность O(N) от числа элементов DOM на странице, там оптимизирован только поиск по id.
Вот еще пример плохого использования jQuery: $('textarea[name="message"]').val($('textarea[name="message"]').val() + "\n");
Если есть время, глянь Knockout и React, Vue, Angular, Angular-light. Также, сразу добавлю, когда авторы Реакта пишут что-то вроде "реакт быстрый потому что использует Virtual DOM, а не медленный DOM", это надо понимать как "реакт быстрее аналогичного решения, которое работало по тем же принципам (перегенерация вида при изменениях), но постоянно бы обращалось к DOM", а не как "реакт быстрее остальных подходов". Ну например для обновления диалога, я не уверен что подход реакта будет быстро работать, это надо мерять.
Также, у тебя по моему не очень удачно реализован переход по истории:
> Contreller.prototype.getConversation = function(withUser) { > $.getJSON('api/getmessages.php?with=' + withUser, function(results) { > window.history.pushState({}, '', '/conversation.php?with=' + withUser); Во-первых, с историей лучше работать через JS-библиотеку, это позволит поддерживать браузеры без pushState(). Во-вторых, если со страницы диалогов вызвать эту функцию, в историю не запишется переход на ту же самую страницу? В-третьих, ты делаешь переход только после получения ответа, это плохо, так как при проблемах со связью и обновлении страницы переход не произойдет. Ну и нет обработки ошибок при выполнении запроса.
Их много, есть встроенные в фреймворки вроде Angular/React, есть отдельные.
Также, работу с АПИ наверно было бы лучше вынести в отдельный класс. Чтобы иметь возможность писать что-нибудь вроде backend.getMessages(...). Это позволит, может быть, позже туда вкрутить поддержку кеширования данных и оффлайн-режима.
В document.ready у тебя код идет стеной. Но лучше было бы, возможно, разбить экран на компоненты (список контактов, диалог и тд), и каждый реализовать в своем классе.
> PDO незачем в кишки прятать, что если я захочу в конфигурации БД указать PostgreSQL, а не MySQL? Это вряд ли имеет смысл, так как нужно, чтобы все SQL запросы соответствовали синтаксису MySQL и Postgres одновременно, а это сложно и почти никто поэтому не делает возможность выбора БД.
Это (сравнение строки с true) опирается на тонкости преобразования типов, которые люди вряд ли помнят и потому трудно понять, что делает код и верно ли он написан. Если ты хочешь проверить, что строка не пуста, то так и надо писать ($s !== '').
> Маркдаун не переваривает табы и игнорирует пробельные отступы. Нужно оформить блок как код (с помощью отступа или 3 косых кавычек) и все будет нормально.
> Алсоу, предложенный там вариант с strval не работает с массивами, Да, с массивами лучше написать свою функцию для проверки, что это массив, что он содержит значения нужных типов и тд.
> public function tearDown() > if ( !empty($this->insertedIds)) { > foreach ($this->insertedIds as $userId) { Есть более интересный метод - начать транзакцию в setUp и отменить ее в tearDown. Ну либо пересоздавать БД перед каждый тестом, но это тяжело. Либо писать такие тесты, чтобы они друг на друга не влияли.
> throw new DbException('Ошибка при получении хешей', 0, $e); Надо добавлять userId в сообщение, иначе как потом расследовать эту ошибку?
> function getHash($userId) > $this->sqlBuilder->select(); тут ты используешь объект у которого неизвестное начальное состояние. Правильнее создавать новый билдер. И вообще, я думаю что билдер тут не нужен, удобнее и быстрее написать SQL запрос, билдер используют, когда запрос может меняться в зависимости от условий.
> else $hash = false; Нужны фигурные скобки
> public function testGetHash() > $userid = 1; > $hash = $this->mapper->getHash($userid) Этот тест полагается на известное состояние БД. Было бы наверно лучше написать тест, который сначала вставляет хеш в БД, а потом пытается его прочесть - тогда он мог бы работать даже на пустой БД. Затем, можно написать тест, который вставляет запись, удаляет, пытается прочесть. И так далее.
> public function testGetHashWrongIDFail() > $userid = 700000; А как-то гарантируется, что в БД нет такого id?
> public function testGetHashIDAsStringFail() > $userid = 'fdfdf1'; лучше 1fdfd, так как оно при преобразовании дает 1
> public function testGetHashIDAsStringFail() > public function testGetHashIDAsArrayFail() > public function testGetHashIDAsBoolFalse() Вообще, если так писать для каждой функции, то объем тестов быстро растет. Такие вещи проще проверять тайпхинтами (в PHP7 ставится тайпхинт на числа), либо условием в начале функции.
Либо объединить их в один метод с массивом неправильных значений.
> public function testAddHashArrayFail() > $result = $this->mapper->addHash($userid, $hash); > $this->assertFalse($result); Вообще при ошибке лучше выкидывать исключение, а не возвращать false, который никто потом не будет проверять.
> public function testCheckSortByWhiteList() > $this->assertContains($sort_by, $this->sortbyWhitelist, 'Значение sort_by не из разрешённого списка'); Это плохая идея, проверять человеческие сообщения, так как стоит там переставить пару слов местами или добавить один пробел, как все сломается. Лучше проверять машинночитаемые значения, если их нет, можно просто проверить что массив сообщений не пуст.
> bool|mixed Returns string with field name on success, second field on false validation, or FALSE on internal logical error. Это тоже понять трудно. Единственное, что я понял, что при логической ошибке лучше бросать исключение. Тем более, что я не вижу, где там возвращается false.
Функция должна возвращать значения одного типа, иначе с ней невозможно работать. Не должно быть такого, что функция возвращает то строку, то массив - это мина замедленного действия.
И кстати, у тебя много где возвращается false, а ты везде, в 100% случаях это проверяешь и обрабатываешь? Уверен, что нет. Надо использовать исключения и тогда проблемы не будет.
> if (array_key_exists($fieldname, $this->input) > && > ( ($key = array_search($this->input[$fieldname], $this->fieldsWhitelist, false)) !== false ) Это тяжело читать, надо выносить части условия в переменные. Или сделать тут два if вместо одного.
Вообще, класс SearchQueryValidator какой-то странный, он там даже подсчетом числа страниц занимается зачем-то. Функции названы неправильно. Например, функцию checkPage() правильнее назвать getOffsetAndLimit(), убрать оттуда ссылки, а может, разбить на 2 функции. А еще лучше убрать этот $this->input и явно передавать в функию номер страницы. На мой взгляд, тут лучше вообще убрать $this->input из класса. И убрать расчет пагинации, так как он тут ни к селу, ни к городу.
> if (preg_match('/ORDER BY/ui', $this->sql) == 0) { Это неправильно, так как слова ORDER BY могут встретиться внутри строки или подзапроса. Не надо тут анализировать SQL код, свойства запроса надо хранить в полях объекта.
> const DELETE_BY_ID = 'DELETE FROM <table_name> WHERE `userid` = :userid' . self::space; Нет причины выносить это в константу.
Ну и ты там везде добавляешь COUNT_ROWS, но может он не всегда нужен. Он ведь влияет на производительность.
В маппере не стоит преобразовывать исключения, так как это раздувает код, а на практике скорее всего никак не используется. Только если в учеюных целях, но тогда надо сделать сообщения более подробными.
> $this->studentValidator->dataSent(); Название функции начинается с глагола.
> $this->studentValidator = new StudentValidator(new StudentMapper($this->pdo), $input); > $datasent = $this->studentValidator->dataSent(); > $student = $this->studentValidator->checkInput($errors, $datasent) Этот код какой-то переусложненный. Почему мы вызываем 2 функции? Что значит dataSent?
> array $inputArray Input, containing 'password' and 'user data' of current user of site. > function __construct(PasswordMapper $mapper, array $inputArray) Почему тут массив, а не просто 2 переменных password и user_data? Из за этого код только тяжелее читать становится.
И вообще, зачем в конструктор передавать пароль, если напимер метод logIn() их не использует? Как-то странно спроектирован класс.
> !isset($defFields['mascVal']) || !isset($defFields['femVal']) Проще передать один объект студента, у которого все нужные поля гарантированно существуют, чем мучаться с массивом. Тут нужен объект, а не массив.
Также, у тебя почему-то 2 шаблона формы регистрации, зачем?
В общем, там еще много чего надо исправлять, давай потихоньку разбираться, если что, пиши вопросы, так как я мог что-то непонятно написать. Пока код переусложнен, MVC тут какой-то странный, многие классы тоже спроектированы странно.
> if ($appStatus !== 0) { > set_exception_handler(function ($e) { Не вижу смысла отключать обработчик на dev
> set_error_handler(function ($errno, $errstr, $errfile, $errline) { > self::addToLog($errno, $errstr, $errfile, $errline); Это не нужно так как исключение будет залоггировано, если не перехвачено. А если оно перехвачено, значит логгировать не требуется.
> self::ensure(!is_null($appStatus), "Не удалось получить настройку режима работы приложения."); Проверку аргументов функции надо ставить в начале. Я бы поставил is_bool тогда.
> static public function getConfigElement($elemName) Непонятно, что работа с конфигом делает в обработчике ошибок.
Логгировать удобнее в стандартный файл ошибок, а не в отдельный файл. Проверять размер лога тогда не потребуется, так как этим занимается отдельный скрипт logrotate в линуксе. Мне кажется, ты зря изобрел свою систему логгирования. Ну и кстати, если ты захочешоь именно свою систему логгирования, бери готовую PSR-совместимую библиотеку логгера.
> Что бы защититься от уязвимости sql - нужно санитайзить переменные непосредственно перед тем как он попадет в базу? Если например нет возможности удостовериться, что селекты и инсерты выполняются через плейсхолдеры где-то там в ядре фремворка, на котором написан проект, правильно? Если нет возможности убедиться, то там может быть произвольное число уязвимостей. Можно конечно каким-нибудь сканером потыкать, но не факт что он их найдет.
> То это уже во вьюхе при выводе инфы от юзеров в шаблон нужно обмазывать? Что бы потенциальный js код не поставился во вьюху и не выполнился вредоносно? Конечно, это XSS называется.
> Что по поводу аплоада файлов, ни слова не сказано как защититься от загрузки pidor.php в папку с аватарками и дальнейшим доступом ко всему коду / в админку проекта. Есть немного информации в задаче про файлообменник https://gist.github.com/codedokode/9424217
> всех нужных объектов и данных приведёт к большому куску кода, которому абсолютно нечего делать в index.php и тому подобных скриптах Делаем либо скрипт container.php, либо класс, либо, что лучше, просто кладем заполнение контейнера в бутстрап-скрипт или класс. Думаю, проще всего не преумнодать сущности и положить все в бустрап-скрипт.
С основ сетевых технологий и обычных сокетов Беркли. У меня были задачи, решишь?
Есть такие задачи: http://arhivach.org/thread/204328/#853691 - если тебе очень не хочется разбираться в особенностях протоколов, первые задачи можно пропустить, но не советую, знания тебе потом пригодятся при отладке программ.
Сделай например клон мобильной версии гиктаймса (m.geektimes.com) либо роема (m.roem.ru), либо новостного сайтпа вроде медузы, что сможешь. Желательно код оформить в виде темы и/или плагинов и выложить на гитхаб без кода вордпресса, так как зачем нам смотреть код вордпресса?
Верстка у тебя пока кривая, переключалка картинок должна работать в новых браузерах без яваскрипта. Бутстрап ты подключил зря, от него в шаблоне ничего нет и он только вредит и утяжеляет страницу.
Шрифты не как на макете.
В HTML коде куча мусора, например: > <meta content="" property="og:image" />
И некоторые сомнительные теги: > <meta content="telephone=no" name="format-detection" />
> based in Jupiter and we would love<br> to turn ideas into Лучше без br
В исходнике сайта у тебя какой-то подозрительный и явно вредоносный зашифрованный яваскрипт:
Какую хочешь, обычно для картинок это размер и формат, для аудио/видео можно добавить длительность, битрейт, кодеки. Посмотри, что дает getId3 и из этого что-нибудь возьми.
> http://ideone.com/tMu8IN кубики Все верно, только exit тут не нужен так как выполниться может только один из 4 блоков.
>http://ideone.com/xutDDU кредит Теперь можно удалить проверку что долг меньше нуля, и может быть у тебя получится объединть 2 ветки if (когда долго больше и когда меньше 5000) вместе, так как код в них похожий.
> $count=count(${'word' . $x}); Вот это уже неправильно. Если ты хочешь обращаться к переменной по номеру, то нужно сложить эти переменные в массив и обращаться к нему.
> Почему в Сфинксе при добавлении строки, в поле вставляется 0 заместо нужного значения? Не знаю, но можно подсоединиться к сфинксу и просто выбрать данные через SELECT. Может у тебя поле как числовое создано? Также учти что сфинкс это поисковой движок, а не хранилище, и он хранит только атрибуты, но не хранит сами проиндексированные тексты.
> Ещё, после обновления конфига ничего не меняется. Э? А почему оно должно меняться? Для обычных индексов надо заново запустить индексацию. Это индексер ведь выкачивает данные из базы и создает/обновляет индексы. Для RT-индексов надо дропнуть их и пересоздать заново наверно. Или может демон перезапустить.
> И после перезагрузки ещё постоянно удаляется папка /var/run/sphinxsearch Возможно что /var/run очищается при перезагрузке. Можно создавать pid прямо в ней.
> Как определить rt_field и rt_attr_uint, если нужен поиск только по одной колонке? Надо изучить в чем различие между полями и атрибутами. Поля используются только для индексирования текста в них и не сохраняются. Атрибуты не добавляют текст в индекс, но сохраняются и их можно использовать в условии WHERE.
> Ещё, при индексации я получаю сообщение "Skipping non-plain index 'rt'...", Не знаю, что это значит. Ты можешь попробовать включить в конфиге или опцией командной строки режим более подробного вывода логов (verbose или как-то так) и поискать причину там.
Я думаю, docs[0] значит число документов, содержащих первое поисковое слово keyword[0]. Поиск ведь ведется так, что для каждого слова в индексе ищутся id документов, а потом эти списки id объединяются в соответствии с текстом запроса (тут немного упомянуто: https://habrahabr.ru/post/263823/http://www.pvsm.ru/java/24146 ).
Файлообменник. Есть контроллер file с экшнами index и addCommentAction. Первый передает во вьюху всякие данные и рисует страницу с данными о файле. Второй производит валидацию и добавляет комментарий в базу данных. Проблема такая: как передать из второго экшна в первый при неправильной валидации названия некорректных полей формы и описание ошибки к каждому полю, через GET или POST? Я хочу это сделать, чтобы не собирать такой же шаблон как и в экшне Index (DRY). В случае GET получается странный роут...
$app->get('/{fileId}[/{wrongFields:.*}]', function ($request, $response, $args) { $wrongFields = explode('/',$request>getAttribute('wrongFields')); });
Количество неправильных полей неограничено, переданные таким образом значения закинутся в массив ($errors[] = $calue), а затем в шаблоне я укажу пользователю неправильные поля. Но таким образом не будет расшифровки ошибок из-за формата роута.
В случае с вариантом POST меня смущает создание дополнительного шаблона с данным методом. Т.е. в конце метода addCommentAction будет...
Тысяча извинений за офтоп, пытаюсь осилить хтмл в подробностях, есть несколько вопросов: 1. Есть ли смысл НЕ закрывать одиночные теги? Типа <br /> 2. Какой вообще смысл использовать method="get" вместо post? 3. Кто-нибудь вообще использует <code> <kbd> <samp> <var> <pre> ? 4.Посмотрел отличия XHTML от HTML, так и не понял: когда на практике используют XHTML?
>>1001347 >1. Есть ли смысл НЕ закрывать одиночные теги? Типа <br /> Зачем ставить слеш? Кажется в XHTML никто не будет вкатываться, HTML5 подъехал.
2. Какой вообще смысл использовать method="get" вместо post? Это для серверной части. Гет используется для передачи параметров в адресной строке, тупо текстом(потом эти параметры разбираются в каком-нибудь фронт-контроллере), Пост - для передачи параметров в суперглобальный массив $_POST, сразу на сервер, иногда нужно передавать в гет, иногда в пост.
3. 3. Кто-нибудь вообще использует <code> <kbd> <samp> <var> <pre> ? хуй знает, я специально вообще хтмл не учил, по мере необходимости гуглю нужные теги, использую <pre> в php, что бы в тестах выводимые данные отображались прилично, а не сплошным текстом, в гугле есть точное описание каждого тега.
>4.Посмотрел отличия XHTML от HTML, так и не понял: когда на практике используют XHTML? Настолько я понял XHTML пришёл на замену HTML, но внезапно(нет) выкатили HTML5 и все радостно на него перекатились, а про XHTML забыли.
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме. ОПу ведь все это читать придется.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: ( http://arhivach.org/thread/254710/ )
Еще предыдущие треды ищутся в гугле по словам "клуб php" или в архиваче. Еще есть такой архив тредов: http://phpclub.rf.gd/
Мейлач лежит? Есть запасной тред: доброчан-орг/s/res/23225.xhtml#i46467
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 2/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.
Платиновые вопросы
- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
- Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery
- Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/.
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
- Что самое главное для программиста? Умение аккуратно оформлять код.
- ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
- Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.