PHP code example of douglasgreyling / light-service

1. Go to this page and download the library: Download douglasgreyling/light-service 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/ */

    

douglasgreyling / light-service example snippets


class TaxController extends SomeController
{
    public function update()
    {
        $order = Order::find(request('id'));
        $tax_ranges = TaxRange::forRegion($order->region);

        if (is_null($tax_ranges)) {
            return ...; // render some view
        }

        $tax_percentage = $tax_ranges->forTotal($order->total);

        if (is_null($tax_percentage)) {
            return ...; // render some other view
        }

        $order->tax = round(($order->total * ($tax_percentage / 100)), 2);

        if ($order->total_with_tax > 200) {
            $order->provide_free_shipping;
        }

        return ...; // Redirect to some view with a flash message
    }
}

class GreetsSomeoneAction
{
    use LightService\Action;

    private $expects  = ['name'];
    private $promises = ['greeting'];

    protected function executed($context)
    {
        $context->greeting = "Hello, {$context->name}. Solved any fun mysteries lately?";
    }
}

$result = GreetsSomeoneAction::execute(['name' => 'Scooby']);

$result = GreetsSomeoneAction::execute(['name' => 'Scooby']);

if ($result->success()) {
    echo $result->greeting;
}

> "Hello, Scooby. Solved any fun mysteries lately?"

class FeedsSomeoneAction
{
    use LightService\Action;

    private $expects = ['name'];

    protected function executed($context)
    {
        $snack = Fridge::fetch('Grapes');

        Person::find($context->name)->feed($snack);
    }
}

class GreetsAndFeedsSomeone
{
    use LightService\Organizer;

    public static function call($name)
    {
        return self::with(['name' => $name])->reduce(
            GreetsSomeoneAction::class,
            FeedSomeoneAction::class
        );
    }
}

$result = GreetsAndFeedsSomeone::call(['name' => 'Shaggy']);

$result = GreetsAndFeedsSomeone::call(['name' => 'Shaggy']);

if ($result->success()) {
    echo "Time to stock up on snacks!";
}

> "Time to stock up on snacks!"

class CalculatesTax
{
    use LightService\Organizer;

    public static function call($order)
    {
        return self::with(['order' => $order])->reduce(
            LooksUpTaxPercentageAction::class,
            CalculatesOrderTaxAction::class,
            ProvidesFreeShippingAction::class
        );
    }
}

class LooksUpTaxPercentageAction
{
    use LightService\Action;

    private $expects  = ['order'];
    private $promises = ['tax_percentage'];

    protected function executed($context)
    {
        $order      = $context->order;
        $tax_ranges = TaxRange::forRegion($order->region);

        $context->tax_percentage = 0;

        if (is_null($tax_ranges)) {
            $context->fail('The tax ranges were not found');
            $this->nextContext();
        }

        $tax_percentage = $tax_ranges->forTotal($order->total);

        if (is_null($tax_percentage)) {
            $context->fail('The tax percentage were not found');
            $this->nextContext();
        }

        $context->tax_percentage = $tax_percentage;
    }
}

class CalculatesOrderTaxAction
{
    use LightService\Action;

    private $expects = ['order', 'tax_percentage'];

    protected function executed($context)
    {
        $context
        ->order
        ->tax = round($order->total * ($tax_percentage / 100), 2);
    }
}

class ProvidesFreeShippingAction
{
    use LightService\Action;

    private $expects = ['order'];

    protected function executed($context)
    {
        $total_with_tax = $context->order->total_with_tax;

        if ($total_with_tax > 200) {
            $context->order->provide_free_shipping;
        }
    }
}

class TaxController extends Controller
{
    public function update()
    {
        $order = Order::find(request('id'));

        $service_result = CalculatesTax::call($order);

        if ($service_result->failure()) {
            return ...; // render some view
        } else {
            return ...; // Redirect to some view with a flash message
        }
    }
}

class SubmitsOrderAction
{
    use LightService\Action;

    protected function executed($context)
    {
        if (!$context->order->submitOrderSuccessful()) {
            $context->failAndReturn('Failed to submit the order');
        }

      // This won't be executed
        $context->mailer->sendOrderNotification();
    }
}

class ChecksOrderStatusAction
{
    use LightService\Action;

    protected function executed($context)
    {
        if ($context->order->mustSendNotification()) {
            $context->skipRemaining("Everything is good, no need to execute the rest of the actions");
        }
    }
}

class SomeOrganizer
{
    use LightService\Organizer;

    public static function call($context)
    {
        return self::with($context)->reduce(...self::actions());
    }

    public static function actions()
    {
        return [
            OneAction::class,
            TwoAction::class,
            ThreeAction::class
        ];
    }
}

class TwoAction
{
    use LightService\Action;

    protected function executed($context)
    {
        if ($context->user->role == 'admin') {
            $context->logger->info('admin is doing something');
        }

        $context->user->doSomething();
    }
}

class SomeOrganizer
{
    use LightService\Organizer;

    public function beforeEach($context)
    {
        if ($context->currentAction() == TwoAction::class) {
            if ($context->user->role != 'admin') {
                return;
            }

            $context->logger->info('admin is doing something');
        }
    }

    public function afterEach($context)
    {
        if ($context->currentAction() == TwoAction::class) {
            if ($context->user->role != 'admin') {
                return;
            }

            $context->logger->info('admin is doing something');
        }
    }

    public function aroundEach($context)
    {
        $context->logger->info('admin is about to do (or already has done) something');
    }

