PHP code example of nickjbedford / laravel-transactions

1. Go to this page and download the library: Download nickjbedford/laravel-transactions library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

nickjbedford / laravel-transactions example snippets


// Used by business logic to perform transactional changes.
abstract class YetAnother\Laravel\Transaction

// Used by controllers to wrap [ request -> transaction -> response ] processes.
abstract class YetAnother\Laravel\Http\TransactionResponder

'providers' => [
    // ...
    
    \YetAnother\Laravel\Providers\TransactionsServiceProvider::class,
],

public function execute(): self
{
    try
    {
        $this->lockTableIfNecessary();
        $this->beforeTransaction();
        DB::transaction(fn() => $this->validateAndPerform());
    }
    catch(Throwable $exception)
    {
        $this->revertSideEffects();
        $this->cleanupAfterFailure();
        throw $exception;
    }
    finally
    {
        $this->afterTransaction();
        $this->unlockTableIfNecessary();
        $this->finally();
    }
    $this->fireEvent();
    return $this;
}

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use YetAnother\Laravel\Transaction;
use App\Models\Attachment;

/**
 * Represents a transaction that must upload a file to a
 * storage destination and update the database.
 */
class UploadAttachmentTransaction extends Transaction
{
    private ?string $uploadedFilePath = null;
    private UploadedFile $file;
    
    public ?Attachment $model = null;
    
    public function __construct(UploadedFile $file)
    {
        $this->file = $file;
    }
    
    /**
     * Validates the action before it is performed.
     * @throws Throwable
     */
    protected function validate() : void
    {
        $extension = strtolower($this->file->getClientOriginalExtension());
        
        if (!in_array($extension, [ 'png', 'jpg', 'jpeg', 'gif' ]))
            throw new InvalidArgumentException('Uploaded file is not a valid file type.');
    }
    
    /**
     * Uploads the file to Amazon S3 then creates an
     * Attachment model in the database.
     * @throws Exception
     */
    protected function perform() : void
    {
        $this->uploadFileToS3();
        $this->createAttachment();
    }
    
    protected function uploadFileToS3(): void
    {
        $path = 'some/path/to/' . $this->file->getClientOriginalName();
        $s3 = Storage::disk('s3');
        
        if ($s3->put($this->file, $path))
            $this->uploadedFilePath = $path;
    }
    
    protected function createAttachment(): void
    {
        $this->model = Attachment::create([
            'disk' => 's3',
            'path' => $this->uploadedFilePath
        ]);
    }
    
    /**
     * Deletes the file from S3 if any processes afterwards
     * failed. The database transaction has already been rolled
     * back at this time. 
     */
    public function cleanupAfterFailure() : void
    {
        parent::cleanupAfterFailure();
        
        if ($this->uploadedFilePath)
        {
            $s3 = Storage::disk('s3');
            $s3->delete($this->uploadedFilePath);
        }
    }
}

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use YetAnother\Laravel\Transaction;

/**
 * This event is fired after the transaction completes.
 */
class TransactionComplete
{
    use Dispatchable, SerializesModels;
    
    public function __construct(Transaction $transaction)
    {
        //
    }
}

use YetAnother\Laravel\Transaction;
use App\Events\TransactionComplete;

class EventFiringTransaction extends Transaction
{
    protected ?string $event = TransactionComplete::class; 
    
    protected function perform() : void
    {
        // 
    }
}

use YetAnother\Laravel\Transaction;
use App\Events\TransactionComplete;

class EventFiringTransaction extends Transaction
{
    protected function perform() : void
    {
        // 
    }
    
    /**
     * Create a custom event to dispatch. 
     * @return mixed
     */
    protected function createEvent()
    {
        return new TransactionComplete($this);
    }
}

use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class ModelController extends Controller
{
    /**
     * Stores the model and redirects to the show action.
     * @param Request $request
     * @return Responsable
     */
    public function store(Request $request): Responsable
    {
        return new CreateModelTransactionResponder();    
    }
}

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use YetAnother\Laravel\Http\TransactionResponder;
use YetAnother\Laravel\Transaction;
use App\Transactions\CreateModelTransaction;

class CreateModelTransactionResponder extends TransactionResponder
{
    /**
     * Creates the appropriate response for a successful transaction. 
     * @param Transaction $transaction
     * @return Response
     */
    protected function getResponseAfterExecution(Transaction $transaction): Response
    {
        /** @var CreateModelTransaction $transaction */
        $redirectTo = route('model.show', [ 'model' => $transaction->model->id ]);
        return redirect($redirectTo);
    }
    
    /**
     * Creates the desired transaction from an incoming request. TransactionResponder
     * will execute this transaction. 
     * @param Request $request
     * @return Transaction
     */
    protected function createTransaction(Request $request): Transaction
    {
        $name = trim($request->name);
        $description = trim($request->description);
        
        return new CreateModelTransaction($name, $description);
    }
    
    /**
     * Overrides the response to return when a transaction fails with an exception.
     * By default, this throws the exception onto Laravel's handling mechanisms, but
     * this could be used to return a structured JSON response or other custom response. 
     * @param Throwable $exception
     * @return Response
     */
    protected function exceptionToResponse(Throwable $exception) : Response
    {
        return response()->json([
            'status' => false,
            'error' => $exception->getMessage(),
            'code' => $exception->getCode()
        ]);
    }
}
shell
php artisan make:transaction CustomTransaction
php artisan make:responder CustomTransactionResponder