• Почему preg_replace заменяет кириллицу на другие символы или вообще не работает?

    @sewar
    $format_price = preg_replace('/руб\.?$/u', '', $format_price);
    Ответ написан
    Комментировать
  • Почему php разработчики используют .htaccess как часть системы?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Незачем пытаться охватить все веб-серверы. Для урока авторы, видимо, решили, что «сойдёт и так» – на примере одного из популярных, Apache.

    Вы уже переросли песочницу тех уроков и знаете другие варианты. Значит, сумеете понять и перенести правила из .htaccess в конфиг NGINX. С помощью Google, SO и Habr.QnA )

    Популярен паттерн "front controller" — когда веб-сервер конфигурят, чтобы все запросы падали только на корневой /index.php, а там уже логика внутри PHP узнавала запрошенный URL /section1/page2 и отдавала соответствующий ответ. Такие решения универсальны относительно веб-сервера.

    Файл .htaccess иногда кладут в проект, потому, что это легкий невидимый файл, который не помешает. Но поможет понять ожидаемое поведение веб-сервера. Конфиги NGINX лежат отдельно от проекта, поэтому их не прилагают. Хотя иногда приводят пример в документации.
    Ответ написан
    Комментировать
  • Как роботам показывать оригинал страницы, а пользователей отправлять редиректом на другой адрес?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Вы хотели сказать "чтобы весь сайт гарантированно вылетел из поиска"?
    Да, это надёжный способ
    Ответ написан
    Комментировать
  • Замена MongoDB?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Отличный повод избавиться от этого нелепого недоразумения и начать использовать нормальную БД.
    Если речь идёт о базе данных, то выбор огромный: mysql, postgres, sqlite, sql-server, oracle
    Можно выбрать себе СУБД по вкусу, спланировать структуру БД вместо той оргии с гетерами, которая применяется в Монге и начать пользоваться.
    Если речь идет об in-memory key-value storage то выбор поменьше, о тоже есть - redis или подзабытый уже нынче мемкеш.
    Ответ написан
    Комментировать
  • C чего новичку начинать изучение php?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Если на английском, то
    https://phptherightway.com/
    https://phpdelusions.net/
    https://www.youtube.com/watch?v=sVbEyFZKgqk&list=P...
    Ещё порекомендую по возможности приобрести книгу Джона Дакетта PHP&MySQL

    Ну и если есть вот прямо такое желание не превратиться в редиску позорящего (а с РНР это практически неизбежно, учитывая количество говнокода, который выдают за обучающие материалы всякие самозванцы, жулики и просто дурачки) то при сомнениях пишите сюда вопросы, мы всегда поможем разобраться и отличить зерна от плевел
    Ответ написан
    2 комментария
  • Как оптимизировать COUNT(*)?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    создайте таблицу в ней что то типа rows_matched
    при инсерте нужной фразы добавляйте 1
    при удалении вычитайте

    по итогу у вас вместо тяжелого селекта очень легкий запрос
    Ответ написан
    Комментировать
  • Как школьнику побороть выгорания и вкатиться в программирование?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Только мухоморы могут помочь спастись от выгорания и включить режим берсерка на длинной дистанции.
    Ответ написан
    Комментировать
  • Как называется такой тип верстки?

    SuperToster
    @SuperToster
    Что такое "тип вёрстки" — затрудняюсь.. Тут верстальщик хотел сверстать лендинг, но случайно нашёл плагин scrollmagic.io... И не смог остановиться )

    Если интересно как сделать подобное, смотрите примеры: scrollmagic.io/examples/index.html, читайте доку.

    Но пользуйтесь в меру. Не как в приведённых вами шаблонах.
    Ответ написан
    Комментировать
  • Как получить четвертый элемент ассоциативного массива?

    Если за дополнительные строки кода или сэкономленную память не доплачивают, то:
    array_values($array)[3]
    Ответ написан
    Комментировать
  • Как автоматом очистить форматирование при копировании / вставке?

    @zkrvndm Автор вопроса
    Софт для автоматизации
    Нашел решение. Оказывается, существует событие paste, которое происходит, когда мы вставляем что-то в блок. Соответственно, можно повесить обработчик на него, отменить действие по умолчанию, а затем перехваченный текст обработать как душе угодно:
    document.querySelector('div[contenteditable="true"]').addEventListener("paste", function(e) {
            e.preventDefault();
            var text = e.clipboardData.getData("text/plain");
            document.execCommand("insertHTML", false, text);
    });
    Ответ написан
    Комментировать
  • Можно ли стать Java Senior разработчиком, если учится полгода-год по 2-3 часа в день?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Чтобы стать сеньором надо лет 8-10 коммерческого опыта.
    Ответ написан
    Комментировать
  • Что означает и зачем нужен + в начале prompt?

    y0u
    @y0u Куратор тега JavaScript
    dev
    Ответ написан
    Комментировать
  • Как работает сайт изнутри (глубокий технический анализ сайта)?

    toxa82
    @toxa82
    Xhprof вам в помощь.
    Ответ написан
    Комментировать
  • Хочу сделать API, с чего начать?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Следует начать с проектирования API. Возмите https://swagger.io/ и набросайте все, что нужно.
    Swagger вам позволяет объединить роутинг, документацию и примеры вызовов в единое целое.
    Кроме этого он позволяет сгенерировать заглушки для разных языков программирования и фреймворков.
    В принципе вы можете найти значительное количество интеграций для разных фреймоворков.

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

    В REST есть 6 принципов, прекрасно изложенных в Wiki. В REST нет ничего сложного и особенного. Это просто надстройка над стандартным протоколом HTTP. Именно поэтому нет никаких особенных уроков. Изучите работу HTTP и вы поймете как работает веб в целом и REST в частности.

    По поводу отдельного сервера для API. Есть множество разных подходов. В последнее время все более актуальными становятся Serverless-приложения. Serverless архитектура идеально вписывается в REST. Но думаю для вас это пока рановато и сложновато. Слишком много для начала.

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

    По поводу best practices есть очень хороший ресурс https://12factor.net/ru/
    Он в целом применяется для всех приложений.

    Запомните: первый блин всегда комом. Прочитайте все ресурсы, которые я привел для вас. В них много ссылок на другие, походите по ним, присмотритесь. Напишите первую версию API так, как вам кажется удобно. Постарайтесь применить практики из статей.
    Вам нужен опыт и вы его не наберетесь, пока не сделаете что-то сами. Вы можете потратить год на чтение, но останетесь на том же месте, с которого начали. А другой человек напишет на коленке API за неделю, а потом перепишет его 20 раз за год и он вам расскажет в 10 раз больше, чем то, что вы изучили за год.
    Дерзайте!
    Ответ написан
    16 комментариев
  • Nginx как создать домен 3 уровня?

    3vi1_0n3
    @3vi1_0n3
    Лучше пропишите нормальные имена в /etc/hosts
    127.0.0.1 server cdn.server
    потом добавьте в секцию server строку
    server_name server
    а в другую
    server_name cdn.server
    Ответ написан
    2 комментария
  • SQL инъекция в UPDATE возможна ли?

    Fernus
    @Fernus
    Техник - Механик :)
    Смысл есть!

    UPD:
    Поясню...я тебе в $id передам 9999 or 1 = 1 и все записи нафиг потерпят изменения!
    Ответ написан
    2 комментария
  • SQL инъекция в UPDATE возможна ли?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Инъекция может быть через любой запрос.
    И защищать тоже надо любые запросы.
    Никогда не надо торговаться, "а можно я не буду защищать именно этот запрос? Ну мааааам!"
    Надо просто всегда следовать простым правилам - любая переменная попадает в запрос только через плейсхолдер

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

    Уязвимость — это сама возможность с помощью переданных в запрос данных изменить его код.
    Даже если ты не знаешь ни одного способа ей воспользоваться, уязвимость от этого никуда не девается.
    Даже если та возможность, про которую ты знаешь, в данном случае не прокатит - остаются ещё тысячи других.
    Если есть уязвимость, то способы ей воспользоваться всегда найдутся.

    То есть сама уязвимость никак не зависит ни от каких второстепенных факторов - типа запроса, передаваемых данных, способов их валидации, твоих знаний SQL. Это сам факт. Можно подставить свой код в запрос? Значит он уязвим. А как конкретно можно нагадить - это отдельная тема.

    Кроме того, любая уязвимость - это всегда ошибки. Если в $id будет пусто, то запрос вызовет ошибку. Если в $id будет слово select то запрос вызовет ошибку. Если будет слово "привет", то запрос вызовет ошибку. Оно тебе надо?

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


    Если вопрос "а можно я не буду защищаться?" вызван ленью, то это тоже решаемо. В принципе, лень - это очень важное качество для программиста. Главное - направить её в нужное русло.

    Если каждый раз писать по три строчки долго
    $sql = "INSERT INTO users SET email = ?, password = ?"; // заменяем на знаки вопроса
    $stmt = $db->prepare($sql); // подготавливаем запрос, получаем stmt
    $stmt->bind_param("ss", $email, $hash); // два знака вопроса - две переменных - две буквы s
    $stmt->execute(); // выполняем запрос

    То надо воспользоваться такой вещью, как программирование. И написать функцию, которая возьмет на себя всю рутинную работу.
    function prepared_query($mysqli, $sql, $params, $types = "")
    {
        $types = $types ?: str_repeat("s", count($params));
        $stmt = $mysqli->prepare($sql);
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        return $stmt;
    }

    и в итоге предыдущие 4 строчки превратятся в одну:
    prepared_query($db, "INSERT INTO users SET email = ?, password = ?", [$email, $hash]);

    или твой запрос:
    prepared_query($db, "UPDATE table SET test WHERE id = ?", [$id]);

    - просто, быстро, удобно и безопасно
    Ответ написан
    26 комментариев
  • Как хранить ID категорий в базе?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Для нормальных разработчиков, а не хипстеров, разъясняем:

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

    В данном же случае необходимо использовать стандартный способ со связанной таблицей. Поскольку при использовании стандартных методов хранения можно пользоваться всеми возможностями, которые предоставляет БД, такими как контроль целостности данных, компактность хранения, использование в индексах и так далее. Не говоря уже о простоте запросов и поддержке со стороны существующих библиотек.
    Ответ написан
    Комментировать
  • Как правильно работать с большим количеством данных?

    @rPman
    Избавляйся от ... where fld like '%...%' это самые плохие по скорости запросы, хотя не всегда это возможно без увеличения размера базы, вообще полнотекстовый поиск можно отдавать на откуп стороннему приложению (это может расширить возможности фильтрации), считай это еще одной формой индекса, хотя лучше данные по другому хранить. Я встречал ситуации когда в varchar хранили значения справочника из десятка значений, но делали по нему like %% что грузило базу прилично, когда как сделать простой комбобокс на порядок эффективнее и удобнее - поиск по подстроке лучше по справочнику делать на клиенте.

    Без индексов скорее всего никуда, если в запросе идет фильтрация по полю, то если не создать на него индекс, этот запрос и будет создавать нагрузку

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

    Частный случай прогноза, не делать select ... limit ... на каждую страницу, а при смене фильтра запрашивать весь диапазон, но только идентификаторы, сохранив их либо в таблице на сервере либо на бакэенде, генерирующим запросы вида select ... id in (...), последнее если количество записей не больше тысяч. Кстати именно постраничная навигация с прогруженным списком id самая шустрая

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

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

    p.s. диск на сервере hdd или ssd? если не хватает денег на большой ssd, настрой маленький ssd как кеш к медленному hdd (linux bcache), даже когда данные полностью не влезают в кеш, это дает заметный прирост, потому что hdd начинает менее случайно двигаться, плюс добавляется буферизация записи (данные записываются на ssd и лежат там пока hdd не освободится), так же дает эффект ускорения записи вынос журнала файловой системы (если ext4) на ssd (требуется пара гигабайт от силы).

    Осторожно, если высокие требования к надежности хранения, кеширующий ssd в режиме записи лучше пусть будет хотя бы raid1, так как иначе при смерти ssd починить данные, размазанные по диску и кешу будет очень сложно. Для кеша только для чтения это не так критично (при смерти ssd сервер просто упадет, не убивая данные).

    Но мне больше нравится резервирование на лету (настроить онлайн репликацию, пусть и на слабый, бакап сервер)
    Ответ написан
    1 комментарий
  • Как правильно работать с большим количеством данных?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Не хочется ругаться, но вопрос очень бессвязный и в нем перемешаны реальные проблемы с нелепыми фантазиями.

    И проблема тут не в незнании как работать с большими базами данных, а в неумении работать с БД в целом.

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

    Детсадовский запрос вида like '%...%' - это отдельный ужас. Надо смотреть на полнотекстовый поиск. А лучше вообще его избегать. На крайний случай использовать внешние поисковые сервисы типа эластика. И только не говори что этот лайк у тебя идёт по полю типа джейсон или "через запятую"

    Но самый конечно кошмар - это select distinct для фильтров. То есть неумение проектировать бд на самом базовом уровне, непонимание самых начальных принципов реляционных бд, нормализации. Вот с этих принципов и надо начать. В потом уже хвататься за большие объемы. Очевидно, что поля по которым ты собрался делать "distinct" - это должны быть отдельные таблицы, от которых в основной таблице будет просто id. поле размером в 4 байта.

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

    В общем, куда лучше бы смотрелись здесь не абстрактные рассуждения про большие объёмы, а конкретный запрос, который "отваливается". С обязательным результатом EXPLAIN

    А ответ на абстрактный вопрос "как работать с большими объемами" очень простой: точно так же, как с небольшими. Реляционные бд изначально проектировались под большие размеры. То есть надо просто уметь работать с бд. Читать про реляционную модель, нормализацию, индексы, оптимизацию запросов.

    Конкретно для грида надо смотреть в сторону Эластика/Сфинкса. В смысле чтобы не только для полнотекстового поиска, а чтобы все фильтры, которые есть выборке, были забиты в поисковый индекс. И все выборки - через поисковый сервис, а не через прямой запрос к базе
    Ответ написан
    8 комментариев