Я хочу создавать папки на основе user_id внутри /laravel/public/file/FolderUserXXX.
Если у меня есть 1000 записей пользователей в базе данных, я хочу создать 1000 папок внутри пути (мне нужно создать эти папки, потому что мой сервер отключается, а папки исчезают).
Я создал задание для его выполнения, и я пробовал его локально с небольшими данными (работает), но в процессе производства я всегда получаю ошибку Allowed memory size of xxxxxxxxxxxxx bytes exhausted (пытался выделить xxxxxxxx байтов). Я добавляю memory_limit до 4 ГБ в php.ini, но проблема все еще возникает.
Вот мой код в app/Console/Commands
сценарий:
Задание createfolder для пользователя с status >= 3 и remark_restore - это null. При каждом успешном создании remark_restore будет изменяться на 1. Я пытался ограничить 1 данными на задание и запускать каждую минуту, но все равно получаю ошибку.
Но если я изменю memory_limit на -1 только для запуска этого задания, а затем верну его обратно к предыдущему значению, будет ли какое-либо влияние в будущем для моей сети?
Есть предложения о том, как предотвратить ошибку memory_limit?
public function handle()
{
try {
ini_set('max_execution_time', 300000);
ini_set('memory_limit','4096M');
$take = 1;
$make_folder = User::where('status', '>=', '3')->wherenull('remark_restore')->limit($take)->get();
foreach ($make_folder as $make_folder) {
$path = public_path().'/file/'.$make_folder->id;
if (!(file_exists($path))) {
$data = User::where('id', $make_folder->id)->update(array('remark_restore' => '1' ));
File::makeDirectory($path, $mode = 0777, true, true);
}
}
$count = User::where('status', '>=', '3')->wherenull('remark_restore')->count();
echo 'Pending : '.$count;
}
catch (\Exception $e) {
\Log::warning($e);
}
}
и попробуйте добавить ограничение на запрос, например limit (10) на запрос.






Ладно, вы путаете ...
Правильный подход здесь - отправлять задание для каждой папки вместо того, чтобы выполнять одно задание для каждого создания.
Итак, у вас должна быть работа типа CreateFolderForUser и в ней что-то вроде:
class CreateFolderForUser
{
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function handle()
{
try {
$path = public_path("/file/{$this->user->id}");
if (!(file_exists($path))) {
File::makeDirectory($path, 0777, true, true);
$this->user->remark_restore = 1;
$this->user->save();
}
}
catch (\Exception $e) {
\Log::warning($e);
}
}
}
Видите, я удалил все, что касается итерации пользователей, вам просто нужно выполнить эту работу, а именно «Создать папку для этого пользователя», ничего больше ...
Также обратите внимание, что я переместил обновление remark_restoreпосле, создав каталог, потому что в вашем предыдущем коде, если создание не удалось, вы уже обновили remark_restore пользователя до 1, но это неверно, у вас была ошибка ...
Теперь у вас должен быть Планировщик, который запускает код или выполняет его в команде, поэтому планировщик вызывает эту команду каждые 5 минут или как вам угодно. Этот код увидит базу данных и отправит это задание каждому пользователю, которому вы хотите создать папку.
public function dispatchUserFolderCreation()
{
$take = 1000;
$users = User::where('status', '>=', '3')
->whereNull('remark_restore')
->limit($take)
->chunk(100, function (Collection $users) {
foreach ($users as $user) {
dispatch(new CreateFolderForUser($user));
}
});
}
Вы можете динамически передавать желаемый $take, если используете команду, поэтому по умолчанию используется 1000, но если вы хотите меньше или больше (не отправляйте 10000, делайте это партиями 2000, не больше), вы можете это сделать.
Попробуйте задержать создание папки внутри вашей функции foreach (). Пример добавления сна (5)