codeages/biz-framework
Biz Framework is a lightweight PHP service-layer framework with a container and core building blocks like config, DB connections/migrations, cache, DAO/service patterns, events, validation, logging, and exceptions—aimed at structuring business logic cleanly.
Installation
composer require codeages/biz-framework
Add to composer.json under extra:
"biz-framework": {
"scan": ["app/Business"]
}
Directory Structure
Create a Business directory in app/ and follow the framework’s conventions:
app/
├── Business/
│ ├── [Domain]/
│ │ ├── [Domain]Service.php
│ │ ├── [Domain]ServiceInterface.php
│ │ ├── [Domain]RepositoryInterface.php
│ │ ├── [Domain]Repository.php
│ │ ├── [Domain]Model.php
│ │ └── [Domain]Exception.php
First Use Case: CRUD Service
Define a UserService in app/Business/User/UserService.php:
namespace App\Business\User;
use Codeages\Biz\Framework\Service;
class UserService extends Service
{
public function create(array $data)
{
return $this->repository()->create($data);
}
}
Register the service in app/Providers/AppServiceProvider.php:
public function register()
{
$this->app->bind(UserServiceInterface::class, UserService::class);
}
Autoloading
Ensure composer dump-autoload is run after adding new classes.
class UserService extends Service
{
public function __construct(
UserRepositoryInterface $repository,
UserValidatorInterface $validator
) {
$this->repository = $repository;
$this->validator = $validator;
}
}
public function updateProfile(array $data)
{
$this->transactional(function () use ($data) {
$this->validator->validate($data);
$this->repository()->update($data);
});
}
RepositoryInterface for data access:
class UserRepository implements UserRepositoryInterface
{
public function findByEmail(string $email)
{
return User::where('email', $email)->first();
}
}
Service::repository() to access the bound repository:
$user = $this->repository()->findByEmail('user@example.com');
app/Business/[Domain]/Command/:
namespace App\Business\User\Command;
class CreateUserCommand
{
public $name;
public $email;
}
public function handle(CreateUserCommand $command)
{
return $this->repository()->create([
'name' => $command->name,
'email' => $command->email,
]);
}
public function create(array $data)
{
$user = $this->repository()->create($data);
event(new UserCreated($user));
return $user;
}
public function validateCreate(array $data)
{
$validator = Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
]);
if ($validator->fails()) {
throw new \RuntimeException($validator->errors()->first());
}
}
use App\Facades\UserServiceFacade;
$user = UserServiceFacade::create($data);
public function __construct(private UserService $userService) {}
public function store(Request $request)
{
return $this->userService->create($request->all());
}
public function handle()
{
$this->userService->seedSampleUsers();
}
$mock = Mockery::mock(UserServiceInterface::class);
$this->app->instance(UserServiceInterface::class, $mock);
scan config in composer.json must match the Business directory structure exactly. Misconfiguration leads to silent failures.scan path and run composer dump-autoload.protected static $repository;
public function repository()
{
return self::$repository ??= app(UserRepositoryInterface::class);
}
class AuthenticatedUserServiceDecorator implements UserServiceInterface
{
public function __construct(private UserService $service) {}
public function create(array $data)
{
if (!auth()->check()) {
throw new \RuntimeException('Unauthenticated');
}
return $this->service->create($data);
}
}
Resource classes or DTOs:
public function toArray($user)
{
return [
'id' => $user->id,
'name' => $user->name,
// ...
];
}
php artisan container:list | grep UserService
$this->app->bind(UserRepositoryInterface::class, UserRepository::class);
transactional block. Nested transactions may fail silently.php artisan event:list
trait SoftDeletesService
{
public function softDelete($id)
{
return $this->repository()->where('id', $id)->delete();
}
}
public function repository()
{
$type = request()->input('type');
return $this->app->make("App\\Business\\User\\{$type}Repository");
}
class LoggedUserService implements UserServiceInterface
{
public function __construct(private UserService $service) {}
public function create(array $data)
{
\Log::info('Creating user', $data);
return $this->service->create($data);
}
}
public function create(array $data)
{
try {
return $this->repository()->create($data);
} catch (\Exception $e) {
throw new UserCreationException($e->getMessage(), $e->getCode());
}
}
class UserRepository implements UserRepositoryInterface
{
public function search(string $query)
{
return User::where('name', 'like', "%{$query}%")->get();
}
}
How can I help you explore Laravel packages today?