Ответы пользователя по тегу PHP
  • Как организовать генерацию номеров тикетов?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Как это сделано у Redis, алгоритм Redlock:
    1. понадобится доп. поле для случайной строки;
    2. генерите случайный ID и случайное значение;
    3. вставляете в таблицу запись с этим ID и значением. БД не позволит вставить, если уже есть такой ID.
    4. Читаете эту запись и её доп.поле. Если считанное доп.значение совпало с вашим сгенеренным случайным значением – всё круто, этот ID ваш, можно его использовать;
    5. Если считалось, но там другое значение доп. поля – придётся снова генерить новый случайный ID и сл. значение ему в пару – до тех пор, пока не попадёте пальцем в небо. Чем больше тикетов в системе, тем дольше может понадобиться погадать. И скорее переписать всю ущербную систему на последовательную нумерацию записей и генерацию не выглядящих последовательными биьективных трансформаций из них (самое простое – инверсия порядка битов).


    Upd. подробнее об идее с перемешиванием битов последовательных ID, чтобы они выглядели непоследовательно. Самый простой вариант однозначного соответствия между двумя множествами это инверсия порядка битов. В БД храните последовательные возрастающие ID. Тип INT в MySQL занимает 4 байта, это 32 бита. Для отображения их клиенту вы в PHP или NodeJS (они все 64-битные) инвертируете порядок бит в младших 4 байтах. Например:
    было 199
    00000000 00000000 00000000 11000111
    стало (зеркально)
    11100011 00000000 00000000 00000000
    это 64-битное число 3808428032
    
    было 200
    00000000 00000000 00000000 11001000
    стало
    00010011 00000000 00000000 00000000 (318767104)


    Такое зеркалирование порядка – операция обратимая. Дважды отзеркалить – будет исходное. Поэтому клиентам показываете эти сложные номера, у себя ведёте последовательные упорядоченные ID.

    Код для реверса порядка бит на JS и PHP я уверен, вы напишете самостоятельно. Подскажу, что для увеличения скорости операции удобно использовать небольшую таблицу байтов 16x16.
    Ответ написан
    Комментировать
  • Как правильно хранить контент сериала?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Для каждого нового сериала новые таблицы? – нет, это неприемлемо.

    Сделайте примерно так:
    • Таблица «Сериалы»: id, название, год, описание, режиссёр, рейтинг IMDB и т.п.
    • «Серии»: id_сериала, id_серии (в формате S02E05), ссылка
    • «Оценки»: id_юзера, id_сериала (+id_серии?), оценка
    • «Юзеры»: id, ник, хэш пароля, дата последнего визита
    • «Комменты»: id, id_сериала, id_юзера, текст коммента


    Ответ написан
    1 комментарий
  • Как строчное число перевести в численное?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Набросал класс для конвертации.

    Принцип действия:
    1. разбить фразу на массив слов по пробелам;
    2. разбить на группы слов по разрядам троек – по словам «тысяч», «млн» и пр.;
    3. внутри этих групп оставшиеся слова переводятся в числа 0..999 по одинаковым правилам;
    4. домножить на соотв. экспоненту десяти ( в 0-й, 3-й, 6-й степени) и сложить.


    Ответ написан
  • Как правильно сделать пост на стене группы при помощи Вконтакте API wall.post?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Токен нужно получить с того же IP, что и будет вызываться метод. Будете вызывать с сервера – надо получать токен, используя этот сервер как прокси для захода браузером в ВК.
    Ответ написан
    3 комментария
  • Как грамотнее сделать, добавление ID пользователя к задаче, или ID задачи к пользователю?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Таблица "Подписки": user_id, page_id

    Primary key – составной индекс из обоих столбцов, просто-индекс по page_id для поиска.
    Ответ написан
    4 комментария
  • Как организовать уведомление о новой заявке на landing page в личку VK?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Варианты:
    1. личное сообщение сообщение от вашего «запасного» аккаунта ВК;
    2. сообщение от Сообщества (группы);
    3. уведомление от Приложения ВК;
    4. смс (платно).

    Метод messages.send() отправляет сообщение от пользователя или сообщества; secure.sendNotification() – уведомление от приложения; secure.sendSMSNotification() – эсэмэсина от приложения. Наверное, лучше сделать сообщение от Сообщества.

    Создайте себе новую закрытую группу, где будете только вы. Включите сообщения сообщества и получите ключ (просто скопируйте его из Настроек сообщества – Работа с API.

    При событии в лендинге откройте скриптом ссылку API ВКонтакта, например, так:
    $url = "https://api.vk.com/method/messages.send";
    $params = [
    	'user_id' => 123456, // ваш user_id в ВК
    	'message' => 'Новая заявка!',
    	'access_token' => $TOKEN, // токен сообщества
    	'v' => 5.62
    ];
    $url = $url . '?' . http_build_query($params);
    file_get_contents($url);
    Ответ написан
    1 комментарий
  • Как вывести каждый день текущего месяца?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Символ 't' в функции date() даёт число дней в текущем месяце. Очень удобно!
    $last = (int) date('t');
    $d = 1;
    do{ echo $d . PHP_EOL; } while($d++ < $last);


    Ideone
    Ответ написан
    Комментировать
  • Как автоматически с интервалом постить изображения из альбома ВК на стену сообщества?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    1. создать Standalone приложение ВК;
    2. получить для него токен админа/редактора сообщества с правами photos, wall;
    3. запускать по расписанию на сервере, брать очередное фото photos.get() и постить wall.post() на стену – всё через api ВКонтакте.
    Ответ написан
    Комментировать
  • Как получить куки с заголовками через guzzle?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Guzzle имплементирует для response psr интерфейс Psr\Http\Message\ResponseInterface
    $res->getHeaders(); // вернет массив всех заголовков


    Про работу с cookies см. документацию Guzzle.
    Ответ написан
    Комментировать
  • Какой создать хеш при передачи api?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Например, как это реализовано у ВКонтакте. Посетитель авторизуется на основном сайте. Для выполнения запросов к api он получает токен – хэш от его id, иногда ip адреса или подсети, «секрета» самого ВК, «секрета» приложения. С любым запросом к api идёт этот хэш, который гарантирует только то, что запрос пришёл от имени такого-то пользователя (и с валидного IP, а не «вдруг» с другого континента).

    Кроме этого, при запросе вычисляется хэш от параметров запроса и «секрета» приложения. Это позволяет убедиться в том, что параметры запроса не подделаны в клиенте – т.к. «секрет» приложения не покидает серверов и не попадает в клиент.
    Ответ написан
    Комментировать
  • Найти в строке подстроку, которая содержит максимальное количество последовательных символов в этой строке?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Надо двигать концы отрезка: правый R и левый L. Изначально оба на нуле.
    Держим текущий набор символов, чтобы проверять на повторы. Помним найденный максимальный отрезок.
    Двигаем правый конец на 1. Если символа нет в наборе, добавляем. Если есть, двигаем L вправо за найденный символ. Перед этим проверяем, а не нашли ли мы очередной максимум.

    Очень кривая спать-хочу реализация, вроде, работает: Ideone

    Старый ответ, please ignore: Двигаться по одному символу. Помнить найденную макс. длину. Сравнивать символ с предыдущим.
    Равен – длина текущего сегмента растёт.
    Не равен – закончился предыдущий сегмент и начался новый. Если длина больше найденного максимума – найден очередной кандидат. Запомнить его длину и начало. Запомнить начало очередного сегмента и считать длину с 1.

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

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Надо как-то определять момент «выхода» пользователя. Будь то таймаут после последнего действия или регулярный ping.

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

    И да, согласен с предыдущим оратором, самым элегантным решением, по-моему, является Redis. Он, в т.ч., умеет хранить данные с заданным временем жизни – если вы выберете вариант с таймайтом после последнего действия.
    Ответ написан
    Комментировать
  • Получить ссылку на скачивание файла с внешнего сервера, и отдать как от своего?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Можно сконфигурить свой nginx так, чтобы при запросе к определенному пути, запросы передавались на тот сервер. Например, вы получили путь к файлу "totServ.com/get/file/abcd-1234". У себя настроили, что все запросы к папке "svojServ.ru/dl/" проксируют запросы туда. И отдаёте пользователю ссылку "svojServ.ru/dl/abcd-1234"
    Ответ написан
    Комментировать
  • Как заменить ключ следующим значением?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Неплохо использовать встроенные функции array_chunk() и array_reduce() :
    <?php
    function pair( $arr) {
    	function keyValue( $result, $item) {
    		$result[ $item[0]] = isset($item[1]) ? $item[1] : null;
    		return $result;
    	}
    	return array_reduce( array_chunk($arr, 2), 'keyValue', []);
    }
    
    print_r( pair( [1,2,3,4,5] ));
    /* Array (
        [1] => 2
        [3] => 4
        [5] => 
    ) */
    Ответ написан
    Комментировать
  • Запуск скрипта через cron?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Вообще веб-часть не нужна. Через крон запускайте скрипт как локальную команду: /usr/bin/php script.php
    Ответ написан
    2 комментария
  • Как сделать обработку формы по двум submit?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Нажатый "submit" передаст своё имя-значение. Ненажатый "submit" – не отправит.
    if( $_POST['message'] === 'Отправить') {
        // отправляем сообщение
      } else if( $_POST['recall'] === 'Перезвонить') {
        // перезваниваем
      }
    Ответ написан
    Комментировать
  • Как сгенерировать последовательно набор из одной буквы и две цифры в PHP?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    В базе данных или где-то ещё хранить последовательные целые ID, присваиваемые пользователям.

    Остаётся сделать мэппинг из целых 0, 1, 2, ... в A00, A01, ... A99, B00, B01, ...

    26 значений (A–Z), 10 значений (0–9), ещё 10 значений (0–9) – 2600 значений всего получится записать в три таких разряда. Вам этого точно достаточно?

    <?php
    function encode($n) {
      if($n >= 2600 || $n<0) throw(new Exception('Out of range 0 <= n < 2600'));
      return chr( 65 + floor( $n / 100)) . sprintf( '%02d', $n % 100);
    }
    
    echo encode(1654); // Q54

    Проверяем, чтобы на вход пришло число не больше 2599 ("Z99") и не меньше 0.
    Берём символ по его ASCII-коду функцией chr(): А=65, B=66 ... Z=90. Чтобы получить из сотен нужный код, делим $n на 100 и округляем вниз. Получается от 0 до 25. Прибавив 65 получаются значения от 65 до 90 – как раз коды от A до Z.

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

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Наверное, надо написать что-то похожее на cинхронизацию времени между клиентом и серверами в NTP. Это потребует нескольких запросов к серверу, чтобы оценить время отклика – т.е. не сразу с загрузки страницы удастся точно запустить таймер. Показать его можно сразу, и в течение следущих секунд скорректировать. Есть готовое решение: NTPJS, не пробовал.

    В простейшем варианте можно обойтись одним AJAX запросом после полной загрузки страницы. Запомнить текущее локальное время var tPing = (new Date).getTime();, запросить ajax'ом с сервера его текущее время tServ, получить ответ и запомнить локальное время tPong, когда ответ получен. И положиться на очень грубую гипотезу, что сервер ответил точно посередине интервала tPing..tPong. Т.е. решить, что разница серверного времени и локального составляет ровно tDiff = tServ - tPing + (tPong - tPing) / 2;

    Теперь для получения предполагаемого серверного «точного» времени, просто прибавлять к текущему локальному времени этот tDiff.
    Ответ написан
    1 комментарий
  • Как правильно шифровать ссылку на видео?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Передавайте потоковое видео. Например, через Amazon CloudFront или установите свой стриминговый сервер – к примеру nginx умеет.
    Ответ написан
  • Подписан ли человек на такую группу и оставлял ли он там фотографии?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Метод users.getSubscriptions() возвращает подписки юзера. Если user_id не указывать, вернёт ваши подписки. Вот такой нехитрый код в процедуре execute() (прямо на той странице его вставьте и «Выполните») вернёт два массива: ваши и его id групп:
    var uid=12345; 
    return {
      "my": API.users.getSubscriptions().groups.items,
      "her": API.users.getSubscriptions({"user_id":uid}).groups.items
    };

    В первой строке задаётся id "того юзера", с кем сравнивать.

    Эти два массива остаётся сопоставить. Можно в скретч-паде браузера выполнить следующий код:
    var r = 
    {"response":.....} // тут целиком ответ из метода execute
    ;                  // и точка-с-запятой в конце.
    var common = [];   // сюда попадут id общих групп
    for(var i=0;i<r.response.my.length;i++){
      if( !!~r.response.her.indexOf( r.response.my[i])) 
        common.push(r.response.my[i]);
    }
    common;   // если в Scratchpad Firefox'а нажать Ctrl+L, 
              // код выполнится а в коммент вставится содержание этого массива


    Постил ли фотографии – надо просмотреть всю фото методом photos.getAll(). Параметр owner_id – по очереди, каждой из общих групп. У каждой фотографии смотреть значение поля user_id – нужны только те, где оно равно искомому юзеру.

    За один вызов метода можно получить до 200 фотографий, поэтому добавляем параметр count=200 и параметром offset листаем по 200 снимков вглубь истории. Можно опять методом execute зарядить сбор – так будет по 25*200 = 5000 фото за один вызов.
    Ответ написан
    Комментировать