Milan Felix Ε ulc
π¦ Package maker β’ π· Architect ModernTV β’ π PHP enthusiast β’ πΏ Multimedia engineer β’ π¨βπ©βπ§βπ¦ Father β’ βοΈ Coffee-based
@xf3l1x
f3l1x.io
30.11.2024
Β
π€·ββοΈ
π΄πΌπ΅π»
Contributte
Contributte
8 years of history
199 repositories
28 members
Contributte
Contributte
sentry sentry-skeleton service-autoloader
seznamcaptcha simple-blogger social starter-skeleton tester tester-skeleton thepay thepay-api thumbator tracy translation ui ui-skeleton uniparser utils validator vite vite-skeleton webapp-skeleton webdata webpack webpack-skeleton wordcha
advisories all anabelle aop api api-docu api-router api-router-skeleton apitte apitte-console apitte-core apitte-debug apitte-events apitte-fullstack apitte-mapping apitte-middlewares apitte-negotiation apitte-openapi apitte-presenter apitte-skeleton application bare benchmarks blogette bootstrap bus cache cli-http code-checker code-rules codeception comgate commits-site componette-design componette-dockerfiles componette-site console console-extra console-skeleton contributte contributte-site cookbook
crafter czech-post database datagrid datagrid-elasticsearch-data-source datagrid-nette-database-data-source datagrid-skeleton ddd-skeleton demo-frankenphp demo-typesense dev di dockerfiles doctrine doctrine-annotations doctrine-cache doctrine-dbal doctrine-extensions-atlantic18 doctrine-extensions-beberlei doctrine-extensions-knplabs doctrine-extensions-oroinc doctrine-extra doctrine-extra-skeleton doctrine-fixtures doctrine-gedmo doctrine-migrations doctrine-mongodb doctrine-odm doctrine-orm doctrine-project doctrine-skeleton dummy-events eet elastica elasticsearch embedded-skeleton event-application-bridge event-bridges event-dispatcher event-dispatcher-extra
event-security-bridge facebook
fileupload fio firewall fly-response flysystem forms forms-bootstrap forms-controls forms-multiplier forms-wizard framex framex-skeleton ftpdeployer fx-skeleton ghpage gopay gopay-api gopay-inline gopay-simple gosms gui-skeleton guzzlette http hydrator image-storage imagist invoice jsonrpc kernel latte latte-email latte-formatter latte-parsedown latte-parsedown-extra live-form-validation logging mail mailing mate menu-control
messenger messenger-skeleton micro-skeleton
microapi middlewares mobilni-platby model model-specification monolog nella nella-skeleton neonizer newrelic newrelic-tracy nextras-criteria nextras-orm-events nextras-orm-generator nextras-orm-query-object ntdb oauth2-client oauth2-server paginator-control payments-skeleton pdf phpdoc phpless phpstan phpunit planette-micro-site planette-play-site planette-site playground psr11-container-interface psr6-caching psr7-http-message qa rabbitmq reCAPTCHA redis replacus scheduler security
sentry sentry-skeleton service-autoloader
seznamcaptcha simple-blogger social starter-skeleton tester tester-skeleton thepay thepay-api thumbator tracy translation ui ui-skeleton uniparser utils validator vite vite-skeleton webapp-skeleton webdata webpack webpack-skeleton wordcha
advisories all anabelle aop api api-docu api-router api-router-skeleton apitte apitte-console apitte-core apitte-debug apitte-events apitte-fullstack apitte-mapping apitte-middlewares apitte-negotiation apitte-openapi apitte-presenter apitte-skeleton application bare benchmarks blogette bootstrap bus cache cli-http code-checker code-rules codeception comgate commits-site componette-design componette-dockerfiles componette-site console console-extra console-skeleton contributte contributte-site cookbook
crafter czech-post database datagrid datagrid-elasticsearch-data-source datagrid-nette-database-data-source datagrid-skeleton ddd-skeleton demo-frankenphp demo-typesense dev di dockerfiles doctrine doctrine-annotations doctrine-cache doctrine-dbal doctrine-extensions-atlantic18 doctrine-extensions-beberlei doctrine-extensions-knplabs doctrine-extensions-oroinc doctrine-extra doctrine-extra-skeleton doctrine-fixtures doctrine-gedmo doctrine-migrations doctrine-mongodb doctrine-odm doctrine-orm doctrine-project doctrine-skeleton dummy-events eet elastica elasticsearch embedded-skeleton event-application-bridge event-bridges event-dispatcher event-dispatcher-extra
event-security-bridge facebook
fileupload fio firewall fly-response flysystem forms forms-bootstrap forms-controls forms-multiplier forms-wizard framex framex-skeleton ftpdeployer fx-skeleton ghpage gopay gopay-api gopay-inline gopay-simple gosms gui-skeleton guzzlette http hydrator image-storage imagist invoice jsonrpc kernel latte latte-email latte-formatter latte-parsedown latte-parsedown-extra live-form-validation logging mail mailing mate menu-control
messenger messenger-skeleton micro-skeleton
microapi middlewares mobilni-platby model model-specification monolog nella nella-skeleton neonizer newrelic newrelic-tracy nextras-criteria nextras-orm-events nextras-orm-generator nextras-orm-query-object ntdb oauth2-client oauth2-server paginator-control payments-skeleton pdf phpdoc phpless phpstan phpunit planette-micro-site planette-play-site planette-site playground psr11-container-interface psr6-caching psr7-http-message qa rabbitmq reCAPTCHA redis replacus scheduler security
Contributte
Contributte
I do not like...
I do not likeΒ creating new project
I do not likeΒ creating CRUD
I do not likeΒ creating something again
Fast prototyping
Low-level files
Customize everything
Framework independent
KISS
Research
Laravel / Symfony
Laravel
.
βββ README.md
βββ app
βββ artisan
βββ bootstrap
βββ composer.json
βββ composer.lock
βββ config
βββ database
βββ package.json
βββ phpunit.xml
βββ postcss.config.js
βββ public
βββ resources
βββ routes
βββ storage
βββ stubs
βββ tailwind.config.js
βββ tests
βββ vendor
βββ vite.config.js
Research
Artisan Make
Laravel
β php artisan make
Laravel Framework 11.34.2
Available commands for the "make" namespace:
make:cast Create a new custom Eloquent cast class
make:channel Create a new channel class
make:class Create a new class
make:command Create a new Artisan command
make:component Create a new view component class
make:controller Create a new controller class
make:enum Create a new enum
make:event Create a new event class
make:listener Create a new event listener class
make:mail Create a new email class
make:middleware Create a new HTTP middleware class
make:migration Create a new migration file
make:model Create a new Eloquent model class
make:request Create a new form request class
make:resource Create a new resource
make:rule Create a new validation rule
make:scope Create a new scope class
make:seeder Create a new seeder class
make:test Create a new test class
make:trait Create a new trait
make:view Create a new view
Research
Laravel
β― php artisan make:controller
β What should the controller be named? βββββββββββββββββββββββββ
β CoolControler β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Which type of controller would you like? βββββββββββββββββββββ
β API β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β What model should this api controller be for? (Optional) βββββ
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
INFO Controller [app/Http/Controllers/CoolControler.php] created successfully.
Research
Laravel
stubs/
βββ cast.inbound.stub
βββ cast.stub
βββ class.invokable.stub
βββ class.stub
βββ console.stub
βββ controller.stub
βββ ...
βββ view-component.stub
<?php
namespace {{ namespace }};
class {{ class }}
{
/**
* Create a new class instance.
*/
public function __construct()
{
//
}
}
Research
Symfony
.
βββ bin
βββ composer.json
βββ composer.lock
βββ config
βββ public
βββ src
βββ symfony.lock
βββ var
βββ vendor
Research
Maker Bundle
Symfony
β php bin/console make
Symfony 7.1.9 (env: dev, debug: true)
Usage:
command [options] [arguments]
Available commands for the "make" namespace:
make:auth Create a Guard authenticator of different flavors
make:command Create a new console command class
make:controller Create a new controller class
make:crud Create CRUD for Doctrine entity class
make:entity Create or update a Doctrine entity class, and optionally an API Platform resource
make:fixtures Create a new class to load Doctrine fixtures
make:form Create a new form class
make:listener [make:subscriber] Creates a new event subscriber class or a new event listener class
make:message Create a new message and handler
make:migration Create a new migration based on database changes
make:schedule Create a scheduler component
make:subscriber Creates a new event subscriber class or a new event listener class
make:test [make:unit-test|make:functional-test] Create a new test class
make:unit-test Create a new test class
make:user Create a new security user class
make:validator Create a new validator and constraint class
make:voter Create a new security voter class
make:webhook Create a new Webhook
Research
Symfony
β php bin/console make:controller
Choose a name for your controller class (e.g. GentleKangarooController):
> CoolController
created: src/Controller/CoolController.php
Success!
Next: Open your new controller class and add some pages!
Research
Symfony
<?= "<?php\n" ?>
namespace <?= $class_data->getNamespace(); ?>;
<?= $class_data->getUseStatements(); ?>
<?= $class_data->getClassDeclaration(); ?>
{
<?= $generator->generateRouteForControllerMethod($route_path, $route_name); ?>
public function <?= $method_name ?>(): <?php if ($with_template) { ?>Response<?php } else { ?>JsonResponse<?php } ?>
{
<?php if ($with_template) { ?>
return $this->render('<?= $template_name ?>', [
'controller_name' => '<?= $class_data->getClassName() ?>',
]);
<?php } else { ?>
return $this->json([
'message' => 'Welcome to your new controller!',
'path' => '<?= $relative_path; ?>',
]);
<?php } ?>
}
}
src/Resources/skeleton/controller/
βββ Controller.tpl.php
βββ twig_template.tpl.php
Research
ππ‘
Crafter
Crafter
β crafter
Crafter magic
Usage:
command [options] [arguments]
Available commands
craft Craft classes by defined config
generate Generate project by defined template
init Create crafter.neon file
Crafter
crafter generate
β What project template do you want to use? ββββββββββββββββββββ
β βΊ β Nella project β
β β Nette project β
β β Doctrine project (coming soon) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Where to create project (folder)? ββββββββββββββββββββββββββββ
β test β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Project
Crafter
composer install
make dev
open browser
Project
test/
βββ Makefile
βββ README.md
βββ app
β βββ Bootstrap.php
β βββ UI
β βββ @Templates
β β βββ @layout.latte
β βββ BasePresenter.php
β βββ Home
β βββ HomePresenter.php
β βββ Templates
β βββ default.latte
βββ composer.json
βββ config
β βββ config.neon
β βββ local.neon.example
βββ phpstan.neon
βββ ruleset.xml
βββ var
β βββ log
β βββ tmp
βββ www
βββ index.php
Crafter
crafter generate
β What project template do you want to use? ββββββββββββββββββββ
β β Nella project β
β βΊ β Nette project β
β β Doctrine project (coming soon) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Where to create project (folder)? ββββββββββββββββββββββββββββ
β test β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Project
Craft
β― crafter craft
β What data structure do you want to craft? ββββββββββββββββββββ
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Crafter
β
Crafter
Config
β crafter init
β What application directory do you want to use? βββββββββββββββ
β src β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β What root namespace do you want to use? ββββββββββββββββββββββ
β App β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β What preset do you want to use? ββββββββββββββββββββββββββββββ
β nette web application β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Do you want to data structure example? βββββββββββββββββββββββ
β Yes example β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
[OK] crafter.neon file has been created
Crafter
# crafter.neon
version: 1
dir: src
namespace: App
preset: nette
data:
user:
fields:
username: {type: string}
email: {type: string}
Config
Craft
# crafter.neon
version: 1
dir: src
namespace: App
preset: nette
data:
user:
fields:
username: {type: string}
email: {type: string}
.
βββ crafter.neon
βββ src
βββ UI
βββ User
βββ Templates
β βββ default.latte
βββ UserPresenter.php
β crafter craft -k user
Crafter
Crafter
Craft
# crafter.neon
version: 1
dir: src
namespace: App
preset: nette
data:
user:
fields:
username: {type: string}
email: {type: string}
.
βββ crafter.neon
βββ src
βββ UI
βββ User
βββ Templates
β βββ default.latte
βββ UserPresenter.php
β crafter craft -k user
# preset=nette
crafters:
presenter:
input: '%cwd%/templates/presenter/presenter.latte'
output: '{$namespace}/UI/{$name|firstUpper}\{$name|firstUpper}Presenter.php'
presenter_template:
input: '%cwd%/templates/presenter/template.latte'
output: 'UI/{$name|firstUpper}/Templates/default.latte'
Craft
# crafter.neon
version: 1
dir: src
namespace: App
preset: nette
data:
user:
fields:
username: {type: string}
email: {type: string}
.
βββ crafter.neon
βββ src
βββ UI
βββ User
βββ Templates
β βββ default.latte
βββ UserPresenter.php
β crafter craft -k user
# preset=nette
crafters:
presenter:
input: '%cwd%/templates/presenter/presenter.latte'
output: '{$namespace}/UI/{$name|firstUpper}\{$name|firstUpper}Presenter.php'
presenter_template:
input: '%cwd%/templates/presenter/template.latte'
output: 'UI/{$name|firstUpper}/Templates/default.latte'
Overtemplating
Crafter
Craft
# crafter.neon
version: 1
dir: src
namespace: App
preset: nette
data:
user:
fields:
username: {type: string}
email: {type: string}
# preset=nette
crafters:
presenter:
input: '%cwd%/templates/presenter/presenter.latte'
output: '{$namespace}/UI/{$name|firstUpper}\{$name|firstUpper}Presenter.php'
presenter_template:
input: '%cwd%/templates/presenter/template.latte'
output: 'UI/{$name|firstUpper}/Templates/default.latte'
# presenter.latte
<?php declare(strict_types = 1);
namespace {$ctx->class->namespace};
use {$ctx->class->rootNamespace}\UI\BasePresenter;
class {$ctx->class->className} extends BasePresenter
{
}
Crafter
# UserPresenter.php
<?php declare(strict_types = 1);
namespace MyApp\UI\User;
use MyApp\UI\BasePresenter;
class UserPresenter extends BasePresenter
{
}
Craft
# crafter.neon
version: 1
dir: src
namespace: App
preset: nette
data:
user:
fields:
username: {type: string}
email: {type: string}
# preset=nette
crafters:
presenter:
input: '%cwd%/templates/presenter/presenter.latte'
output: '{$namespace}/UI/{$name|firstUpper}\{$name|firstUpper}Presenter.php'
presenter_template:
input: '%cwd%/templates/presenter/template.latte'
output: 'UI/{$name|firstUpper}/Templates/default.latte'
# default.latte
{block #content}
<div>
Hello {{=date('d.m.Y')}}!
</div>
Crafter
{block #content}
<div>
Hello 30.11.2024!
</div>
Crafter
Craft
# crafter.neon
version: 1
dir: app
namespace: App
preset: fx
data:
user:
fields:
username: {type: string}
email: {type: string}
app
βββ Api
β βββ User
β βββ Create
β β βββ CreateUserController.php
β β βββ CreateUserRequest.php
β β βββ CreateUserRequestBody.php
β β βββ CreateUserResponse.php
β βββ Delete
β β βββ DeleteUserController.php
β β βββ DeleteUserRequest.php
β β βββ DeleteUserResponse.php
β βββ Get
β β βββ GetUserController.php
β β βββ GetUserRequest.php
β β βββ GetUserResponse.php
β βββ List
β β βββ ListUserController.php
β β βββ ListUserFilter.php
β β βββ ListUserRequest.php
β β βββ ListUserResponse.php
β βββ Update
β βββ UpdateUserController.php
β βββ UpdateUserRequest.php
β βββ UpdateUserRequestBody.php
β βββ UpdateUserResponse.php
βββ Domain
βββ User
βββ CreateUserCommand.php
βββ CreateUserHandler.php
βββ Database
β βββ User.php
β βββ UserRepository.php
βββ DeleteUserCommand.php
βββ DeleteUserHandler.php
βββ GetUserCommand.php
βββ GetUserHandler.php
βββ ListUserCommand.php
βββ ListUserHandler.php
βββ UpdateUserCommand.php
βββ UpdateUserHandler.php
<?php
declare(strict_types=1);
namespace App\Domain\User;
readonly class CreateUserCommand
{
public function __construct(
public string $username,
public string $email,
) {
}
}
# Local
composer require contributte/crafter
# Global binary
composer global require contributte/crafter
# PHAR
curl github.com -o crafter.phar
Generate project
Generate classes
Custom templates
Configure via NEON
Templating via Latte
Framework independent
Recap
Recap
I do not like...
creating new project
creating CRUD
creating something again
Generate project
Generate classes
Custom templates
Configure via NEON
Templating via Latte
Framework independent
Recap + AI
Recap + AI
crafter craft --witch
crafter craft --witch --ui
crafter craft --ui
Time to selfie π·
Thank you!
@xf3l1x
f3l1x.io
By Milan Felix Ε ulc
π¦ Package maker β’ π· Architect ModernTV β’ π PHP enthusiast β’ πΏ Multimedia engineer β’ π¨βπ©βπ§βπ¦ Father β’ βοΈ Coffee-based