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:
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;
}
}
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,
]);
}
}
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));
}
}
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();
}
}
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'),
];
}
}
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));
}
}