*/ private Builder $builder; private string $folderPath; protected const string CARBON_FORMAT = 'Y-m-d\TH:i:sP'; /** * @param Builder $builder */ public function __construct(string $disk, string $folderPath, string $filename, Builder $builder, int $chunk) { $this->disk = $disk; $this->filename = $filename; $this->chunk = $chunk; $this->builder = $builder; $this->folderPath = $folderPath; } /** * @param T $model * @return array */ abstract public function mapRow(Model $model): array; /** * @throws \League\Csv\CannotInsertRecord * @throws \League\Csv\Exception * @throws \League\Csv\UnavailableStream */ public function export(): void { $tempDirectory = TemporaryDirectory::make(); $writer = Writer::createFromPath($tempDirectory->path($this->filename), 'w+'); $writer->setDelimiter(','); $writer->setEnclosure('"'); $writer->setEscape(''); $writer->insertOne(static::HEADER); $this->builder->chunk($this->chunk, function (Collection $models) use ($writer): void { foreach ($models as $model) { $data = $this->mapRow($model); $row = $this->convertRow($data); $this->validateRow($row); $writer->insertOne(array_values($row)); } }); Storage::disk($this->disk)->putFileAs($this->folderPath, new File($tempDirectory->path($this->filename)), $this->filename); $tempDirectory->delete(); } /** * @param array $data * @return array */ private function convertRow(array $data): array { $convertedRow = []; foreach ($data as $key => $value) { if ($value instanceof Carbon) { $convertedRow[$key] = $value->format(static::CARBON_FORMAT); } elseif (is_float($value)) { $convertedRow[$key] = (string) $value; } elseif ($value === null) { $convertedRow[$key] = ''; } else { $convertedRow[$key] = $value; } } return $convertedRow; } /** * @param array $row */ private function validateRow(array $row): void { if (array_keys($row) !== static::HEADER) { throw new \LogicException('Invalid row'); } } }