Ответы пользователя по тегу PHP
  • Как отправить файл POST из скрипта?

    valerium
    @valerium
    Изобретая велосипед
    Судя по всему, принимающий скрипт находится вне вашей власти или вам как минимум неьзя его править. Я угадал? :-)

    В документации PHP написано, что он "способен получать загруженные файлы из любого браузера, совместимого со стандартом RFC-1867". В стандарте RFC-1867, в свою очередь, введён тип кодирования "multipart/form-data". Следовательно, чтобы PHP понял, что ему передают не просто переменную в POST, а файл (и пометил его в массив $_FILES), нужно, чтобы клиент передал ему соответствующий тип. Так что можно либо внимательно изучить документ и организовать передачу самому, используя сокеты, либо внимательно изучить документацию в PHP к cURL.

    В PHP 5.5 изменились правила использования cURL, таким образом, чтобы передать файл, нужно использовать объект CURLFile (кстати, в русской версии документации этой страницы нет). В коде это будет выглядеть как-то так (не проверял).

    $ch = curl_init();
    $curlfile = new CURLFile('/home/user/we-are-champions.mp3', 'audio/mp3', 'best-song.mp3')
    curl_setopt($ch, CURLOPT_POSTFIELDS, $curlfile);
    $content = curl_exec($ch);
    curl_close ($ch);


    Ну, или просто откатитесь на более старую версию PHP (до 5.5) и используйте тот подход, который описан в ответе выше. Но это неразумно, на мой взгляд.
    Ответ написан
    1 комментарий
  • Как с помощью php поделить выражение в строке на составляющие?

    valerium
    @valerium
    Изобретая велосипед
    Если предположить, что разделитель заранее неизвестен, то задача становится гораздо интереснее :-) Для конкретности добавим ещё условие: строка состоит из двух чисел и разделителя.

    $input = '46/120';
    
    $i = 0;
    while ($input[$i] >= '0' && $input[$i] <= '9') {
        $i++;
    }
    
    $a = substr($input, 0, $i-1);
    $b = substr($input, $i+1);
    $delimiter = $input[$i];
    Ответ написан
    3 комментария
  • Какой запрос составить для выборки изображений из базы по заданым фильтрам?

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

    SELECT * FROM `images` WHERE
        `images`.`id` = `keyword-to-image`.`image_id` AND
        `images`.`id` = `colors-to-image`.`image_id` AND
        `keyword-to-image`.`keyword_id` = 234 AND
        `colors-to-image`.`color_id` = 345 AND
        `colors-to-image`.`color_id` <> 543;


    То есть мы получим все изображения, к которым привязано ключевое слово с id 234 и цвет с id 345, но при этом не привязан цвет с id 543. Количество этих AND можно легко менять в скрипте. Кроме того, сравнение целых чисел намного быстрее сравнения строк.

    Правда, это потребует перестройки всей базы данных, но только один раз, достаточно написать скрипт.
    Ответ написан
    1 комментарий
  • Перебрать правильно массив php?

    valerium
    @valerium
    Изобретая велосипед
    foreach $array['response']['items'] as $item {
        var_dump($item);
    }
    Ответ написан
  • Почему возникает ошибка при использовании функции mail?

    valerium
    @valerium
    Изобретая велосипед
    Директива sendmail_path принимает путь к исполняемому файлы, а Вы, похоже, указали только путь до папки, где лежит исполняемый файл.
    Ответ написан
  • PHP. поиск по слову?

    valerium
    @valerium
    Изобретая велосипед
    А почему бы не использовать регулярные выражения?

    Я так понял, нужна функция, которой передаются пять параметров, один из которых не обязателен. Тогда можно оформить так.

    function my_compare($haystack, $needle, $begin, $end, $middle = false) {
        // Используем "ленивую" особенность проверки условий в PHP
        $begin && $regexp[] = "$needle.+";
        $end && $regexp[] = ".+$needle";
        $middle && $regexp[] = ".+$needle.+";
    
        $result = array();
        foreach $regexp as $pattern {
            $result = array_merge($result, preg_grep($pattern, $haystack));
        }
    
        return $result;
    }


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

    valerium
    @valerium
    Изобретая велосипед
    Сжимать прямо в PHP приемлемо только если файлов немного и они небольшого размера. Большие файлы не успеют сжаться за стандартные 30 секунд, которые Apache отводит на исполнение скриптов. Так что если хотите масштабируемое решение, посмотрите в сторону сжатия в фоне.

    Простейший способ - очередь сжатия. После того как пользователь ставит галочки и жмёт "Скачать", скрипт записывает список сжимаемых файлов в, допустим, базу данных. Сидящий в фоне скрипт раз в минуту (условно) проверяет появление новых файлов в списке. Как только находит, начинает работу. При этом страница, которую видит клиент, раз в 10-15 секунд по аяксу запрашивает статус сжатия. Когда оно закончится, пользователю отдаётся ссылка на скачивание.

    Так же грамотным решением было бы использование специализированного менеджера очередей, вроде RabbitMQ.

    P. S. Позиционировать себя как разработчика сайтов и не знать про стандартный модуль PHP - это интересно :-)
    Ответ написан
    Комментировать
  • Не могу понять, почему скрипт очищает весь крон, место удаления конкретной строки, как сделать правильно?

    valerium
    @valerium
    Изобретая велосипед
    Вообще да, сделано дико криво. Сначала скрипт забирает файл с сервера, потом обрабатывает его на своей стороне, потом весь же файл передаёт обратно. Не проще ли «точечно» обработать файл на стороне сервера? Есть же волшебная утилита sed!

    $connect = ssh2_connect('localhost', '22');
    ssh2_auth_password($connect, ssh_login, ssh_password);
    $stream = ssh2_exec($connect,"sed -i.back 's/* * * * * /home/jitter.sh; /usr/bin/flock -xn /tmp/$path_script.lock -c \'/usr/bin/php -q /var/www/deone/data/www/vk-manager.ru/script/grabber/$path_script >/dev/null 2>&1\'//' /var/spool/cron/crontabs/deone");
    ssh2_exec($connect, '/etc/init.d/cron restart');


    То есть потоковый редактор sed (волшебная вещь! очень советую изучить) удаляет одну строку в файле, при этом (на всякий случай) создаёт резервную копию исходного файла с суффиксом .back.

    Кстати, судя по всему, подключение идёт к рутовой записи по паролю, это совершенно несекурно. Представляете, кто-то украдёт Ваш скрипт? Заморочтесь и настройте sudo и авторизацию по ключу.

    И да, надеюсь, localhost — это просто замена для конфиденциальности?
    Ответ написан
    Комментировать
  • Как узнать, из чего состоит время ожидания ответа от сервера?

    valerium
    @valerium Автор вопроса
    Изобретая велосипед
    Сам спросил, сам ответил… Лажанул я :-)

    Суть в том, что я не там ставил microtime(). Для архивации я использовал ZipArchive, и измерял время, которое требуется для ZipArchive::addFile(), но не учёл ZipArchive::close(). А ведь именно в момент закрытия происходит запись в файл.
    Ответ написан
    Комментировать
  • Как сделать генерацию случайных символов?

    valerium
    @valerium
    Изобретая велосипед
    Если эти 17 случайных символов не участвуют в криптографии, то почему бы не взять хэш от текущих даты-времени, и откусить от него 17 символов?

    function getSymbols() {
        return strtolower(substr(hash('gost', date('r')), 0, 17));
    }

    Если получать эти символы нужно чаще, чем раз в секунду, то придётся использовать класс DateTime, т. к. функция date() не работает с миллисекундами.
    Ответ написан
    3 комментария
  • Как узнать, что поступил JSON запрос на PHP?

    valerium
    @valerium
    Изобретая велосипед
    @dpr дал неплохой совет, но если так уж хочется скрыть кухню от пользователя, то почему бы не воспользоваться встроенными в протокол HTTP возможностями?

    На стороне клиента
    xmlhttp.setRequestHeader('Accept', 'application/json');


    На стороне сервера
    if ($_SERVER['HTTP_ACCEPT'] == 'application/json') {
        // тут генерируем JSON
    } else {
        // тут генерируем HTML
    }


    Использование HTTP-заголовка Accept предпочтительнее, чем HTTP_X_REQUESTED_WITH, потому что
    1. вы точно знаете, что передали заголовок ручками, а не полагаетесь на разработчиков браузера,
    2. используете более старую и устоявшюся (но не устаревшую) возможность, встроенную в протокол,
    3. оставляете себе задел на использование других представлений, например, XML, CVS, Plain text и т. д.
    Ответ написан
    2 комментария