Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save alaminfirdows/4342ab3a82586a4a23a59f4eaf660db1 to your computer and use it in GitHub Desktop.
Save alaminfirdows/4342ab3a82586a4a23a59f4eaf660db1 to your computer and use it in GitHub Desktop.
uses-of-service-class-in-laravel.md

We can use service classes in laravel -

  • ⁠To Separate Complex Business Logic
  • ⁠Third-Party Service Integration
  • ⁠Improve Code Reusability
  • ⁠Separate Logics for Testing
  • ⁠Data Transformation (Convert Data from One Format to Another)
  • ⁠Service Layer Abstraction

Here are some examples:

1. To Separate Complex Business Logic

Example: Calculating the total price of an order, including dynamic discounts, taxes based on location, and varying shipping fees.

Service Class:

namespace App\Services;

class OrderService
{
    public function calculateTotalPrice($order)
    {
        $subtotal = $this->calculateSubtotal($order->items);
        $discount = $this->applyDiscounts($subtotal, $order->user);
        $tax = $this->calculateTax($subtotal, $order->address);
        $shipping = $this->calculateShipping($order->address);

        return $subtotal - $discount + $tax + $shipping;
    }

    protected function calculateSubtotal($items)
    {
        return array_sum(array_map(fn($item) => $item->price * $item->quantity, $items));
    }

    protected function applyDiscounts($subtotal, $user)
    {
        // Example logic: 5% discount for premium users, 10% discount for orders above $100
        if ($user->is_premium) {
            return $subtotal * 0.05;
        } elseif ($subtotal > 100) {
            return $subtotal * 0.10;
        }

        return 0;
    }

    protected function calculateTax($subtotal, $address)
    {
        // Example logic: Different tax rates based on state
        $taxRates = [
            'CA' => 0.075,
            'NY' => 0.085,
            // Add more states here
        ];

        $state = $address->state;
        return isset($taxRates[$state]) ? $subtotal * $taxRates[$state] : 0;
    }

    protected function calculateShipping($address)
    {
        // Example logic: Free shipping for local, $20 for international
        return $address->country === 'US' ? 0 : 20;
    }
}

2. Third-Party Service Integration

Example: Integrating Stripe for handling payments with customer and invoice management.

Service Class:

namespace App\Services;

use Stripe\Stripe;
use Stripe\Charge;
use Stripe\Customer;

class PaymentService
{
    public function __construct()
    {
        Stripe::setApiKey(config('services.stripe.secret'));
    }

    public function createCustomer($user)
    {
        return Customer::create([
            'email' => $user->email,
            'name' => $user->name,
            'source' => $user->stripe_token, // Assume the token is provided by frontend
        ]);
    }

    public function chargeCustomer($customerId, $amount, $currency = 'usd', $description = 'Charge Description')
    {
        return Charge::create([
            'customer' => $customerId,
            'amount' => $amount * 100, // Stripe expects amount in cents
            'currency' => $currency,
            'description' => $description,
        ]);
    }
}

3. Improve Code Reusability

Example: Handling various types of emails, such as welcome, order confirmation, and password reset emails.

Service Class:

namespace App\Services;

use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeMail;
use App\Mail\OrderConfirmationMail;
use App\Mail\PasswordResetMail;

class EmailService
{
    public function sendWelcomeEmail($user)
    {
        Mail::to($user->email)->send(new WelcomeMail($user));
    }

    public function sendOrderConfirmationEmail($order)
    {
        Mail::to($order->user->email)->send(new OrderConfirmationMail($order));
    }

    public function sendPasswordResetEmail($user, $token)
    {
        Mail::to($user->email)->send(new PasswordResetMail($user, $token));
    }
}

4. Separate Logics for Testing

Example: An authentication service to abstract user login, logout, and registration functionalities.

Service Class:

namespace App\Services;

use Illuminate\Support\Facades\Auth;
use App\Models\User;
use Illuminate\Support\Facades\Hash;

class AuthService
{
    public function register($data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }

    public function login($credentials)
    {
        return Auth::attempt($credentials);
    }

    public function logout()
    {
        Auth::logout();
    }

    public function check()
    {
        return Auth::check();
    }
}

5. Data Transformation (Convert Data from One Format to Another)

Example: Transforming user data for an API response, including additional information such as roles and permissions.

Service Class:

namespace App\Services;

class UserDataTransformer
{
    public function transform($user)
    {
        return [
            'id' => $user->id,
            'name' => $user->name,
            'email' => $user->email,
            'roles' => $user->roles->pluck('name'),
            'permissions' => $user->permissions->pluck('name'),
            'registered_at' => $user->created_at->format('Y-m-d H:i:s'),
        ];
    }
}

6. Service Layer Abstraction

Example: Handling notifications via email, SMS, and push notifications.

Service Class:

namespace App\Services;

use App\Notifications\EmailNotification;
use App\Notifications\SmsNotification;
use App\Notifications\PushNotification;
use Illuminate\Support\Facades\Notification;

class NotificationService
{
    public function send($type, $recipient, $message)
    {
        switch ($type) {
            case 'email':
                $this->sendEmail($recipient, $message);
                break;
            case 'sms':
                $this->sendSms($recipient, $message);
                break;
            case 'push':
                $this->sendPushNotification($recipient, $message);
                break;
        }
    }

    protected function sendEmail($recipient, $message)
    {
        Notification::route('mail', $recipient->email)->notify(new EmailNotification($message));
    }

    protected function sendSms($recipient, $message)
    {
        Notification::route('nexmo', $recipient->phone)->notify(new SmsNotification($message));
    }

    protected function sendPushNotification($recipient, $message)
    {
        Notification::route('fcm', $recipient->device_token)->notify(new PushNotification($message));
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment