chiiya/laravel-utilities

Common utilities for laravel projects

Fund package maintenance!
chiiya

5.1.0 2023-03-21 14:08 UTC

README

Latest Version on Packagist GitHub Code Style Action Status Total Downloads

Common classes and utilities for Laravel projects.

Installation

You can install the package via composer:

composer require chiiya/laravel-utilities

You can optionally publish the config file with:

php artisan vendor:publish --tag="utilities-config"

This is the contents of the published config file:

return [
    /*
    |--------------------------------------------------------------------------
    | Temporary path
    |--------------------------------------------------------------------------
    | Used for downloads and unzipping files.
    */
    'tmp_path' => storage_path('tmp'),
];

Usage

TimedCommand - Print command execution time

Simple extension of the Laravel Command that prints execution time after completion.

use Chiiya\Common\Commands\TimedCommand;  
  
class SendEmails extends TimedCommand
{
    protected $signature = 'mail:send {user}';
    
    public function handle(DripEmailer $drip)
    {
        $drip->send(User::find($this->argument('user')));
    }  
$ php artisan mail:send 1
> Execution time: 0.1s  
SetsSender - Set sender for mailables

Trait to set the sender (return path) for mailables for e.g. bounce handling.

use Chiiya\Common\Mail\SetsSender;
  
class OrderShipped extends Mailables
{
    use SetsSender;

    public function build(): self
    {
        return $this
            ->subject('Order shipped')
            ->markdown('emails.orders.shipped')
            ->sender('return@example.com');
    }
}
PresentableTrait - View presenters for eloquent models

View presenter similar to the no longer maintained laracasts/presenter package. Useful for doing some manipulations before displaying data.

use Chiiya\Common\Presenter\Presenter;

/** @extends Presenter<User> */  
class UserPresenter extends Presenter
{
    public function name(): string
    {
        return $this->first_name.' '.$this->last_name;
    }
}
use Chiiya\Common\Presenter\PresentableTrait;
  
class User extends Model
{
    /** @use PresentableTrait<UserPresenter> */
    use PresentableTrait;
    
    protected string $presenter = UserPresenter::class;
}
<h1>Hello, {{ $user->present()->name }}</h1>
AbstractRepository - Base repository for the repository pattern

Base repository for usage of the repository pattern. It provides get, find, index, search, count, create, update and delete methods for the configured $model. Most methods accept an optional $filters parameter, that may be used to apply the filters configured in the applyFilters method to your queries.

A general recommendation is to only use repositories as a place to store your complex queries and/or queries that are used repeatedly in multiple places, since otherwise they might be considered an anti-pattern. For more complex queries it can however be useful to separate them from your services. Repositories also serve as a way to self-document those queries by using descriptive method names. This way developers don't have to parse database queries and try to understand their purpose when going through your application logic.


use Chiiya\Common\Repositories\AbstractRepository;

/**
 * @extends AbstractRepository<Post>
 */
class PostRepository extends AbstractRepository
{
    protected string $model = Post::class;

    /**
     * @return Collection<Post>
     */
    public function postsDiscussedYesterday()
    {
        return $this->newQuery()
            ->whereHas('comments', function (Builder $builder) {
                $builder
                    ->where('created_at', '>=', now()->subDay()->startOfDay())
                    ->where('created_at', '<=', now()->subDay()->endOfDay());
            })
            ->get();
    }

    /**
     * @inheritDoc
     */
    protected function applyFilters(Builder $builder, array $parameters): Builder
    {
        if (isset($parameters['title'])) {
            $builder->where('title', '=', $parameters['title']);
        }

        return $builder;
    }
}
// Find by primary key
$post = $repository->get(10);
// Find (first) by filters
$post = $repository->find(['title' => 'Lorem ipsum']);
// List all entities, optionally filtered
$posts = $repository->index();
$posts = $repository->index(['title' => 'Lorem ipsum']);
// Count entities, optionally filtered
$count = $repository->count();
$count = $repository->count(['title' => 'Lorem ipsum']);
// Create new entity
$post = $repository->create(['title' => 'Some title']);
// Update entity
$repository->update($post, ['title' => 'Lorem ipsum']);
// Delete entity
$repository->delete($post);

// Custom methods
$posts = $repository->postsDiscussedYesterday();
CodeService - Generate large amounts of random codes

Service class for efficiently generating large amounts of random, unique codes in memory for later processing.

use Chiiya\Common\Services\CodeService::class;
          
class CouponService {
    public function __construct(
        private CodeService $service,
    ) {}
          
    public function generateCodes()
    {
        // Optional, import previously exported codes so that we don't generate codes that already exist
        $this->service->import(storage_path('app/exports'));
        // Generate specified amount of random codes using the given pattern and character set
        $this->service->generate(
            1_000_000,
            '####-####-####',
            CodeService::SET_NUMBERS_AND_UPPERCASE,
        );
        // Get generated codes for further processing
        $codes = $this->service->getCodes();
        // ... e.g. bulk insert $codes into database
        // Export newly generated codes into (batched) CSV files. Optionally specify the amount of codes per file
        $this->service->export(storage_path('app/exports'));
        $this->service->export(path: storage_path('app/exports'), perFile: 500_000);
    }
}
CsvReader - Read CSV files

Small wrapper around the openspout/openspout csv reader for high-performance reading of CSV files:

$reader = resolve(\Chiiya\Common\Services\CsvReader::class);
$reader->open('/path/to/file.csv');
foreach ($reader->rows() as $row) {
    $values = $row->toArray();
}
$reader->close();
CsvWriter - Write CSV files

Small wrapper around the openspout/openspout csv writer:

$writer = resolve(\Chiiya\Common\Services\CsvWriter::class);
$writer->open('/path/to/file.csv');
$writer->write(['Value 1', 'Value 2']);
$writer->close();
ExcelReader - Read XLS/XLSX files

Small wrapper around the openspout/openspout excel reader for high-performance reading of XLS/XLSX files:

$reader = resolve(\Chiiya\Common\Services\ExcelReader::class);
$reader->open('/path/to/file.xlsx');
foreach ($reader->getSheetIterator() as $sheet) {
    foreach ($sheet->getRowIterator() as $row) {
        $values = $row->toArray();
    }
}
$reader->close();
ExcelWriter - Write XLX/XLSX files

Small wrapper around the openspout/openspout excel writer:

$writer = resolve(\Chiiya\Common\Services\ExcelWriter::class);
$writer->open('/path/to/file.xlsx');
$writer->setCurrentSheetName('Sheet 1');
$writer->addHeaderRow(['Name', 'Email']);
$writer->write(['John Doe', 'john.doe@example.com']);
$writer->addSheet('Sheet 2');
$writer->write(['Value 1', 'Value 2']);
$writer->close();
FileDownloader - Download remote files

Utility class for downloading files from a remote URL.

$downloader = resolve(\Chiiya\Common\Services\FileDownloader::class);
$file = $downloader->download('https://example.com/path/to/file.txt');
dump($file->getPath());
$file->delete();
Zipper - Unzip .zip files

Utility class for unzipping .zip files.

$zipper = resolve(\Chiiya\Common\Services\Zipper::class);
$location = $zipper->unzip('/path/to/file.zip');

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

License

The MIT License (MIT). Please see License File for more information.