Skip to content

Instantly share code, notes, and snippets.

@asvae
Last active February 13, 2017 12:13
Show Gist options
  • Save asvae/af47815fca84c38a80436eae939d4de9 to your computer and use it in GitHub Desktop.
Save asvae/af47815fca84c38a80436eae939d4de9 to your computer and use it in GitHub Desktop.
Laravel BYR to BYN currency converter command
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class ConvertBYRToBYN extends Command
{
protected $signature = 'convert-byr-to-byn';
protected $description = 'Convert BYR to BYN in database.';
private $count = 0;
public function handle()
{
$query = \DB::table('ads')->where('currency', 'BYR');
$this->line("We have {$query->count()} ads with BYR.");
$query->chunk(1000, function ($ads) {
foreach ($ads as $ad) {
$this->updateOne($ad);
$this->count++;
}
$this->line($this->count);
});
$this->comment("Done updating BYR to BYN. Total: $this->count ads.");
}
/**
* Обновляем валюту для конкретного объявления.
*/
private function updateOne($ad){
$price = $ad->ad_price < 10000 ? $ad->ad_price : $ad->ad_price/10000;
\DB::table('ads')->where([
'id' => $ad->id
])->update([
'ad_price' => $price,
'currency' => 'BYN',
]);
}
}
/*
Результаты выполнения комманды:
1) Почему-то обработана только половина выдачи.
We have 18356 ads with BYR.
1000
2000
3000
4000
5000
6000
7000
8000
9000
9356
Done updating BYR to BYN. Total: 9356 ads.
2) Снова только половина
We have 9000 ads with BYR.
1000
2000
3000
4000
5000
Done updating BYR to BYN. Total: 5000 ads.
3) Для этого испытания я закомментировал строчку `$this->updateOne($ad);`. В итоге count базы и цикла совпали.
We have 4000 ads with BYR.
1000
2000
3000
4000
Done updating BYR to BYN. Total: 4000 ads.
4) Откомментировал назад — снова половина выдачи.
We have 4000 ads with BYR.
1000
2000
Done updating BYR to BYN. Total: 2000 ads.
*/
@asvae
Copy link
Author

asvae commented Feb 13, 2017

Там получается выборка модифицирующая. Т.е. выводятся только результаты, у которых 'currency' = 'BYR'. И в результате выборки эти самые валюты заменяются. И у лары индексация chunk-а как то от такой фигни багает.
Суть в чем.
Лара юзает chunk. Просекает, что chunk-ов, например, 4.
Берет 1000 записей.
Конвертит.
Берет следующие 1000 записей.
Вот здесь прикол в том, что это записи 2000-3000 из изначальной выборки.
Потом она пытается взять 3й чанк. А его нет. Потому что выборка на 2000 сместилась.
Дат мина.
Адекватное решение будет while луп с лимитом на кверю. Я думаю.

@asvae
Copy link
Author

asvae commented Feb 13, 2017

Решение:

do {
    $ads = $query->limit(1000)->get();
    foreach ($ads as $ad) {
        $this->updateOne($ad);
        $this->count++;
    }
    $this->line($this->count);
} while(! empty($ads));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment