Milan Felix Šulc
📦 Package maker • 👷 Architect ModernTV • 🐘 PHP enthusiast • 💿 Multimedia engineer • 👨👩👧👦 Father • ☕️ Coffee-based
??.??.2019
@xf3l1x
@nettefw
composer require nettrine/dbal
CompilerExtension
Tracy
Classes
CompilerExtension
Parameters
Register
services
Decorate
services
Modify
PHP code
loadConfiguration()
beforeCompile()
afterCompile()
Services
private $defaults = [
'debug' => false,
'configuration' => [
'sqlLogger' => null,
'resultCacheImpl' => null,
'filterSchemaAssetsExpression' => null,
'autoCommit' => true,
],
'connection' => [...]
];
public function loadConfiguration(): void
{
$config = $this->validateConfig($this->defaults);
}
Expect::structure([
'debug' => Expect::bool(false),
'configuration' => Expect::structure([
'sqlLogger' => Expect::string(),
'resultCacheImpl' => Expect::string(),
'filterSchemaExpression' => Expect::string()->nullable(),
'autoCommit' => Expect::bool(true),
]),
'connection' => Expect::array()->default([
'driver' => 'pdo_sqlite',
'types' => [],
'typesMapping' => [],
]),
]);
composer require nettrine/dbal
composer require nettrine/orm
ORM
Symfony Console
DBAL
extensions:
# Doctrine DBAL
dbal: Nettrine\DBAL\DI\DbalExtension
dbal_console: Nettrine\DBAL\DI\DbalConsoleExtension
# Doctrine ORM
orm: Nettrine\ORM\DI\OrmExtension
orm_cache: Nettrine\ORM\DI\OrmCacheExtension
orm_console: Nettrine\ORM\DI\OrmConsoleExtension
orm_annotations: Nettrine\ORM\DI\OrmAnnotationsExtension
# Symfony Console
console: Contributte\Console\DI\ConsoleExtension(%consoleMode%)
public function loadConfiguration(): void
{
$builder = $this->getContainerBuilder();
$config = $this->validateConfig($this->defaults);
$builder
->addDefinition($this->prefix('application'))
->setFactory(Application::class);
}
public function loadConfiguration(): void
{
$builder = $this->getContainerBuilder();
$config = $this->validateConfig($this->defaults);
$builder->addDefinition($this->prefix('schemaToolCreateCommand'))
->setType(CreateCommand::class);
}
public function beforeCompile(): void
{
$builder = $this->getContainerBuilder();
$commands = $builder->findByType(Command::class);
$app = $builder->getDefinition($this->prefix('application'));
foreach ($commands as $serviceName => $service) {
$app->addSetup('add', [$service]);
}
}
public function createServiceConsole__application()
{
$service = new Symfony\Component\Console\Application;
$service->add($this->getService('orm.console.schemaToolDropCommand'));
$service->add($this->getService('orm.console.schemaToolUpdateCommand'));
$service->add($this->getService('orm.console.validateSchemaCommand'));
return $service;
}
tracy:
bar:
- My\Awesome\SuperPanel
public function afterCompile(ClassType $class): void
{
$initialize = $class->getMethod('initialize');
$initialize->addBody(
'$this->getService(?)->addPanel($this->getService(?));',
['tracy.bar', $this->prefix('queryPanel')]
);
}
}
DbalExtension.php
# Container_54599b6ea8.php
public function initialize()
{
$this->getService('tracy.bar')
->addPanel($this->getService('dbal.queryPanel'));
}
public function loadConfiguration(): void
{
$builder->addDefinition($this->prefix('connection'))
->setFactory(Connection::class)
->addSetup('@Tracy\Bar::addPanel', [
new Statement(QueryPanel::class, ['@self']),
]);
}
public function createServiceDbal__connection()
{
$service = new Doctrine\DBAL\Connection;
$this->getService('tracy.bar')
->addPanel(new Nettrine\DBAL\QueryPanel($service));
return $service;
}
tracy:
blueScreen:
- My\AwesomeBlueScreen::renderException
public static function renderException(?Throwable $e): ?array
{
if ($e === NULL) return NULL;
if ($e instanceof QueryException) {
return [
'tab' => 'SQL',
'panel' => Helpers::highlight($e->getSql()),
];
}
return NULL;
}
composer require nettrine/annotations
/**
* @Component\Component(name="user_list")
* @Component\Security(role="admin")
* @Component\Cache(expire="+20 minutes")
*/
💰
💰
💰
💰
use Doctrine\Common\Annotations\Annotation\Target;
/**
* @Annotation
* @Target("CLASS")
*/
final class Component
{
/** @var string */
public $name;
}
/**
* @Component\Component(name="user_list")
* @Component\Security(role="admin")
*/
final class UserListFactory implements IControlFactory
{
public function create(?array $args = null)
{
return new UserList(...);
}
}
public function loadConfiguration(): void
{
$builder = $this->getContainerBuilder();
$builder->addDefinition($this->prefix('creator'))
->setFactory(ComponentCreator::class);
}
public function beforeCompile(): void
{
$builder = $this->getContainerBuilder();
$components = $builder->findByType(IControlFactory::class);
$metadata = [];
foreach ($components as $service => $def) {
$meta = $this->parseAnnotations($def);
$meta['def'] = $def;
$metadata[] = $meta;
}
}
services:
- App\Components\UserListFactory
protected function parseAnnotations(string $class): array
{
$reader = new AnnotationReader();
$rc = new ReflectionClass($class);
$annotations = $reader->getClassAnnotations($rc);
$metadata = [];
foreach ($annotations as $annotation) {
// Parse @Component
if (get_class($annotation) === Component::class) {
$metadata['name'] = $annotation->name;
continue;
}
// Other annotations..
}
return $metadata;
}
public function beforeCompile(): void
{
// ...
$creator = $builder->getDefinition($this->prefix('creator'));
foreach ($metadata as $item) {
$creator->addSetup('register', [
$item['name'],
$item['def']
]);
}
}
trait TMagicControl
{
/** @var IMagicControlFactory @inject */
public $magicControlFactory;
public function createComponentMagic(): MagicControl
{
return $this->magicControlFactory->create();
}
}
class MagicControl
{
protected function createComponent($name): BaseComponent
{
return $this->creator->create($name, $args);
}
}
{block #content}
{control magic-user_list}
{/}
composer require nettrine/dbal
composer require nettrine/orm
composer require nettrine/fixtures
composer require nelmio/alice
use Doctrine\Common\DataFixtures\AbstractFixture;
class UserFixture extends AbstractFixture
{
public function load(ObjectManager $manager): void
{
$user = new User('Felix', 'Felicis');
$manager->persist($user);
$manager->flush();
}
}
class UserFixture extends AbstractFixture
{
public function load(ObjectManager $manager): void
{
$loader = new NativeLoader();
$users = $loader->loadData([
User::class => [
'user{0..100}' => [
'__construct' => [
'<firstName()>',
'<lastName()>',
'2 (unique)' => '<email()>',
],
],
],
]);
foreach($users as $user) {
$manager->persist($user);
}
$manager->flush();
}
}
extensions:
# Doctrine DBAL
dbal: Nettrine\DBAL\DI\DbalExtension
dbal_console: Nettrine\DBAL\DI\DbalConsoleExtension
# Doctrine ORM
orm: Nettrine\ORM\DI\OrmExtension
orm_cache: Nettrine\ORM\DI\OrmCacheExtension
orm_console: Nettrine\ORM\DI\OrmConsoleExtension
orm_annotations: Nettrine\ORM\DI\OrmAnnotationsExtension
# Data Fixtures
fixtures: Nettrine\Fixtures\DI\FixturesExtension
fixtures:
paths:
- %rootDir%/db/Fixtures
github.com/planette/nutella-project
Keep Contributting!
@xf3l1x
f3l1x.io
By Milan Felix Šulc
📦 Package maker • 👷 Architect ModernTV • 🐘 PHP enthusiast • 💿 Multimedia engineer • 👨👩👧👦 Father • ☕️ Coffee-based