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

    @rPman
    Я помню реализовывал очень простой механизм разграничения доступа к статическим файлам без привязки к особенностям веб серверов (там есть плагины на авторизацию) и при этом чтобы файлы для веб сервера оставались статикой.

    Файлы размещаются в каталоге, недоступном веб серверу а в конфиге веб сервера включается поддержка симлинков (например apache - Options FollowSymLinks). Затем, модуль авторизации создает на каталог с файлами, к которым нужен доступ для пользователя символическую ссылку в публично доступном каталоге, с именем, равным идентификатору сессии пользователя session_id() а по завершению сеанса, симлинк удаляется (если сеанс должен завершаться автоматически, придется использовать какой то работающий демон или периодический по крону для проверки всех сессий на завершение). Таким образом ссылка на скачивание будет формироваться из сессии пользователя и будет оставаться статичной (т.е. веб сервер будет отдавать этот файл сам, максимально эффективно), но доступ к ней будет только у авторизованного.

    Код для этого дела - несколько строчек.

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

    @rPman
    Не понятно причем тут php, но у apache есть режим отображения содержимого каталога как html, в виде списка файлов в табличном виде (имя, размер, дата модификации...), и имя файла будет ссылкой на этот файл, если кликнуть на файлы изображений или любых других файлов, типы которых зарегистрированы в браузере - они будут отображены внутри, иначе будет диалог загрузки файла.
    <Directory /var/www/html>
            Options +Indexes
            AllowOverride None
            Require all granted
        </Directory>

    тут +Indexes делает именно это - генерацию html

    p.s. если же нужно на php генерировать список файлов по своей логике то добавляешь поддержку php в apache (модуль mod_php или php-fpm) и index.php:
    foreach (scandir('.') as $file)
    {
        if ($file == '.' || $file == '..') continue;
        echo '<a href="' . htmlspecialchars($file) . '">' . htmlspecialchars($file) . '</a> - ' . filesize($file) . '<br>';
    }
    Ответ написан
  • Как можно использовать результат запроса из другого файла?

    @rPman
    Предпологаю что речь идет о веб бакэнде - приложении, запускаемом на веб сервере по запросу из браузера. И главное, предполагаю что используется cgi подход, когда на каждый запрос из браузера запускается отдельный процесс php (даже если это модуль веб сервера, он конечно оптимизируется до асинхронных потоков) но содержимое памяти каждый раз пустое.

    Если у тебя mainpage.php и poisk.php это разные запросы, то через глобальные переменные данные между ними не передать.

    Нужна какая-нибудь база данных, чем бы она не являлась, например:
    * хранить в специальных заголовках запроса - cookies, эти данные как мяч будут автоматически передаваться между клиентом и сервером, т.е. все запросы от клиента будут содержать копию всех установленных cookies, до истечения их времени жизни
    * переменные сессии (используются cookies автоматически)
    сессия доступна сразу после session_start() а данные через ассоциативный массив $_SESSION (автоматически сохраняется по окончанию скрипта, учти это при параллельных запросах), идентификатор сессии автоматически поддерживается в заголовках запроса (сессия стартует когда пользователь открывает сайт, и единая для других окон, адже после перезапуска браузера, время жизни опция cookie_lifetime)
    Очень часто идентификаторы сессии или специально созданное значение в ней используется как идентификатор для поиска данных в других местах (например БД)
    * можно использовать файлы, в которых данные хранятся в сериализованном виде, в php штатно работает var_export/eval, serialize/unserialize, json_encode/json_decode - текстовые и бинарный igbinary_serialize/igbinary_unserialize (очень эффективный формат) или свой собственный, по желанию
    * можно использовать базу данных, начиная с sqlite (размещается в файле но работа с помощью sql), настоятельно рекомендую PDO - универсальная прослойка для работы с реляционными БД
    * есть еще всякие memcache, apcu, или к примеру самописный сервер данных (на сокетах и не только) но применимость - отдельный разговор

    p.s. есть иной подход, когда на php пишется полноценный веб сервер, принимающий http запросы (его напрямую редко пускают в интернет, обычно ставят еще какой-нибудь nginx для поддержки ssl и других тонкостей), в этом случае php приложение скорее всего - один инстанс (один процесс), который не завершается по завершению запроса, обрабатывает запросы клиентов асинхронно, в этом случае глобальные переменные будут доступны между запросами.
    Ответ написан
    3 комментария
  • Какую архитектуру парсинга маркетплейса выбрать?

    @rPman
    100к событий в секунду с торговой платформы это сюр, такое практически нереально, (ну может в самый первый раз когда база пустая).

    С высокой вероятностью там так - вы собираете в секунду 100к информационных единицы (отзывы, товары, ..) но в базе из них обновить и добавить считанные процент из этого, и вот в этот момент есть способы как оптимизировать, например перенести обработку из медленной базы данных (медленные они, потому что универсальные и транзакционные) в оперативную память.

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

    Отсюда архитектура - отдельно дубовые парсеры-загрузчики (их можно размещать буквально где угодно, они получают команду на загрузку и молотят, выдавая json-чики пакетами в виде результата), отдельно узлы-обработчики, которые на каждый пакет данных от загрузчиков делает нужные запросы в базу данных (или заранее кеширует в памяти, но тут нужно считать, что дешевле - апгрейдить сервер базы данных или держать на дисках кеш-дампы запросов и обновлять их параллельно БД, в этом случае кстати БД остается как конечное хранилище и аналитики). Ну и про базу данных, они на запись медленные только если там индексы распиханы по максимуму, хороший способ, если загрузка в базу редкая (например раз в сутки длится час) то можно отключить на это время индексы, провести загрузку, вернуть индексы - это кратно ускоряет процесс ЗАГРУЗКИ но не проверки целостности и поиск данных, т.е. подходит именно когда анализ проводится не в БД.

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

    p.s. у меня крутился сервис, годами собирающий терабайты данных на скорости 4к-10к событий в секунду (time series), хранить это в классической базе я не стал, а организовал хранилище на файлах, поверх которых в базе данных собирается аггрегированная выжимка и индексы.

    Это было оправдано, так как разработка аналитического сервиса шла уже в процессе загрузки и это была суть работы, т.е. нельзя заранее определить, что из этих данных и как может понадобиться, база данных строилась каждый раз под задачу, проходом по всем данным (больше времени занимала их распаковка - json с упаковкой zstd)
    Ответ написан
    Комментировать
  • Где PHP хранит кэш на "отдачу"?

    @rPman
    Отдает nextcloud, значит настройки его смотреть.

    Попробуй в /var/www/nextcloud/config/config.php (путь может немного другим быть, например home, смотри настройки веб сервера) и там настройка
    'tempdirectory' => '/tmp/nextcloudtemp',
    Ответ написан
  • Как в PHP использовать в родителе константу или статическую переменную из потомка?

    @rPman
    Имя_класса::имя_пременной
    Так же ключевое слово parent - имя предка, self - текущего класса
    например parent::CONST_NAME
    p.s. опс, не то.


    Чтобы уж ответить на вопрос, в php нет метода получения списка потомков класса, но есть функция get_declared_classes() - возвращает массив имен всех классов, и функция is_subclass_of("объект или имя класса","имя проверяемого класса") вернет true если первый класс является потомком второго. Так всех перебрав можно будет получить список потомков, ну а затем нужному по имени из переменной - $var_class_name::static_member и даже по имени мембера в переменной $var_class_name::$$static_member_name
    Ответ написан
  • Как сделать globbing строки в php?

    @rPman
    Ответ - регулярные выражения, синтаксис чуть сложнее чем * и ? но возможности выше
    preg_replace для однобайтовых кодировок или mb_ereg_replace для любых.

    регулярное выражение для твоей задачи будет выглядеть примерно так /word.*/ если после слова может присутствовать любое количество любых символов, включая нулевое (иначе использовать .+). Тут точка - это любой символ, а следующий за ним * или + - любое их количество

    upd. совсем забыл, preg_replace с модификатором /u понимает utf8 строки
    Ответ написан
    4 комментария
  • Какая конструкция у кода должна быть без goto?

    @rPman
    Если объединить все твои последовательные if в непрерывную конструкцию
    if () {} elseif () {} elseif.... else {}
    то goto или return Rsa97 не понадобятся
    Ответ написан
    Комментировать
  • Как получать динамические значения из таблицы Excel через php?

    @rPman
    excel таблица залитая на google docs

    минимум 100 запросов в секунду

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

    Если убрать из списка google, то можно самостоятельно хостить headless excel (майкрософтовский офис, приложение на чем угодно, работа с activex из того же .asp) либо libreoffice, вот пример на питоне но идею я надеюсь ты понял...

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

    @rPman
    Мда, математику бы вам подучить.

    Сумма чисел, отсутствующих в арифметической прогрессии (школа 9 класс кажется) можно посчитать по формуле - сумма чисел в полной последовательсности минус сумма чисел в имеющемся массиве.

    $foo = [1, 2, 3, 6];
    
    $n=end($foo);
    $asum=((1+$n)*$n)/2;
    echo $asum-array_sum($foo);
    Ответ написан
    4 комментария
  • Как изменить переменную, которая находится вне класса?

    @rPman
    На будущее, когда вариант Rsa97 не прокатит, нужно передавать объекты по ссылке
    class MyClass {
        private $array;
    
        public function __construct(&$array) {
            $this->array = &$array;
    	$this->array['123']='456';
        }
    }
    
    $array = [];
    $grid = new MyClass($array);
    print_r($array);
    Ответ написан
  • Как записать в базу пустое поле?

    @rPman
    Не надо так делать, откуда вы берете такие инструкции?
    VALUES ('.$user_id.','.$a
    пользоваться нужно prepared statements (они есть для всех драйверов, вот например mysqli), это не только исключит разные проблемы с типами (например строки придется экранировать) но и даст бонусом защиту от sql-иньекций

    Причина, почему у тебя не работает - конкатенация NULL со строкой ничего не делает (добавляет пустую строку), а нужно писать NULL либо исключить поле из sql запроса а при создании таблицы у поля написать default null
    Ответ написан
    Комментировать
  • Почему у меня неправильно определяется IP пользователя?

    @rPman
    $_SERVER['REMOTE_ADDR'] устанавливает твой веб сервер, ему вы доверяете.
    Но, если пользователь заходит через прокси сервер - то тут будет выходной ip адрес этого прокси.

    Если прокси сервер не скрывает информацию о своих клиентах то
    $_SERVER['HTTP_X_FORWARDED_FOR'] и $_SERVER['HTTP_CLIENT_IP'] должны содержать ожидаемое, но это значит нужно доверять этому прокси серверу.

    Хочешь узнать реальный ip адрес, используй javascript в браузере пользователя (т.е. придется доверять уже пользователю в плане, а отреверсит ли он твой код и не подсунет что угодно).

    Cамый известный и достаточно надежный способ (его сразу отключают любые адекватные анонимизеры) - это WebRTC. Технология позволяет двум браузерам открывать прямое соединение (да еще и udp) друг с другом, а веб сервер только организует процесс. Т.е. подняв соответствующего клиента WebRTC (погугли, правда я для php с ходу готовой библиотеки не нашел) и организовав подключение клиента с этим твоим сервером, который представляется обычным веб клиентом), ты сможешь по тому, с какого ip адреса пришло соответствующее соединение, определить настоящий, даже если пользователь использует прокси.

    Это не защитит от vpn, тут никакими способами определить ip адрес пользователя не получится, потому что с точки зрения сетевых технологий, vpn - это как бы проводок пользовательского компьютера подключили к vpn-серверу, и никакие коммуникации не пойдут иначе, если пользователь не укажет иного (можно настроить маршрутизацию на выход через разные шлюзы в зависимости от геолокации, кстати этим можно воспользоваться, разместив кучу своих серверов в разных локациях и, обращаясь к ним из браузера клиента, сравнивать ip адреса)
    Ответ написан
    2 комментария
  • Возможна ли sql инъекция?

    @rPman
    почти наверняка будут глюки при использовании utf8 или любой другой мультибайтовой кодировки, и формировании строки с неправильной комбинацией символов, так как mysql_escape_string не будет их считать опасными (она вообще только для однобайтовых кодировок).

    Чтобы воспользоваться уязвимостью нужно серьезно зарыться в исходники php или mysql и понимать как обрабатываются ими мультибайтовые кодировки.

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

    @rPman
    Если у тебя 'устаревший' http rest подход с функционалом server side only (т.е. браузер не будет требовать javascript) то лучшим решением в твоем случае будет использование фреймов. Размести каждую или эту конкретную форму в своем фрейме - тег IFRAME

    В этом случае, если нужно будет из одного фрейма по ссылкам менять адрес всей страницы, то у тега A нужно будет установить атрибут target=_top

    p.s. альтернатива, сделать единую форму, и по нажатию разных кнопок отправлять содержимое всех полей, устанавливая их значение при следующем открытии страницы. Определить, какую кнопку нажал можно по ее имени (в $_POST будет установлено значение name для той кнопки, которая была нажата).
    Ответ написан
    Комментировать
  • Как ограничить доступ к странице сайта на устройстве пк браузеров?

    @rPman
    Открывамем гугл, пишем github browser mobile detector
    получаем ссылку на почти сотню проектов, отсортированных по популярности, первый какраз на php
    Ответ написан
    Комментировать
  • Почему не записываются данные в MySQL базу данных?

    @rPman
    заверши транзакцию в конце скрипта перед close - commit
    p.s. в 2024 году использовать mysqli это моветон.

    использовать видео, да еще и такое зашакаленное и на неадекватном хостинге (как так, по пробелу паузу не делает) чтобы передать исходники это прямое издевательство над теми у кого ты просишь помощи.
    Ответ написан
    9 комментариев
  • Как скачать файл на сервер по ссылке без расширения?

    @rPman
    При переходе по указанной ссылке видео в браузере не качается, а идет переход на страницу с youtube роликом, но по 'счастливой оплошности' разработчика этого сайта идентификатор youtube ролика размещен прямо в ссылке:
    presaver.com/youtube/qU5A0MLHtyE/download/22?title=treiler2023

    (видно что сайт - рекламная пустышка, контента в нем нет, все полезное содержимое размещено в ссылке, загрузки видео не происходит, скорее всего сломалось что то)

    Это значит, выделяешь из ссылки этот код (например с помощью регулярных выражений метод preg_match или с помощью комбинации parse_url выделив путь с помощью PHP_URL_PATH и explode, разбив путь по '/'), и запускаешь утилиту
    yt-dlp "https://www.youtube.com/watch?v=qU5A0MLHtyE" -f код_формата

    если запустить с ключом -F то будет выведен список доступных форматов и их кодов, при наличии ffmpeg в можно будет объединять аудио и видео потоки

    все это запускать из php с помощью `обратных ковычек` либо вот список вариантов

    p.s. yt-dlp рекомендую ставить с помощью pip, там обновляется оперативнее чем тот что ставится из репозитария ubuntu и других.
    Ответ написан
  • Как получить доступ к контенту iframe?

    @rPman
    На javascript с правами вебсайта ты этого не сможешь сделать, браузер не дает доступ к сторонним доменам в iframe, за исключением доменов-потомков (типа твой domain.ru а iframe - zzz.domain.ru, такой вариант доступ имеет), потому что там сайт открывается с куками пользователя, т.е. можно было бы открывать критичные сайты в iframe и собирать доступы к ним нахяляву.

    Доступ к iframe в браузере имеют плагины и скрипты, запущенные из консоли (плюс все что управляется из selenium).

    Так же возможен свой кастомный браузер на базе какого-нибудь webkit (там доступ к контенту прямой без ограничений), но что то мне говорит что ни плагины ни свой браузер тебе не подходит.

    p.s. универсально, а точнее если со стороны сайта, публикуемого в iframe, идет борьба с этим, у тебя нет возможности узнать что там отображается.

    Но если специально никто не следит, то можно поднять на своем сервере прокси, который будет заворачивать в твой домен указанный (например сайт domain.ru в iframe - yoyo.com, а ты создаешь yoyo-com.domain.ru как копию yoyo.com и открываешь уже этот сайт в iframe, доступ будет с твоими куки (а не куки пользователя).

    Особого смысла в таком действии нет, как и нет смысла проверять, что же там открылось в iframe.
    Ответ написан
  • Как правильно лоигровать ошибки php?

    @rPman
    Не получится, синтаксические ошибки не отловить, так как они появляются до запуска скрипта на выполнение.

    Но если перед запуском приложения выполнить php с ключом -l (--syntax-check) то приложение не будет запущено а только пройдет проверка на ошибки и при наличии она будет выведена, ее можно прочитать
    exec('php --syntax-check main.php',$error_str);

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