    public static function call($context)
    {
        return self::with($context)->reduce(...self::actions());
    }

    public static function actions()
    {
        return [
            OneAction::class,
            TwoAction::class,
            ThreeAction::class
        ];
    }
}

class TwoAction
{
    use LightService\Action;

    protected function executed($context)
    {
        $context->user->doSomething();
    }
}

class FooAction
{
    use LightService\Action;

    private $expects  = ['a', 'b'];
    private $promises = ['c'];

    protected function executed($context)
    {
        $context->c = $context->a + $context->b;
    }
}

class FooAction
{
    use LightService\Action;

    private $expects  = 'a';
    private $promises = 'b';

    protected function executed($context)
    {
        $context->b = $context->a + 1;
    }
}

$result = GreetsSomeoneAction::execute(['name' => 'Scooby']);

var_dump($result->toArray());

class AnOrganizer
{
    use LightService\Organizer;

    private $aliases = ['my_key' => 'key_alias'];

    public static function call($order)
    {
        return self::with(['order' => $order])->reduce(
            AnAction::class,
            AnotherAction::class,
        );
    }
}

class AnAction
{
    use LightService\Action;

    private $promises = 'my_key';

    protected function executed($context)
    {
        $context->my_key = "value";
    }
}

class AnotherAction
{
    use LightService\Action;

    private $expects = 'key_alias';

    protected function executed($context)
    {
        $context->key_alias;
    }
}

class SomeAction
{
    use LightService\Action;

    protected function executed($context)
    {
        $context->fail("I don't like what happened here.");
    }
}

class SomeAction
{
    use LightService\Action;

    protected function executed($context)
    {
        if (95 < $context->teapot->heat()) {
            $context->fail("The teapot is not hot enough", 1234);
        }

      # Make some tea

        if (2 < $context->sugar->amount()) {
            $context->fail("There is not enough sugar for the tea", 5678);
        }
    }
}

$result = SomeAction::execute();

echo $result->message();
> "The teapot is not hot enough"

echo $result->errorCode();
> 1234

class SaveEntities
{
    use LightService\Action;

    private $expects = 'user';

    protected function executed($context)
    {
        $context->user->save();
    }

    protected function rolledBack($executed)
    {
        $context->user->destroy();
    }
}

class CallSomeExternalAPI
{
    use LightService\Action;

    protected function executed($context)
    {
        $api_call_result = SomeAPI::saveUser($context->user);

        if ($api_call_result->failure) {
            $context->failWithRollback("Error when calling external API");
        }
    }
}

class ExtractsTransformsLoadsData
{
    public static function run($connection)
    {
        $context = RetrievesConnectionInfo::call($connection);
        $context = PullsDataFromRemoteApi::call($context);

        $retrieved_items = $context->retrieved_items;

        if ($retrieved_items->empty) {
            NotifiesEngineeringTeamAction::execute($context);
        }

        foreach ($retrieved_items as $item) {
            $context->item = $item;
            TransformsData::call($context);
        }

        $context = LoadsData::call($context);

        return SendsNotifications::call($context);
    }
}

class ExtractsTransformsLoadsData
{
    use LightService\Organizer;

    public static function call($connection)
    {
        return self::with(['connection' => $connection])->reduce(...self::actions());
    }

    public static function actions()
    {
        return [
            RetrievesConnectionInfo::class,
            PullsDataFromRemoteApi::class,
            self::reduceIf(
                function ($context) {
                    return array_empty($context->retrieved_items);
                },
                [ NotifiesEngineeringTeamAction::class ]
            ),
            self::iterate('retrieved_items', [ TransformsData::class ]),
            LoadsData::class,
            SendsNotifications::class
        ];
    }
}

class ReduceUntilOrganizer
{
    use LightService\Organizer;

    public static function call($number)
    {
        return self::with(['number' => $number])->reduce(
            AddsOneAction::class,
            self::reduceUntil(
                function ($context) {
                    return 3 < $context->number;
                },
                [ AddsOneAction::class ]
            )
        );
    }
}

class ReduceIfOrganizer
{
    use LightService\Organizer;

    public static function call($number)
    {
        return self::with(['number' => $number])->reduce(
            AddsOneAction::class,
            self::reduceIf(
                function ($context) {
                    return 1 < $context->number;
                },
                [ AddsOneAction::class ]
            ),
            AddsOneAction::class
        );
    }
}

class IterateOrganizer
{
    use LightService\Organizer;

    public static function call($context)
    {
        return self::with($context)->reduce(
            self::iterate('numbers', [
                IterateAction::class,
            ])
        );
    }
}

class IterateAction
{
    use LightService\Action;

    private $expects  = ['number'];
    private $promises = ['number'];

    protected function executed($context)
    {
        $context->sum += $context->number;
    }
}

class ExecuteOrganizer
{
    use LightService\Organizer;

    public static function call($number)
    {
        return self::with(['number' => $number])->reduce(
            AddsOneAction::class,
            self::execute(function ($context) {
                $context->number += 1;
            })
        );
    }
}

class AddToContextOrganizer
{
    use LightService\Organizer;

    public static function call()
    {
        return self::with([])->reduce(
            self::addToContext(['number' => 0]),
            AddsOneAction::class
        );
    }
}

docker compose run --rm --build php

docker build --build-arg PHP_VERSION=8.2 -t light-service-php:8.2 .
docker run --rm light-service-php:8.2