├── .env.dist ├── .gitignore ├── assets └── .gitignore ├── bin ├── console └── phpunit ├── composer.json ├── composer.lock ├── config ├── bundles.php ├── packages │ ├── dev │ │ ├── easy_log_handler.yaml │ │ ├── monolog.yaml │ │ ├── routing.yaml │ │ ├── swiftmailer.yaml │ │ └── web_profiler.yaml │ ├── doctrine.yaml │ ├── doctrine_migrations.yaml │ ├── fos_rest.yaml │ ├── framework.yaml │ ├── prod │ │ ├── doctrine.yaml │ │ └── monolog.yaml │ ├── routing.yaml │ ├── security.yaml │ ├── swiftmailer.yaml │ ├── test │ │ ├── framework.yaml │ │ ├── monolog.yaml │ │ ├── swiftmailer.yaml │ │ └── web_profiler.yaml │ ├── translation.yaml │ └── twig.yaml ├── routes.yaml ├── routes │ ├── annotations.yaml │ └── dev │ │ ├── twig.yaml │ │ └── web_profiler.yaml ├── services.yaml └── services_test.yaml ├── package.json ├── phpunit.xml.dist ├── public └── index.php ├── readme.txt ├── src ├── Application │ ├── DTO │ │ ├── ArticleAssembler.php │ │ └── ArticleDTO.php │ └── Service │ │ ├── .gitignore │ │ └── ArticleService.php ├── Domain │ └── Model │ │ ├── .gitignore │ │ └── Article │ │ ├── Article.php │ │ └── ArticleRepositoryInterface.php ├── Infrastructure │ ├── Http │ │ ├── Rest │ │ │ └── Controller │ │ │ │ ├── .gitignore │ │ │ │ └── ArticleController.php │ │ └── Web │ │ │ └── Controller │ │ │ └── .gitignore │ ├── Migrations │ │ └── .gitignore │ └── Repository │ │ ├── .gitignore │ │ └── ArticleRepository.php └── Kernel.php ├── symfony.lock ├── templates └── base.html.twig ├── tests └── .gitignore ├── translations └── .gitignore └── webpack.config.js /.env.dist: -------------------------------------------------------------------------------- 1 | # This file is a "template" of which env vars need to be defined for your application 2 | # Copy this file to .env file for development, create environment variables when deploying to production 3 | # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration 4 | 5 | ###> symfony/framework-bundle ### 6 | APP_ENV=dev 7 | APP_SECRET=dcec9205a79267e18a6a65fb24ce97e0 8 | #TRUSTED_PROXIES=127.0.0.1,127.0.0.2 9 | #TRUSTED_HOSTS=localhost,example.com 10 | ###< symfony/framework-bundle ### 11 | 12 | ###> symfony/swiftmailer-bundle ### 13 | # For Gmail as a transport, use: "gmail://username:password@localhost" 14 | # For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode=" 15 | # Delivery is disabled by default via "null://localhost" 16 | MAILER_URL=null://localhost 17 | ###< symfony/swiftmailer-bundle ### 18 | 19 | ###> doctrine/doctrine-bundle ### 20 | # Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url 21 | # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" 22 | # Configure your db driver and server_version in config/packages/doctrine.yaml 23 | DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name 24 | ###< doctrine/doctrine-bundle ### 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ###> symfony/framework-bundle ### 3 | /.env 4 | /public/bundles/ 5 | /var/ 6 | /vendor/ 7 | ###< symfony/framework-bundle ### 8 | 9 | ###> symfony/webpack-encore-pack ### 10 | /node_modules/ 11 | /public/build/ 12 | ###< symfony/webpack-encore-pack ### 13 | 14 | ###> symfony/phpunit-bridge ### 15 | .phpunit 16 | /phpunit.xml 17 | ###< symfony/phpunit-bridge ### 18 | 19 | ###> symfony/web-server-bundle ### 20 | /.web-server-pid 21 | ###< symfony/web-server-bundle ### 22 | .idea/ 23 | phpdocker/ 24 | docker-compose.yml 25 | -------------------------------------------------------------------------------- /assets/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/assets/.gitignore -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | load(__DIR__.'/../.env'); 23 | } 24 | 25 | $input = new ArgvInput(); 26 | $env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev', true); 27 | $debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)) && !$input->hasParameterOption('--no-debug', true); 28 | 29 | if ($debug) { 30 | umask(0000); 31 | 32 | if (class_exists(Debug::class)) { 33 | Debug::enable(); 34 | } 35 | } 36 | 37 | $kernel = new Kernel($env, $debug); 38 | $application = new Application($kernel); 39 | $application->run($input); 40 | -------------------------------------------------------------------------------- /bin/phpunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | ['all' => true], 5 | Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true], 6 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], 7 | Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true], 8 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], 9 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], 10 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], 11 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], 12 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], 13 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], 14 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], 15 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], 16 | Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true], 17 | FOS\RestBundle\FOSRestBundle::class => ['all' => true], 18 | ]; 19 | -------------------------------------------------------------------------------- /config/packages/dev/easy_log_handler.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | EasyCorp\EasyLog\EasyLogHandler: 3 | public: false 4 | arguments: ['%kernel.logs_dir%/%kernel.environment%.log'] 5 | 6 | #// FIXME: How to add this configuration automatically without messing up with the monolog configuration? 7 | #monolog: 8 | # handlers: 9 | # buffered: 10 | # type: buffer 11 | # handler: easylog 12 | # channels: ['!event'] 13 | # level: debug 14 | # easylog: 15 | # type: service 16 | # id: EasyCorp\EasyLog\EasyLogHandler 17 | -------------------------------------------------------------------------------- /config/packages/dev/monolog.yaml: -------------------------------------------------------------------------------- 1 | monolog: 2 | handlers: 3 | main: 4 | type: stream 5 | path: "%kernel.logs_dir%/%kernel.environment%.log" 6 | level: debug 7 | channels: ["!event"] 8 | # uncomment to get logging in your browser 9 | # you may have to allow bigger header sizes in your Web server configuration 10 | #firephp: 11 | # type: firephp 12 | # level: info 13 | #chromephp: 14 | # type: chromephp 15 | # level: info 16 | console: 17 | type: console 18 | process_psr_3_messages: false 19 | channels: ["!event", "!doctrine", "!console"] 20 | -------------------------------------------------------------------------------- /config/packages/dev/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: true 4 | -------------------------------------------------------------------------------- /config/packages/dev/swiftmailer.yaml: -------------------------------------------------------------------------------- 1 | # See https://symfony.com/doc/current/email/dev_environment.html 2 | swiftmailer: 3 | # send all emails to a specific address 4 | #delivery_addresses: ['me@example.com'] 5 | -------------------------------------------------------------------------------- /config/packages/dev/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler: 2 | toolbar: true 3 | intercept_redirects: false 4 | 5 | framework: 6 | profiler: { only_exceptions: false } 7 | -------------------------------------------------------------------------------- /config/packages/doctrine.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Adds a fallback DATABASE_URL if the env var is not set. 3 | # This allows you to run cache:warmup even if your 4 | # environment variables are not available yet. 5 | # You should not need to change this value. 6 | env(DATABASE_URL): '' 7 | 8 | doctrine: 9 | dbal: 10 | # configure these for your database server 11 | driver: 'pdo_mysql' 12 | server_version: '5.7' 13 | charset: utf8mb4 14 | default_table_options: 15 | charset: utf8mb4 16 | collate: utf8mb4_unicode_ci 17 | 18 | # With Symfony 3.3, remove the `resolve:` prefix 19 | url: '%env(resolve:DATABASE_URL)%' 20 | orm: 21 | auto_generate_proxy_classes: '%kernel.debug%' 22 | naming_strategy: doctrine.orm.naming_strategy.underscore 23 | auto_mapping: true 24 | mappings: 25 | Domain: 26 | is_bundle: false 27 | type: annotation 28 | dir: '%kernel.project_dir%/src/Domain/Model' 29 | prefix: 'App\Domain\Model' 30 | alias: Domain\Model 31 | -------------------------------------------------------------------------------- /config/packages/doctrine_migrations.yaml: -------------------------------------------------------------------------------- 1 | doctrine_migrations: 2 | dir_name: '%kernel.project_dir%/src/Infrastructure/Migrations' 3 | # namespace is arbitrary but should be different from App\Migrations 4 | # as migrations classes should NOT be autoloaded 5 | namespace: DoctrineMigrations 6 | -------------------------------------------------------------------------------- /config/packages/fos_rest.yaml: -------------------------------------------------------------------------------- 1 | fos_rest: 2 | view: 3 | view_response_listener: true 4 | exception: 5 | exception_controller: 'fos_rest.exception.controller:showAction' 6 | codes: 7 | Doctrine\ORM\EntityNotFoundException: 404 8 | format_listener: 9 | rules: 10 | - { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json ] } 11 | body_converter: 12 | enabled: true -------------------------------------------------------------------------------- /config/packages/framework.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | secret: '%env(APP_SECRET)%' 3 | #default_locale: en 4 | #csrf_protection: true 5 | #http_method_override: true 6 | 7 | # Enables session support. Note that the session will ONLY be started if you read or write from it. 8 | # Remove or comment this section to explicitly disable session support. 9 | session: 10 | handler_id: ~ 11 | 12 | #esi: true 13 | #fragments: true 14 | php_errors: 15 | log: true 16 | 17 | cache: 18 | # Put the unique name of your app here: the prefix seed 19 | # is used to compute stable namespaces for cache keys. 20 | #prefix_seed: your_vendor_name/app_name 21 | 22 | # The app cache caches to the filesystem by default. 23 | # Other options include: 24 | 25 | # Redis 26 | #app: cache.adapter.redis 27 | #default_redis_provider: redis://localhost 28 | 29 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) 30 | #app: cache.adapter.apcu 31 | -------------------------------------------------------------------------------- /config/packages/prod/doctrine.yaml: -------------------------------------------------------------------------------- 1 | doctrine: 2 | orm: 3 | metadata_cache_driver: 4 | type: service 5 | id: doctrine.system_cache_provider 6 | query_cache_driver: 7 | type: service 8 | id: doctrine.system_cache_provider 9 | result_cache_driver: 10 | type: service 11 | id: doctrine.result_cache_provider 12 | 13 | services: 14 | doctrine.result_cache_provider: 15 | class: Symfony\Component\Cache\DoctrineProvider 16 | public: false 17 | arguments: 18 | - '@doctrine.result_cache_pool' 19 | doctrine.system_cache_provider: 20 | class: Symfony\Component\Cache\DoctrineProvider 21 | public: false 22 | arguments: 23 | - '@doctrine.system_cache_pool' 24 | 25 | framework: 26 | cache: 27 | pools: 28 | doctrine.result_cache_pool: 29 | adapter: cache.app 30 | doctrine.system_cache_pool: 31 | adapter: cache.system 32 | -------------------------------------------------------------------------------- /config/packages/prod/monolog.yaml: -------------------------------------------------------------------------------- 1 | monolog: 2 | handlers: 3 | main: 4 | type: fingers_crossed 5 | action_level: error 6 | handler: nested 7 | excluded_404s: 8 | # regex: exclude all 404 errors from the logs 9 | - ^/ 10 | nested: 11 | type: stream 12 | path: "%kernel.logs_dir%/%kernel.environment%.log" 13 | level: debug 14 | console: 15 | type: console 16 | process_psr_3_messages: false 17 | channels: ["!event", "!doctrine"] 18 | -------------------------------------------------------------------------------- /config/packages/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: ~ 4 | -------------------------------------------------------------------------------- /config/packages/security.yaml: -------------------------------------------------------------------------------- 1 | security: 2 | # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers 3 | providers: 4 | in_memory: { memory: ~ } 5 | firewalls: 6 | dev: 7 | pattern: ^/(_(profiler|wdt)|css|images|js)/ 8 | security: false 9 | main: 10 | anonymous: true 11 | 12 | # activate different ways to authenticate 13 | 14 | # http_basic: true 15 | # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate 16 | 17 | # form_login: true 18 | # https://symfony.com/doc/current/security/form_login_setup.html 19 | 20 | # Easy way to control access for large sections of your site 21 | # Note: Only the *first* access control that matches will be used 22 | access_control: 23 | # - { path: ^/admin, roles: ROLE_ADMIN } 24 | # - { path: ^/profile, roles: ROLE_USER } 25 | -------------------------------------------------------------------------------- /config/packages/swiftmailer.yaml: -------------------------------------------------------------------------------- 1 | swiftmailer: 2 | url: '%env(MAILER_URL)%' 3 | spool: { type: 'memory' } 4 | -------------------------------------------------------------------------------- /config/packages/test/framework.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | test: true 3 | session: 4 | storage_id: session.storage.mock_file 5 | -------------------------------------------------------------------------------- /config/packages/test/monolog.yaml: -------------------------------------------------------------------------------- 1 | monolog: 2 | handlers: 3 | main: 4 | type: stream 5 | path: "%kernel.logs_dir%/%kernel.environment%.log" 6 | level: debug 7 | channels: ["!event"] 8 | -------------------------------------------------------------------------------- /config/packages/test/swiftmailer.yaml: -------------------------------------------------------------------------------- 1 | swiftmailer: 2 | disable_delivery: true 3 | -------------------------------------------------------------------------------- /config/packages/test/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler: 2 | toolbar: false 3 | intercept_redirects: false 4 | 5 | framework: 6 | profiler: { collect: false } 7 | -------------------------------------------------------------------------------- /config/packages/translation.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | default_locale: '%locale%' 3 | translator: 4 | paths: 5 | - '%kernel.project_dir%/translations' 6 | fallbacks: 7 | - '%locale%' 8 | -------------------------------------------------------------------------------- /config/packages/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | paths: ['%kernel.project_dir%/templates'] 3 | debug: '%kernel.debug%' 4 | strict_variables: '%kernel.debug%' 5 | -------------------------------------------------------------------------------- /config/routes.yaml: -------------------------------------------------------------------------------- 1 | #index: 2 | # path: / 3 | # controller: App\Controller\DefaultController::index 4 | -------------------------------------------------------------------------------- /config/routes/annotations.yaml: -------------------------------------------------------------------------------- 1 | web_controller: 2 | resource: ../../src/Infrastructure/Http/Web/Controller/ 3 | type: annotation 4 | 5 | rest_controller: 6 | resource: ../../src/Infrastructure/Http/Rest/Controller/ 7 | type: annotation 8 | prefix: /api -------------------------------------------------------------------------------- /config/routes/dev/twig.yaml: -------------------------------------------------------------------------------- 1 | _errors: 2 | resource: '@TwigBundle/Resources/config/routing/errors.xml' 3 | prefix: /_error 4 | -------------------------------------------------------------------------------- /config/routes/dev/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler_wdt: 2 | resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' 3 | prefix: /_wdt 4 | 5 | web_profiler_profiler: 6 | resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' 7 | prefix: /_profiler 8 | -------------------------------------------------------------------------------- /config/services.yaml: -------------------------------------------------------------------------------- 1 | # Put parameters here that don't need to change on each machine where the app is deployed 2 | # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration 3 | parameters: 4 | locale: 'en' 5 | 6 | services: 7 | # default configuration for services in *this* file 8 | _defaults: 9 | autowire: true # Automatically injects dependencies in your services. 10 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. 11 | public: false # Allows optimizing the container by removing unused services; this also means 12 | # fetching services directly from the container via $container->get() won't work. 13 | # The best practice is to be explicit about your dependencies anyway. 14 | 15 | # makes classes in src/ available to be used as services 16 | # this creates a service per class whose id is the fully-qualified class name 17 | App\: 18 | resource: '../src/*' 19 | exclude: '../src/{Entity,Infrastructure/Migrations,Application/DTO/*DTO.php,Tests,Kernel.php}' 20 | 21 | # controllers are imported separately to make sure services can be injected 22 | # as action arguments even if you don't extend any base controller class 23 | App\Infrastructure\Http\Web\Controller\: 24 | resource: '../src/Infrastructure/Http/Web/Controller' 25 | tags: ['controller.service_arguments'] 26 | 27 | App\Infrastructure\Http\Rest\Controller\: 28 | resource: '../src/Infrastructure/Http/Rest/Controller' 29 | tags: ['controller.service_arguments'] 30 | # add more service definitions when explicit configuration is needed 31 | # please note that last definitions always *replace* previous ones 32 | -------------------------------------------------------------------------------- /config/services_test.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | 5 | # If you need to access services in a test, create an alias 6 | # and then fetch that alias from the container. As a convention, 7 | # aliases are prefixed with test. For example: 8 | # 9 | # test.App\Service\MyService: '@App\Service\MyService' 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@symfony/webpack-encore": "^0.17.0" 4 | }, 5 | "license": "UNLICENSED", 6 | "private": true, 7 | "scripts": { 8 | "dev-server": "encore dev-server", 9 | "dev": "encore dev", 10 | "watch": "encore dev --watch", 11 | "build": "encore production" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | tests/ 23 | 24 | 25 | 26 | 27 | 28 | ./src/ 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | load(__DIR__.'/../.env'); 16 | } 17 | 18 | $env = $_SERVER['APP_ENV'] ?? 'dev'; 19 | $debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)); 20 | 21 | if ($debug) { 22 | umask(0000); 23 | 24 | Debug::enable(); 25 | } 26 | 27 | if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) { 28 | Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); 29 | } 30 | 31 | if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) { 32 | Request::setTrustedHosts(explode(',', $trustedHosts)); 33 | } 34 | 35 | $kernel = new Kernel($env, $debug); 36 | $request = Request::createFromGlobals(); 37 | $response = $kernel->handle($request); 38 | $response->send(); 39 | $kernel->terminate($request, $response); 40 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | * Enter database credentials in env file 2 | * Run 'php bin/console doctrine:schema:create' -------------------------------------------------------------------------------- /src/Application/DTO/ArticleAssembler.php: -------------------------------------------------------------------------------- 1 | setContent($articleDTO->getContent()); 28 | $article->setTitle($articleDTO->getTitle()); 29 | 30 | return $article; 31 | } 32 | 33 | /** 34 | * @param Article $article 35 | * @param ArticleDTO $articleDTO 36 | * @return Article 37 | */ 38 | public function updateArticle(Article $article, ArticleDTO $articleDTO): Article 39 | { 40 | return $this->readDTO($articleDTO, $article); 41 | } 42 | 43 | /** 44 | * @param ArticleDTO $articleDTO 45 | * @return Article 46 | */ 47 | public function createArticle(ArticleDTO $articleDTO): Article 48 | { 49 | return $this->readDTO($articleDTO); 50 | } 51 | 52 | /** 53 | * @param Article $article 54 | * @return ArticleDTO 55 | */ 56 | public function writeDTO(Article $article) 57 | { 58 | return new ArticleDTO( 59 | $article->getTitle(), 60 | $article->getContent() 61 | ); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/Application/DTO/ArticleDTO.php: -------------------------------------------------------------------------------- 1 | title = $title; 30 | $this->content = $content; 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function getTitle(): string 37 | { 38 | return $this->title; 39 | } 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getContent(): string 45 | { 46 | return $this->content; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/Application/Service/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/src/Application/Service/.gitignore -------------------------------------------------------------------------------- /src/Application/Service/ArticleService.php: -------------------------------------------------------------------------------- 1 | articleRepository = $articleRepository; 39 | $this->articleAssembler = $articleAssembler; 40 | } 41 | 42 | /** 43 | * @param int $articleId 44 | * @return Article 45 | * @throws EntityNotFoundException 46 | */ 47 | public function getArticle(int $articleId): Article 48 | { 49 | $article = $this->articleRepository->findById($articleId); 50 | if (!$article) { 51 | throw new EntityNotFoundException('Article with id '.$articleId.' does not exist!'); 52 | } 53 | return $article; 54 | } 55 | 56 | /** 57 | * @return array|null 58 | */ 59 | public function getAllArticles(): ?array 60 | { 61 | return $this->articleRepository->findAll(); 62 | } 63 | 64 | /** 65 | * @param ArticleDTO $articleDTO 66 | * @return Article 67 | */ 68 | public function addArticle(ArticleDTO $articleDTO): Article 69 | { 70 | $article = $this->articleAssembler->createArticle($articleDTO); 71 | $this->articleRepository->save($article); 72 | 73 | return $article; 74 | } 75 | 76 | /** 77 | * @param int $articleId 78 | * @param ArticleDTO $articleDTO 79 | * @return Article 80 | * @throws EntityNotFoundException 81 | */ 82 | public function updateArticle(int $articleId, ArticleDTO $articleDTO): Article 83 | { 84 | $article = $this->articleRepository->findById($articleId); 85 | if (!$article) { 86 | throw new EntityNotFoundException('Article with id '.$articleId.' does not exist!'); 87 | } 88 | $article = $this->articleAssembler->updateArticle($article, $articleDTO); 89 | $this->articleRepository->save($article); 90 | 91 | return $article; 92 | } 93 | 94 | /** 95 | * @param int $articleId 96 | * @throws EntityNotFoundException 97 | */ 98 | public function deleteArticle(int $articleId): void 99 | { 100 | $article = $this->articleRepository->findById($articleId); 101 | if (!$article) { 102 | throw new EntityNotFoundException('Article with id '.$articleId.' does not exist!'); 103 | } 104 | 105 | $this->articleRepository->delete($article); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/Domain/Model/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/src/Domain/Model/.gitignore -------------------------------------------------------------------------------- /src/Domain/Model/Article/Article.php: -------------------------------------------------------------------------------- 1 | id; 41 | } 42 | 43 | /** 44 | * @param int $id 45 | */ 46 | public function setId(int $id): void 47 | { 48 | $this->id = $id; 49 | } 50 | 51 | /** 52 | * @return string 53 | */ 54 | public function getTitle(): string 55 | { 56 | return $this->title; 57 | } 58 | 59 | /** 60 | * @param string $title 61 | * @throws \InvalidArgumentException 62 | */ 63 | public function setTitle(string $title): void 64 | { 65 | if (\strlen($title) < 5) { 66 | throw new \InvalidArgumentException('Title needs to have 5 or more characters.'); 67 | } 68 | 69 | $this->title = $title; 70 | } 71 | 72 | /** 73 | * @return string 74 | */ 75 | public function getContent(): string 76 | { 77 | return $this->content; 78 | } 79 | 80 | /** 81 | * @param string $content 82 | */ 83 | public function setContent(string $content): void 84 | { 85 | $this->content = $content; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/Domain/Model/Article/ArticleRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | articleService = $articleService; 34 | } 35 | 36 | /** 37 | * Creates an Article resource 38 | * @Rest\Post("/articles") 39 | * @ParamConverter("articleDTO", converter="fos_rest.request_body") 40 | * @param ArticleDTO $articleDTO 41 | * @return View 42 | */ 43 | public function postArticle(ArticleDTO $articleDTO): View 44 | { 45 | $article = $this->articleService->addArticle($articleDTO); 46 | 47 | // In case our POST was a success we need to return a 201 HTTP CREATED response with the created object 48 | return View::create($article, Response::HTTP_CREATED); 49 | } 50 | 51 | /** 52 | * Retrieves an Article resource 53 | * @Rest\Get("/articles/{articleId}") 54 | * @param int $articleId 55 | * @return View 56 | * @throws \Doctrine\ORM\EntityNotFoundException 57 | */ 58 | public function getArticle(int $articleId): View 59 | { 60 | $article = $this->articleService->getArticle($articleId); 61 | 62 | // In case our GET was a success we need to return a 200 HTTP OK response with the request object 63 | return View::create($article, Response::HTTP_OK); 64 | } 65 | 66 | /** 67 | * Retrieves a collection of Article resource 68 | * @Rest\Get("/articles") 69 | * @return View 70 | */ 71 | public function getArticles(): View 72 | { 73 | $articles = $this->articleService->getAllArticles(); 74 | 75 | // In case our GET was a success we need to return a 200 HTTP OK response with the collection of article object 76 | return View::create($articles, Response::HTTP_OK); 77 | } 78 | 79 | /** 80 | * Replaces Article resource 81 | * @Rest\Put("/articles/{id}") 82 | * @ParamConverter("articleDTO", converter="fos_rest.request_body") 83 | * @param int $articleId 84 | * @param ArticleDTO $articleDTO 85 | * @return View 86 | * @throws \Doctrine\ORM\EntityNotFoundException 87 | */ 88 | public function putArticle(int $articleId, ArticleDTO $articleDTO): View 89 | { 90 | $article = $this->articleService->updateArticle($articleId, $articleDTO); 91 | 92 | // In case our PUT was a success we need to return a 200 HTTP OK response with the object as a result of PUT 93 | return View::create($article, Response::HTTP_OK); 94 | } 95 | 96 | /** 97 | * Removes the Article resource 98 | * @Rest\Delete("/articles/{articleId}") 99 | * @param int $articleId 100 | * @return View 101 | * @throws \Doctrine\ORM\EntityNotFoundException 102 | */ 103 | public function deleteArticle(int $articleId): View 104 | { 105 | $this->articleService->deleteArticle($articleId); 106 | 107 | // In case our DELETE was a success we need to return a 204 HTTP NO CONTENT response. The object is deleted. 108 | return View::create([], Response::HTTP_NO_CONTENT); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Infrastructure/Http/Web/Controller/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/src/Infrastructure/Http/Web/Controller/.gitignore -------------------------------------------------------------------------------- /src/Infrastructure/Migrations/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/src/Infrastructure/Migrations/.gitignore -------------------------------------------------------------------------------- /src/Infrastructure/Repository/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/src/Infrastructure/Repository/.gitignore -------------------------------------------------------------------------------- /src/Infrastructure/Repository/ArticleRepository.php: -------------------------------------------------------------------------------- 1 | entityManager = $entityManager; 34 | $this->objectRepository = $this->entityManager->getRepository(Article::class); 35 | } 36 | 37 | /** 38 | * @param int $articleId 39 | * @return Article 40 | */ 41 | public function findById(int $articleId): ?Article 42 | { 43 | return $this->objectRepository->find($articleId); 44 | } 45 | 46 | /** 47 | * @return array 48 | */ 49 | public function findAll(): array 50 | { 51 | return $this->objectRepository->findAll(); 52 | } 53 | 54 | /** 55 | * @param Article $article 56 | */ 57 | public function save(Article $article): void 58 | { 59 | $this->entityManager->persist($article); 60 | $this->entityManager->flush(); 61 | } 62 | 63 | /** 64 | * @param Article $article 65 | */ 66 | public function delete(Article $article): void 67 | { 68 | $this->entityManager->remove($article); 69 | $this->entityManager->flush(); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/Kernel.php: -------------------------------------------------------------------------------- 1 | getProjectDir().'/var/cache/'.$this->environment; 21 | } 22 | 23 | public function getLogDir() 24 | { 25 | return $this->getProjectDir().'/var/log'; 26 | } 27 | 28 | public function registerBundles() 29 | { 30 | $contents = require $this->getProjectDir().'/config/bundles.php'; 31 | foreach ($contents as $class => $envs) { 32 | if (isset($envs['all']) || isset($envs[$this->environment])) { 33 | yield new $class(); 34 | } 35 | } 36 | } 37 | 38 | protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) 39 | { 40 | $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); 41 | // Feel free to remove the "container.autowiring.strict_mode" parameter 42 | // if you are using symfony/dependency-injection 4.0+ as it's the default behavior 43 | $container->setParameter('container.autowiring.strict_mode', true); 44 | $container->setParameter('container.dumper.inline_class_loader', true); 45 | $confDir = $this->getProjectDir().'/config'; 46 | 47 | $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); 48 | $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob'); 49 | $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); 50 | $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); 51 | } 52 | 53 | protected function configureRoutes(RouteCollectionBuilder $routes) 54 | { 55 | $confDir = $this->getProjectDir().'/config'; 56 | 57 | $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); 58 | $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob'); 59 | $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /symfony.lock: -------------------------------------------------------------------------------- 1 | { 2 | "doctrine/annotations": { 3 | "version": "1.0", 4 | "recipe": { 5 | "repo": "github.com/symfony/recipes", 6 | "branch": "master", 7 | "version": "1.0", 8 | "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672" 9 | } 10 | }, 11 | "doctrine/cache": { 12 | "version": "v1.7.1" 13 | }, 14 | "doctrine/collections": { 15 | "version": "v1.5.0" 16 | }, 17 | "doctrine/common": { 18 | "version": "v2.8.1" 19 | }, 20 | "doctrine/dbal": { 21 | "version": "v2.6.3" 22 | }, 23 | "doctrine/doctrine-bundle": { 24 | "version": "1.6", 25 | "recipe": { 26 | "repo": "github.com/symfony/recipes", 27 | "branch": "master", 28 | "version": "1.6", 29 | "ref": "c745b67e4dec2771d4d57a60efd224faf445c929" 30 | } 31 | }, 32 | "doctrine/doctrine-cache-bundle": { 33 | "version": "1.3.2" 34 | }, 35 | "doctrine/doctrine-migrations-bundle": { 36 | "version": "1.2", 37 | "recipe": { 38 | "repo": "github.com/symfony/recipes", 39 | "branch": "master", 40 | "version": "1.2", 41 | "ref": "c1431086fec31f17fbcfe6d6d7e92059458facc1" 42 | } 43 | }, 44 | "doctrine/inflector": { 45 | "version": "v1.3.0" 46 | }, 47 | "doctrine/instantiator": { 48 | "version": "1.1.0" 49 | }, 50 | "doctrine/lexer": { 51 | "version": "v1.0.1" 52 | }, 53 | "doctrine/migrations": { 54 | "version": "v1.6.2" 55 | }, 56 | "doctrine/orm": { 57 | "version": "v2.6.1" 58 | }, 59 | "easycorp/easy-log-handler": { 60 | "version": "1.0", 61 | "recipe": { 62 | "repo": "github.com/symfony/recipes", 63 | "branch": "master", 64 | "version": "1.0", 65 | "ref": "70062abc2cd58794d2a90274502f81b55cd9951b" 66 | } 67 | }, 68 | "egulias/email-validator": { 69 | "version": "2.1.3" 70 | }, 71 | "fig/link-util": { 72 | "version": "1.0.0" 73 | }, 74 | "friendsofsymfony/rest-bundle": { 75 | "version": "2.2", 76 | "recipe": { 77 | "repo": "github.com/symfony/recipes-contrib", 78 | "branch": "master", 79 | "version": "2.2", 80 | "ref": "258300d52be6ad59b32a888d5ddafbf9638540ff" 81 | } 82 | }, 83 | "jdorn/sql-formatter": { 84 | "version": "v1.2.17" 85 | }, 86 | "monolog/monolog": { 87 | "version": "1.23.0" 88 | }, 89 | "nikic/php-parser": { 90 | "version": "v4.0.0" 91 | }, 92 | "ocramius/proxy-manager": { 93 | "version": "2.2.0" 94 | }, 95 | "phpdocumentor/reflection-common": { 96 | "version": "1.0.1" 97 | }, 98 | "phpdocumentor/reflection-docblock": { 99 | "version": "4.3.0" 100 | }, 101 | "phpdocumentor/type-resolver": { 102 | "version": "0.4.0" 103 | }, 104 | "psr/cache": { 105 | "version": "1.0.1" 106 | }, 107 | "psr/container": { 108 | "version": "1.0.0" 109 | }, 110 | "psr/link": { 111 | "version": "1.0.0" 112 | }, 113 | "psr/log": { 114 | "version": "1.0.2" 115 | }, 116 | "psr/simple-cache": { 117 | "version": "1.0.1" 118 | }, 119 | "sensio/framework-extra-bundle": { 120 | "version": "4.0", 121 | "recipe": { 122 | "repo": "github.com/symfony/recipes", 123 | "branch": "master", 124 | "version": "4.0", 125 | "ref": "aaddfdf43cdecd4cf91f992052d76c2cadc04543" 126 | } 127 | }, 128 | "swiftmailer/swiftmailer": { 129 | "version": "v6.0.2" 130 | }, 131 | "symfony/asset": { 132 | "version": "v4.0.6" 133 | }, 134 | "symfony/browser-kit": { 135 | "version": "v4.0.6" 136 | }, 137 | "symfony/cache": { 138 | "version": "v4.0.6" 139 | }, 140 | "symfony/config": { 141 | "version": "v4.0.6" 142 | }, 143 | "symfony/console": { 144 | "version": "3.3", 145 | "recipe": { 146 | "repo": "github.com/symfony/recipes", 147 | "branch": "master", 148 | "version": "3.3", 149 | "ref": "e3868d2f4a5104f19f844fe551099a00c6562527" 150 | } 151 | }, 152 | "symfony/css-selector": { 153 | "version": "v4.0.6" 154 | }, 155 | "symfony/debug": { 156 | "version": "v4.0.6" 157 | }, 158 | "symfony/debug-bundle": { 159 | "version": "3.3", 160 | "recipe": { 161 | "repo": "github.com/symfony/recipes", 162 | "branch": "master", 163 | "version": "3.3", 164 | "ref": "71d29aaf710fd59cd3abff2b1ade907ed73103c6" 165 | } 166 | }, 167 | "symfony/debug-pack": { 168 | "version": "v1.0.4" 169 | }, 170 | "symfony/dependency-injection": { 171 | "version": "v4.0.6" 172 | }, 173 | "symfony/doctrine-bridge": { 174 | "version": "v4.0.6" 175 | }, 176 | "symfony/dom-crawler": { 177 | "version": "v4.0.6" 178 | }, 179 | "symfony/dotenv": { 180 | "version": "v4.0.6" 181 | }, 182 | "symfony/event-dispatcher": { 183 | "version": "v4.0.6" 184 | }, 185 | "symfony/expression-language": { 186 | "version": "v4.0.6" 187 | }, 188 | "symfony/filesystem": { 189 | "version": "v4.0.6" 190 | }, 191 | "symfony/finder": { 192 | "version": "v4.0.6" 193 | }, 194 | "symfony/flex": { 195 | "version": "1.0", 196 | "recipe": { 197 | "repo": "github.com/symfony/recipes", 198 | "branch": "master", 199 | "version": "1.0", 200 | "ref": "cc1afd81841db36fbef982fe56b48ade6716fac4" 201 | } 202 | }, 203 | "symfony/form": { 204 | "version": "v4.0.6" 205 | }, 206 | "symfony/framework-bundle": { 207 | "version": "3.3", 208 | "recipe": { 209 | "repo": "github.com/symfony/recipes", 210 | "branch": "master", 211 | "version": "3.3", 212 | "ref": "8a2f7fa50a528f0aad1d7a87ae3730c981b367ce" 213 | } 214 | }, 215 | "symfony/http-foundation": { 216 | "version": "v4.0.6" 217 | }, 218 | "symfony/http-kernel": { 219 | "version": "v4.0.6" 220 | }, 221 | "symfony/inflector": { 222 | "version": "v4.0.6" 223 | }, 224 | "symfony/intl": { 225 | "version": "v4.0.6" 226 | }, 227 | "symfony/lts": { 228 | "version": "4-dev" 229 | }, 230 | "symfony/maker-bundle": { 231 | "version": "1.0", 232 | "recipe": { 233 | "repo": "github.com/symfony/recipes", 234 | "branch": "master", 235 | "version": "1.0", 236 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" 237 | } 238 | }, 239 | "symfony/monolog-bridge": { 240 | "version": "v4.0.6" 241 | }, 242 | "symfony/monolog-bundle": { 243 | "version": "3.1", 244 | "recipe": { 245 | "repo": "github.com/symfony/recipes", 246 | "branch": "master", 247 | "version": "3.1", 248 | "ref": "371d1a2b69984710646b09a1182ef1d4308c904f" 249 | } 250 | }, 251 | "symfony/options-resolver": { 252 | "version": "v4.0.6" 253 | }, 254 | "symfony/orm-pack": { 255 | "version": "v1.0.5" 256 | }, 257 | "symfony/phpunit-bridge": { 258 | "version": "3.3", 259 | "recipe": { 260 | "repo": "github.com/symfony/recipes", 261 | "branch": "master", 262 | "version": "3.3", 263 | "ref": "179470cb6492db92dffee208cfdb436f175c93b4" 264 | } 265 | }, 266 | "symfony/polyfill-intl-icu": { 267 | "version": "v1.7.0" 268 | }, 269 | "symfony/polyfill-mbstring": { 270 | "version": "v1.7.0" 271 | }, 272 | "symfony/polyfill-php72": { 273 | "version": "v1.7.0" 274 | }, 275 | "symfony/process": { 276 | "version": "v4.0.6" 277 | }, 278 | "symfony/profiler-pack": { 279 | "version": "v1.0.3" 280 | }, 281 | "symfony/property-access": { 282 | "version": "v4.0.6" 283 | }, 284 | "symfony/property-info": { 285 | "version": "v4.0.6" 286 | }, 287 | "symfony/routing": { 288 | "version": "4.0", 289 | "recipe": { 290 | "repo": "github.com/symfony/recipes", 291 | "branch": "master", 292 | "version": "4.0", 293 | "ref": "cda8b550123383d25827705d05a42acf6819fe4e" 294 | } 295 | }, 296 | "symfony/security": { 297 | "version": "v4.0.6" 298 | }, 299 | "symfony/security-bundle": { 300 | "version": "3.3", 301 | "recipe": { 302 | "repo": "github.com/symfony/recipes", 303 | "branch": "master", 304 | "version": "3.3", 305 | "ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527" 306 | } 307 | }, 308 | "symfony/serializer": { 309 | "version": "v4.0.6" 310 | }, 311 | "symfony/serializer-pack": { 312 | "version": "v1.0.1" 313 | }, 314 | "symfony/stopwatch": { 315 | "version": "v4.0.6" 316 | }, 317 | "symfony/swiftmailer-bundle": { 318 | "version": "2.5", 319 | "recipe": { 320 | "repo": "github.com/symfony/recipes", 321 | "branch": "master", 322 | "version": "2.5", 323 | "ref": "3db029c03e452b4a23f7fc45cec7c922c2247eb8" 324 | } 325 | }, 326 | "symfony/templating": { 327 | "version": "v4.0.6" 328 | }, 329 | "symfony/translation": { 330 | "version": "3.3", 331 | "recipe": { 332 | "repo": "github.com/symfony/recipes", 333 | "branch": "master", 334 | "version": "3.3", 335 | "ref": "6bcd6c570c017ea6ae5a7a6a027c929fd3542cd8" 336 | } 337 | }, 338 | "symfony/twig-bridge": { 339 | "version": "v4.0.6" 340 | }, 341 | "symfony/twig-bundle": { 342 | "version": "3.3", 343 | "recipe": { 344 | "repo": "github.com/symfony/recipes", 345 | "branch": "master", 346 | "version": "3.3", 347 | "ref": "f75ac166398e107796ca94cc57fa1edaa06ec47f" 348 | } 349 | }, 350 | "symfony/validator": { 351 | "version": "v4.0.6" 352 | }, 353 | "symfony/var-dumper": { 354 | "version": "v4.0.6" 355 | }, 356 | "symfony/web-link": { 357 | "version": "v4.0.6" 358 | }, 359 | "symfony/web-profiler-bundle": { 360 | "version": "3.3", 361 | "recipe": { 362 | "repo": "github.com/symfony/recipes", 363 | "branch": "master", 364 | "version": "3.3", 365 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6" 366 | } 367 | }, 368 | "symfony/web-server-bundle": { 369 | "version": "3.3", 370 | "recipe": { 371 | "repo": "github.com/symfony/recipes", 372 | "branch": "master", 373 | "version": "3.3", 374 | "ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a" 375 | } 376 | }, 377 | "symfony/webpack-encore-pack": { 378 | "version": "1.0", 379 | "recipe": { 380 | "repo": "github.com/symfony/recipes", 381 | "branch": "master", 382 | "version": "1.0", 383 | "ref": "db7185a4e6193a81c70d51e8b8ac0e656fea7ad3" 384 | } 385 | }, 386 | "symfony/yaml": { 387 | "version": "v4.0.6" 388 | }, 389 | "twig/twig": { 390 | "version": "v2.4.7" 391 | }, 392 | "webmozart/assert": { 393 | "version": "1.3.0" 394 | }, 395 | "willdurand/jsonp-callback-validator": { 396 | "version": "v1.1.0" 397 | }, 398 | "willdurand/negotiation": { 399 | "version": "v2.3.1" 400 | }, 401 | "zendframework/zend-code": { 402 | "version": "3.3.0" 403 | }, 404 | "zendframework/zend-eventmanager": { 405 | "version": "3.2.0" 406 | } 407 | } 408 | -------------------------------------------------------------------------------- /templates/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Welcome!{% endblock %} 6 | {% block stylesheets %}{% endblock %} 7 | 8 | 9 | {% block body %}{% endblock %} 10 | {% block javascripts %}{% endblock %} 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/tests/.gitignore -------------------------------------------------------------------------------- /translations/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffreyVerreckt/Symfony4-REST-API/56f798f0e838858b526f3102d669cda2df1f1f06/translations/.gitignore -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var Encore = require('@symfony/webpack-encore'); 2 | 3 | Encore 4 | // the project directory where compiled assets will be stored 5 | .setOutputPath('public/build/') 6 | // the public path used by the web server to access the previous directory 7 | .setPublicPath('/build') 8 | .cleanupOutputBeforeBuild() 9 | .enableSourceMaps(!Encore.isProduction()) 10 | // uncomment to create hashed filenames (e.g. app.abc123.css) 11 | // .enableVersioning(Encore.isProduction()) 12 | 13 | // uncomment to define the assets of the project 14 | // .addEntry('js/app', './assets/js/app.js') 15 | // .addStyleEntry('css/app', './assets/css/app.scss') 16 | 17 | // uncomment if you use Sass/SCSS files 18 | // .enableSassLoader() 19 | 20 | // uncomment for legacy applications that require $/jQuery as a global variable 21 | // .autoProvidejQuery() 22 | ; 23 | 24 | module.exports = Encore.getWebpackConfig(); 25 | --------------------------------------------------------------------------------