Installation
composer require companyos/core
Ensure your config/bundles.php includes:
return [
// ...
CompanyOS\CoreBundle\CompanyOSCoreBundle::class => ['all' => true],
];
Database Configuration
Update config/packages/doctrine.yaml to match your database schema. The bundle expects DDD-style entities (e.g., src/Entity/).
First Use Case: Plugin Registration
Create a basic plugin in src/Plugin/ (e.g., MyPlugin.php):
namespace App\Plugin;
use CompanyOS\CoreBundle\Plugin\AbstractPlugin;
class MyPlugin extends AbstractPlugin
{
public function getName(): string
{
return 'my_plugin';
}
}
Register it in config/packages/companyos_core.yaml:
companyos_core:
plugins:
my_plugin: App\Plugin\MyPlugin
API Endpoint
The bundle provides a skeleton for API routes. Extend src/Controller/ with a custom controller (e.g., ApiController.php):
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
class ApiController
{
#[Route('/api/test', name: 'api_test', methods: ['GET'])]
public function test(): JsonResponse
{
return new JsonResponse(['status' => 'ok']);
}
}
Domain-Driven Design (DDD) Layering
User, Role) in src/Entity/ with business logic in methods.UserService) to orchestrate domain logic. Example:
namespace App\Service;
use CompanyOS\CoreBundle\Domain\Service\UserServiceInterface;
class UserService implements UserServiceInterface
{
public function createUser(array $data): void
{
// Business logic here
}
}
config/packages/doctrine.yaml.Event-Driven Architecture
UserCreatedEvent) via the event dispatcher:
$this->eventDispatcher->dispatch(new UserCreatedEvent($user));
$eventDispatcher->addListener(UserCreatedEvent::class, function (UserCreatedEvent $event) {
// Handle event (e.g., log, notify)
});
Plugin System Integration
UserServiceInterface).PluginInitializedEvent) to inject behavior:
$eventDispatcher->addListener(PluginInitializedEvent::class, [$this, 'onPluginInit']);
companyos_core.plugins config. Use PluginManager to interact with them:
$pluginManager = $this->container->get('companyos_core.plugin_manager');
$myPlugin = $pluginManager->getPlugin('my_plugin');
API-First Design
JsonResponse for API endpoints. Leverage DTOs (Data Transfer Objects) for input/output:
#[Route('/api/users', name: 'api_users', methods: ['POST'])]
public function createUser(UserDto $dto): JsonResponse
{
$this->userService->createUser($dto->toArray());
return new JsonResponse(['status' => 'created']);
}
/api/ and version them (e.g., /api/v1/users).Authentication
config/packages/security.yaml:
security:
providers:
oauth_provider:
companyos_core:
service: App\Security\OAuthUserProvider
firewalls:
api:
pattern: ^/api
stateless: true
oauth:
provider: oauth_provider
OAuthUserProvider to fetch users from your domain layer.Doctrine Entities
CompanyOS\CoreBundle\Domain\Entity\AbstractEntity for base functionality (e.g., timestamps, UUIDs).namespace App\Repository;
use CompanyOS\CoreBundle\Domain\Repository\UserRepositoryInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
class UserRepository extends ServiceEntityRepository implements UserRepositoryInterface
{
public function findByEmail(string $email): ?User
{
return $this->createQueryBuilder('u')
->where('u.email = :email')
->setParameter('email', $email)
->getQuery()
->getOneOrNullResult();
}
}
Command Bus (CQRS)
CommandBus:
$this->commandBus->dispatch(new CreateUserCommand($data));
CreateUserCommandHandler) to process commands.Testing
PluginManager and EventDispatcher in unit tests:
$pluginManager = $this->createMock(PluginManager::class);
$pluginManager->method('getPlugin')->willReturn($mockPlugin);
$this->container->set('companyos_core.plugin_manager', $pluginManager);
Alpha Version Limitations
make:migration.src/Controller/ApiController) to avoid NotFoundHttpException.Plugin System Quirks
companyos_core.plugins. Use:
services:
App\Plugin\MyPlugin:
tags: ['companyos_core.plugin']
public function __construct(private UserServiceInterface $userService)
{
}
Event-Driven Gotchas
$eventDispatcher->addListener(UserCreatedEvent::class, [$this, 'handleUserCreated'], 10);
EventDispatcher into domain entities. Keep events in the application layer.Authentication Caveats
security.yaml matches your OAuth provider (e.g., password grant type for local auth).Security component to store tokens or integrate with lexik/jwt-authentication-bundle.Performance Tips
getName().$plugin = $this->container->get('companyos_core.plugin_manager')->getPlugin('my_plugin', true);
Enable Debug Mode
Set APP_ENV=dev in .env to see detailed errors and Symfony’s profiler.
Plugin Debugging
bin/console debug:container | grep companyos_core.plugin_manager
config/packages/companyos_core.yaml.Event Listener Debugging
bin/console debug:event-dispatcher UserCreatedEvent
$eventDispatcher->addListener(UserCreatedEvent::class, function (UserCreatedEvent $event) {
error_log('Event triggered: ' . $event->getUser()->getId());
});
Doctrine Issues
bin/console doctrine:schema:validate
*RepositoryInterface.Customizing Core Services
config/services.yaml:
services:
App\Service\UserService: ~
CompanyOS\CoreBundle\Domain\Service\UserServiceInterface: '@App\Service\UserService'
**Adding New Events
How can I help you explore Laravel packages today?