Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Ну надо же, такого я не ожидал - и правда стоило только <?php сделать и заработало. А с каких это пор современные версии php стали забивать на короткие тэги? вроде бы когда то наоборот было, новые версии стали короткие поддерживать (я правда не так хорошо знаком с историей пхп), а счас получается обратная мода пошла?
Всегда так было:
; This directive determines whether or not PHP will recognize code between
; <? and ?> tags as PHP source which should be processed as such. It is
; generally recommended that <?php and ?> should be used and that this feature
; should be disabled, as enabling it may result in issues when generating XML
; documents, however this remains supported for backward compatibility reasons.
; Note that this directive does not control the <?= shorthand tag, which can be
; used regardless of this directive.
; Default Value: On
; Development Value: Off
; Production Value: Off
short_open_tag = Off
short_open_tag иногда включают локально, но всегда рекомендовалось использовать полную версию. Ну, и на <?= ?> это не влияет, она всегда работает.
Насколько это безопасно, хранить токен в куках?
Не опаснее, чем хранить идентификатор сессии, что уже делает Laravel. Фактически, токен и есть этот идентификатор - просто случайная строка. Другое дело, что...
каждый раз отправлять запрос на API auth.site.ru(по токену получаем информацию о пользователе) с токеном из кук
...Каждый раз этого делать не нужно, только однажды. Человек зашел на auth, его перебросило назад на pr с токеном в запросе, дальше pr один раз запрашивает auth и делает вид, как будто человек "честно" вошел через форму (т.е. создает сессию и сохраняет туда все, что требуется). Можно и вовсе избежать запроса на auth, если передать всю информацию к pr сразу (можно в зашифрованном виде, если есть закрытые для пользователя данные): https://pr/sso?user=123&name=foo&...
Если же нужно разлогинить пользователя, то это делается уже на стороне сервера без участия браузера - auth сам удаляет сессию из базы pr (и других связанных сайтов).
У меня nginx, но через него не получается.
Как раз логично делать через nginx, двумя блоками server, первый из которых работает для myexample99.com и редирект не делает, а второй работает для всех остальных, с редиректом.
Без адреса сайта тут сказать ничего нельзя. Могу посоветовать скачать curl (если на Windows) и запросить страницу через него. Если страница будет нормальной, значит проблема у вас, если через curl страницы тоже нет, тогда дело в сайте.
Использовать вебсокеты для отслеживания
Вообще не обязательно для этого использовать WebSockets. Сегодня нынче их везде суют, не зная про старый-добрый EventSource - "односторонний" аналог, который не требует ни Node.js (на котором так любят писать сервера WS), ни особой настройки сервера, ни особого протокола, а его API просто и понятно:
var es = new EventSource('foo.php')
es.onmessage = function (e) {
alert(e.data)
}
На стороне сервера:
<?php
header("Content-Type: text/event-stream");
header("X-Accel-Buffering: no"); // если у вас nginx
while (true) {
echo "data: hello!\r\n\r\n";
ob_flush();
flush();
sleep(5);
}
И все.
А по сабжу, на клиенте достаточно всего-навсего в любом месте открыть поток и забыть про него:
new EventSource('online.php')
На сервере - как я написал выше, кидать в поток пустые сообщения каждые N секунд, чтобы избежать таймаута. И пока скрипт крутится - считать клиента в онлайне. Через register_shutdown_function() на отключение можно как-то отреагировать, сбросить там флаг в БД и пр. Даже если у клиента целый день открыта страница в фоне и он с ней ничего не делает - поток будет работать.
Особое достоинство в том, что EventSource сам переподключается, если соединение рвется (ушел в ждущий режим, в метро и т.п. WebSockets нервно курит в сторонке при реализации подобных задач.
У EventSource еще много интересного - советую почитать MDN: https://developer.mozilla.org/en-US/doc … ventSource
ReflectionParameter::getClass() is deprecated
https://www.php.net/manual/ru/reflectio … tclass.php
Эта функция была УДАЛЕНА в PHP 8.0.0. Использование этой функции не рекомендуется.
Если менять Laravel не хочется, то поставь более старую версию XAMPP (с веткой PHP 7.x).
Сложно сказать по описанию без кода, но, вероятно, подойдет способ с учетом уже обработанных индексов. То есть если массивы без ключей (цифровые ключи по порядку), то для каждого можно запоминать последний индекс, который был обработан (начинается с 0, после прохода по циклу = count($array) и т.д.), а в каждой итерации сверять итерируемый индекс с запомненным и пропускать уже обработанные.
Что мешает запускать тот же Apache из XAMPP из-под обычного пользователя? Совершенно не обязательно и даже не желательно запускать его из-под сервисов (админа) - если кто-то влезет в систему, как это было со старыми версиями XAMPP с дырой, то у него будет удаленный админский доступ к ПК.
а вообще винда для всего этого очень не удобна
Да все нормально на Windows с веб-разработкой. И 20 лет назад нормально было, и 10, и сейчас. Тем более с WSL.
Проще использовать два массива - старый и новый, и писать только в новый. Или данных много?
Я всегда файлы измеряю в степенях двойки, поэтому 5 Мегабайт (как бы это не записывалось) это 5*1024*1024 = 5242880 байт или 5120 Килобайт.
"Кило" это просто приставка, обозначающая как раз 1000 ("кило"метр, "кило"грамм). Но в ИТ в комбинации с "байтом" она традиционно обозначает 1024, т.е. степень двойки. Формально это пытались исправить, введя "киби" вместо "кило", "гиби" вместо "гига" и т.д. (см. Википедию) - но, насколько можно судить, это совершенно не прижилось и народ продолжает использовать "кило" как 1024. Получше ситуация с сокращениями (как "кг" для "килограммов" - "кб" / "Кб" / "КБ"): заглавная "К" (и "М", "Г" и т.д.) используется для "кило как 2^10", а строчная "к" - для "кило как 10^3". Таким образом, 1 кБ = 1000 байт, 1 КБ = 1024 байта. Кроме того, есть сокращение Ки (Ki) - 1 КиБ (1 KiB) = 1024 байта, это как раз исходит из единицы "киби" (kibi - кибибайт). С формальной точки зрения калькулятор Google прав, он все это знает и в этом можно убедиться, введя "киб" или "kib" вместо "кб"/"kb".
Тем не менее, надо констатировать, что в современном мире единицы измерения в байтах используются как ни попадя и обычно все-таки под "кило" понимается 1024, вне зависимости от. "кб", "КБ", "Кб", "кБ" - все это 1024 байта. Особо занятно, что иногда "б" вовсе убирают и тогда без контекста не понятно, имеется в виду байт или что-то другое (например, число строк в таблице): "5к", "10М".
на данный момент остановился на поднятии опускании по одному элементу.
Да, решение так себе. Впрочем, средствами БД это одной строкой и не реализовать. На ум приходит два варианта.
Первый - два запроса:
UPDATE SET position = position + 1 WHERE position >= новая позиция;
UPDATE SET position = новая позиция WHERE id = передвигаемая запись;
Если выполнять внутри одной транзакции, то не вижу ограничений у этого способа, разве что в гипотетическом будущем счетчик position может переполниться.
Второй - экзотический. UPDATE с разными значениями на нескольких записях делать нельзя, но можно сделать ход конем: использовать стандартные функции SQL, чтобы по id записи получить ее положение.
Для начала выбираешь все записи вообще: SELECT * FROM
Затем сортируешь их как угодно на стороне PHP.
А затем меняешь position для всех одним запросом:
UPDATE SET position = INSTR(" <?=join(" ", array_column($sorted, "id"))?> ", " " || id || " ");
Таким образом, генерируешь строку из id в порядке, в котором их записи должны идти, а UPDATE ставить position так, что чем ближе id к началу строки - тем его position будет меньше. Соответственно, первый элемент будет с position = 2, а последний - с самой большой position.
Этот метод, однако, не безопасный с точки зрения одновременного доступа, да и медленный.
inner join (
select count(*) as cnt,
Зачем так сложно? Подзапрос не нужен, JOIN'ить таблицу можно саму на себя.
select count(*) as cnt,
u.firstname,
u.lastname
from users
join users u on users.firstname = u.firstname and users.lastname = u.lastname
group by u.firstname, u.username
having cnt > 1
Вместо этого я просто могу написать require('такой-то файл').
Если у тебя использование класса делается в одном месте - autoload это лишняя писанина. Если в двух - уже нет. А если в десятке или сотне мест - то профит налицо.
Если бы я мог запускать эту функцию из любого файла...
spl_autoload_register() можно запускать из любого файла.
Как вы думаете, стоит ли заморочиться использовать JS как Front-End ради "плавной" работы страниц, если проект планируется порядка 20-30 страниц?
Чем меньше JavaScript, тем лучше. В большинстве проектов или, по крайней мере, на большинстве страниц большинства проектов скрипты не нужны. Экономьте свои силы (используйте возможности, уже предоставляемые браузеров) и электроэнергию своих клиентов.
Нужно именно "воткнуть" в нужное место списка (и остальные сдвинуть вниз или вверх), а не поменять местами.
В таблице БД нет никакого порядка записей. Обычно кажется, что SELECT без ORDER возвращает строки в том же порядке, в каком они были вставлены (INSERT), но это только кажется и, например, после DELETE строк в начале таблицы и последующей вставкой новых эти самые новые будут идти первыми, а не последними. Более того, после оптимизации таблицы порядок опять может поменяться.
В связи с этим не понятна трудность. Ты же сам и указываешь решение:
хорошо даже если я добавлю новый столбец которому будет название topnum и будет хранить текущую позицию и сортировать я буду по нему, вопроса это все равно не отменяет.
Так и делай: добавляй новое поле, например, position, а в SELECT добавляй ... ORDER BY position DESC.
В логах запросы к любым ресурсам.
Проблема только в том, что логи 1) обычно отключают, т.к. они тормозят систему, 2) [должны быть] не доступны для чтения скриптам.
Подскажите пжл, кто с опытом, как лучше написать счетчик просмотров изображения?
Если изображение маленькое, то ссылаешься на скрипт (маршрут), который увеличивает счетчик где-то в БД или на диске, после чего делает readfile('pic.jpg');. Если файл большой, то без помощи веб-сервера не обойтись - скрипт увеличивает счетчик, а потом делает нечто вроде header('X-Accel-Redirect: pic.jpg'); (это для nginx). Это позволит клиенту использовать мультипоточную загрузку/догрузку, Expires и прочее. Для мелких файлов это не так важно, поэтому там можно и через readfile() отдавать.
Имена товаров сложные - `APK2R AP-1D APE2 Apecs`, например.
Можно сделать второе поле в таблице, дублирующее то, по которому хочется делать поиск, но в это поле заносить нормализованные (трансформированные) данные. Например: APK2R_AP_1D_APE2_APEC. То есть удалять спецсимволы, преобразовывать пробелы. Аналогично поступать с поисковым запросом. Кроме прочего, в это поле можно включить дополнительные тексты, например, заголовок и описание.
@Proger_XP ты по прежнему считаешь, что обрабатывать дохуялионы записей в массиве на стороне PHP это нормально?
Он ситуации зависит. Если их в БД изначально нет, то странно их вначале туда вставить, потом обработать, а потом извлечь (если памяти веб-сервера хватит, конечно). В PHP вполне быстрые стандартные функции, это все-таки Си; конечно, лучше не делать то же самое самим PHP, как человек тут выше делает в цикле.
При этом всегда остаётся немаленькая вероятность что в результате ошибки записи в базе будут таки НЕуникальны.
Для гарантий нужно использовать индексы (UNIQUE), вне зависимости от того, как ты обрабатываешь записи - через SQL или PHP, ибо два клиента могут одновременно выполнить один и тот же SQL и получить дубли.
Если решать задачу средствами SQL, то уникальность будет гарантирована, а тяжелые запросы будет выполнять оптимизированный на это сервер БД.
С этим я спорить не буду, так как все-таки очень зависит от ситуации. Вот еще два аргумента:
1. Чем "круче" SQL, тем меньше он переносим, а PHP - один на всех. При гипотетическом переносе проекта с MySQL на PgSQL (например) работы сильно прибавится. Да и отлаживать кучерявые SQL - так себе удовольствие.
2. PHP выполняется на стороне бекенда, а SQL - на стороне БД. В проекте вполне можно представить несколько независимых бекендов, но вот несколько независимых БД - с трудом (ибо это уже будут разные проекты). Так что решая задачу на стороне PHP ты нагружаешь (а то и блокируешь) только один бекенд, а не БД и все бекенды соответственно.
пользователь может загрузить фотографию через API, указав URL-адрес фотографии
Если я правильно понял , то необходимо использовать какую-нибудь стороннюю программу , т.е интегрировать ее в проэкт Laravel .
file_get_contents('https://laravel.ru/logo.png');
copy('https://laravel.ru/logo.png', 'c:/сохранить_сюда.png');
проблема в том что если окно не активно то звук не воспроизводится, как сделать что бы в фоновом режиме воспроизводился звук (например как у яндекса или у деливери) так как если вкладка не открыта то и звука нет
Я думаю, что здесь все зависит от браузера. Последнее время стало модно все запрещать и резать - аудио только по клику, замедление таймеров в фоновых страницах и т.п. Скорее всего, у вас звук даже не начинает воспроизведение, а не "если вкладка не открыта то и звука нет" - такого, по-моему, еще никто не делал, т.к. онлайн-плееры сразу пойдут лесом.
array_column($array, null, "NUMBER");
Или увеличить memory_limit в php.ini.
P.S. Вообще когда с базой работаешь, надо отказываться от стереотипов работы с массивами. Очень неоптимально тащить всё в PHP. Вместо этого надо поручать тяжёлую работу серверу БД — он отлично справляется.
С этим можно похоливарить. По моему опыту как раз описанная задача (импорт прайс-листа на сайт) проще всего решается "в лоб" - загрузкой всех данных в память в начале и выгрузкой их в БД в конце - благо прайс загружается редко и даже когда это происходит - загружает только 1 клиент (без параллельной загрузки). Поэтому заморачиваться с курсорами, частичным обновлением, а то и хранимыми процедурами бессмысленно - программировать это на порядок сложнее, чем выделить пусть даже 150 Мб под один редкий запрос и манипулировать всем массивом данных в скрипте. Такой сценарий потянет даже дешевый VPS с 256 Мб RAM.
интересная статья, но я все равно не понимаю как эта уязвимость могла сработать. При обращении к странице \.svn я ведь получу то же сообщение что страница не найдена. Роутер ведь отсечет этот запрос.
artoodetoo прав:
роутер срабатывает только для тех файлов, для которых веб-сервер не нашёл соответствующего "статического" файла
Но соль проблемы глубже. Раньше в Subversion (это, можно считать, предшественник git) папки .svn создавались не в корне репозитория, как у .git, а в каждой подпапке. Каждая такая папка содержала интересные вещи типа истории и исходников. Соответственно, если у тебя сайт деплоится из Subversion, то в твоей папке public_html (или аналога) всегда лежала "скрытая" папка .svn. Это описанная в статье уязвимость.
С git и Laravel проблема как будто не актуальна, так как git не мусорит своими папками везде, а Laravel поделен на корень и на public_html, причем public_html это подпапка в корне и потому .git в ней нет. Однако даже в Laravel есть любители перепиливать пути так, чтобы корень сайта указывал на корень фреймворка, то бишь помещают public_html в корень. А теперь добавь к этому модную нынче тенденцию все деплоить из git (я не говорю, что это плохо), и привет - в корне лежит .git, где, в отличии от Subversion, которая хранила только верхний коммит, хранится ВСЯ история и ВСЕ исходники во ВСЕХ папках данного репозитория. (Если не используется shallow repository.)
Так что будь начеку. Я лично советую всегда помещать это правило в конфиг всех хостов nginx:
location ~ /\. {
deny all;
}
Правда, это отключит и запросы ACME, так что если используется Let's Encrypt, то надо добавить и второе, пустое:
location ^~ /.well-known/ {
}