├── .docker ├── php │ ├── Dockerfile │ └── php.ini └── scripts │ └── setup.sh ├── .env.dist ├── .gitignore ├── LICENCE ├── bin └── console ├── composer.json ├── composer.lock ├── config ├── bundles.php ├── packages │ ├── dev │ │ ├── routing.yaml │ │ └── web_profiler.yaml │ ├── doctrine.yaml │ ├── fos_oauth_server.yaml │ ├── framework.yaml │ ├── nelmio_api_doc.yaml │ ├── prod │ │ └── doctrine.yaml │ ├── routing.yaml │ ├── security.yaml │ ├── test │ │ ├── doctrine.yaml │ │ ├── framework.yaml │ │ └── web_profiler.yaml │ ├── translation.yaml │ └── twig.yaml ├── routes.yaml ├── routes │ ├── annotations.yaml │ ├── dev │ │ ├── twig.yaml │ │ └── web_profiler.yaml │ ├── nelmio_api_doc.yaml │ └── oauth.yaml ├── services.yaml └── services_test.yaml ├── docker-compose.yml ├── phpunit.xml.dist ├── public └── index.php ├── readme.md ├── screenshot.png ├── src ├── Authorization │ ├── Console │ │ └── ClientCreateCommand.php │ ├── Controller │ │ ├── OAuthAuthorizeController.php │ │ └── OAuthTokenController.php │ └── Entity │ │ └── Oauth2 │ │ ├── AccessToken.php │ │ ├── AuthCode.php │ │ ├── Client.php │ │ └── RefreshToken.php ├── DataFixtures │ ├── .gitignore │ ├── ArticleFixtures.php │ └── UserFixtures.php ├── Kernel.php └── Project │ ├── App │ ├── EventListener │ │ └── ApiExceptionListener.php │ ├── Interface │ │ └── ValidationInterface.php │ └── Support │ │ ├── AppEntityRepository.php │ │ └── FractalService.php │ ├── Console │ └── ProjectTestCommand.php │ ├── Domain │ ├── Article │ │ ├── ArticleService.php │ │ ├── ArticleTransformer.php │ │ └── Entity │ │ │ ├── Article.php │ │ │ └── Tag.php │ └── User │ │ ├── Contract │ │ └── UserRepositoryInterface.php │ │ ├── Entity │ │ └── User.php │ │ ├── UserService.php │ │ └── UserTransformer.php │ ├── Http │ └── Controller │ │ ├── AppController.php │ │ ├── ArticleController.php │ │ ├── HomeController.php │ │ ├── SearchController.php │ │ └── UserController.php │ ├── Infrastructure │ ├── Article │ │ └── ArticleRepository.php │ └── User │ │ └── UserRepository.php │ └── Resources │ ├── config │ ├── services.yaml │ └── transformers.yaml │ ├── doctrine │ └── mapping │ │ ├── Article.Entity.Article.orm.yml │ │ ├── Article.Entity.Tag.orm.yml │ │ └── User.Entity.User.orm.yml │ └── routing │ └── routes.yaml ├── symfony.lock ├── templates └── base.html.twig ├── tests ├── .gitignore ├── UnitTest.php └── integration │ └── ArticleServiceTest.php └── translations └── .gitignore /.docker/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.3-cli 2 | 3 | 4 | # Installing Ubuntu Packages 5 | RUN export DEBIAN_FRONTEND=noninteractive \ 6 | && apt-get update \ 7 | && apt-get install -y --no-install-recommends apt-utils \ 8 | && apt-get install -y sqlite3 \ 9 | && apt-get install -y gzip git jq \ 10 | && apt-get install -y zip unzip \ 11 | && apt-get install -y libxml2-dev libzip-dev \ 12 | && apt-get install -y libssl-dev libcurl4-openssl-dev pkg-config \ 13 | && apt-get install -y libicu-dev g++ libxml2 \ 14 | && apt-get install -y libbz2-dev zlib1g-dev 15 | 16 | # Installing PHP Core Extensions 17 | RUN docker-php-ext-install -j$(nproc) iconv \ 18 | && docker-php-ext-install -j$(nproc) bcmath \ 19 | && docker-php-ext-install -j$(nproc) intl \ 20 | && docker-php-ext-install -j$(nproc) sockets \ 21 | && docker-php-ext-install -j$(nproc) opcache \ 22 | && docker-php-ext-install -j$(nproc) calendar \ 23 | && docker-php-ext-install -j$(nproc) pdo_mysql \ 24 | && docker-php-ext-install -j$(nproc) zip \ 25 | && docker-php-ext-install -j$(nproc) pcntl soap curl xml mbstring soap 26 | 27 | # Enable PHP Debug 28 | RUN pecl install xdebug \ 29 | && docker-php-ext-enable xdebug 30 | 31 | # Install PHP composer 32 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 33 | 34 | COPY ./php.ini /usr/local/etc/php/php.ini 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /.docker/php/php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | 3 | ;;;;;;;;;;;;;;;;;;; 4 | ; About php.ini ; 5 | ;;;;;;;;;;;;;;;;;;; 6 | ; PHP's initialization file, generally called php.ini, is responsible for 7 | ; configuring many of the aspects of PHP's behavior. 8 | 9 | ; PHP attempts to find and load this configuration from a number of locations. 10 | ; The following is a summary of its search order: 11 | ; 1. SAPI module specific location. 12 | ; 2. The PHPRC environment variable. (As of PHP 5.2.0) 13 | ; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) 14 | ; 4. Current working directory (except CLI) 15 | ; 5. The web server's directory (for SAPI modules), or directory of PHP 16 | ; (otherwise in Windows) 17 | ; 6. The directory from the --with-config-file-path compile time option, or the 18 | ; Windows directory (C:\windows or C:\winnt) 19 | ; See the PHP docs for more specific information. 20 | ; http://php.net/configuration.file 21 | 22 | ; The syntax of the file is extremely simple. Whitespace and lines 23 | ; beginning with a semicolon are silently ignored (as you probably guessed). 24 | ; Section headers (e.g. [Foo]) are also silently ignored, even though 25 | ; they might mean something in the future. 26 | 27 | ; Directives following the section heading [PATH=/www/mysite] only 28 | ; apply to PHP files in the /www/mysite directory. Directives 29 | ; following the section heading [HOST=www.example.com] only apply to 30 | ; PHP files served from www.example.com. Directives set in these 31 | ; special sections cannot be overridden by user-defined INI files or 32 | ; at runtime. Currently, [PATH=] and [HOST=] sections only work under 33 | ; CGI/FastCGI. 34 | ; http://php.net/ini.sections 35 | 36 | ; Directives are specified using the following syntax: 37 | ; directive = value 38 | ; Directive names are *case sensitive* - foo=bar is different from FOO=bar. 39 | ; Directives are variables used to configure PHP or PHP extensions. 40 | ; There is no name validation. If PHP can't find an expected 41 | ; directive because it is not set or is mistyped, a default value will be used. 42 | 43 | ; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one 44 | ; of the INI constants (On, Off, True, False, Yes, No and None) or an expression 45 | ; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a 46 | ; previously set variable or directive (e.g. ${foo}) 47 | 48 | ; Expressions in the INI file are limited to bitwise operators and parentheses: 49 | ; | bitwise OR 50 | ; ^ bitwise XOR 51 | ; & bitwise AND 52 | ; ~ bitwise NOT 53 | ; ! boolean NOT 54 | 55 | ; Boolean flags can be turned on using the values 1, On, True or Yes. 56 | ; They can be turned off using the values 0, Off, False or No. 57 | 58 | ; An empty string can be denoted by simply not writing anything after the equal 59 | ; sign, or by using the None keyword: 60 | 61 | ; foo = ; sets foo to an empty string 62 | ; foo = None ; sets foo to an empty string 63 | ; foo = "None" ; sets foo to the string 'None' 64 | 65 | ; If you use constants in your value, and these constants belong to a 66 | ; dynamically loaded extension (either a PHP extension or a Zend extension), 67 | ; you may only use these constants *after* the line that loads the extension. 68 | 69 | ;;;;;;;;;;;;;;;;;;; 70 | ; About this file ; 71 | ;;;;;;;;;;;;;;;;;;; 72 | ; PHP comes packaged with two INI files. One that is recommended to be used 73 | ; in production environments and one that is recommended to be used in 74 | ; development environments. 75 | 76 | ; php.ini-production contains settings which hold security, performance and 77 | ; best practices at its core. But please be aware, these settings may break 78 | ; compatibility with older or less security conscience applications. We 79 | ; recommending using the production ini in production and testing environments. 80 | 81 | ; php.ini-development is very similar to its production variant, except it is 82 | ; much more verbose when it comes to errors. We recommend using the 83 | ; development version only in development environments, as errors shown to 84 | ; application users can inadvertently leak otherwise secure information. 85 | 86 | ; This is php.ini-development INI file. 87 | 88 | ;;;;;;;;;;;;;;;;;;; 89 | ; Quick Reference ; 90 | ;;;;;;;;;;;;;;;;;;; 91 | ; The following are all the settings which are different in either the production 92 | ; or development versions of the INIs with respect to PHP's default behavior. 93 | ; Please see the actual settings later in the document for more details as to why 94 | ; we recommend these changes in PHP's behavior. 95 | 96 | ; display_errors 97 | ; Default Value: On 98 | ; Development Value: On 99 | ; Production Value: Off 100 | 101 | ; display_startup_errors 102 | ; Default Value: Off 103 | ; Development Value: On 104 | ; Production Value: Off 105 | 106 | ; error_reporting 107 | ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED 108 | ; Development Value: E_ALL 109 | ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT 110 | 111 | ; html_errors 112 | ; Default Value: On 113 | ; Development Value: On 114 | ; Production value: On 115 | 116 | ; log_errors 117 | ; Default Value: Off 118 | ; Development Value: On 119 | ; Production Value: On 120 | 121 | ; max_input_time 122 | ; Default Value: -1 (Unlimited) 123 | ; Development Value: 60 (60 seconds) 124 | ; Production Value: 60 (60 seconds) 125 | 126 | ; output_buffering 127 | ; Default Value: Off 128 | ; Development Value: 4096 129 | ; Production Value: 4096 130 | 131 | ; register_argc_argv 132 | ; Default Value: On 133 | ; Development Value: Off 134 | ; Production Value: Off 135 | 136 | ; request_order 137 | ; Default Value: None 138 | ; Development Value: "GP" 139 | ; Production Value: "GP" 140 | 141 | ; session.gc_divisor 142 | ; Default Value: 100 143 | ; Development Value: 1000 144 | ; Production Value: 1000 145 | 146 | ; session.sid_bits_per_character 147 | ; Default Value: 4 148 | ; Development Value: 5 149 | ; Production Value: 5 150 | 151 | ; short_open_tag 152 | ; Default Value: On 153 | ; Development Value: Off 154 | ; Production Value: Off 155 | 156 | ; variables_order 157 | ; Default Value: "EGPCS" 158 | ; Development Value: "GPCS" 159 | ; Production Value: "GPCS" 160 | 161 | ;;;;;;;;;;;;;;;;;;;; 162 | ; php.ini Options ; 163 | ;;;;;;;;;;;;;;;;;;;; 164 | ; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" 165 | ;user_ini.filename = ".user.ini" 166 | 167 | ; To disable this feature set this option to empty value 168 | ;user_ini.filename = 169 | 170 | ; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) 171 | ;user_ini.cache_ttl = 300 172 | 173 | ;;;;;;;;;;;;;;;;;;;; 174 | ; Language Options ; 175 | ;;;;;;;;;;;;;;;;;;;; 176 | 177 | ; Enable the PHP scripting language engine under Apache. 178 | ; http://php.net/engine 179 | engine = On 180 | 181 | ; This directive determines whether or not PHP will recognize code between 182 | ; tags as PHP source which should be processed as such. It is 183 | ; generally recommended that should be used and that this feature 184 | ; should be disabled, as enabling it may result in issues when generating XML 185 | ; documents, however this remains supported for backward compatibility reasons. 186 | ; Note that this directive does not control the would work. 319 | ; http://php.net/syntax-highlighting 320 | ;highlight.string = #DD0000 321 | ;highlight.comment = #FF9900 322 | ;highlight.keyword = #007700 323 | ;highlight.default = #0000BB 324 | ;highlight.html = #000000 325 | 326 | ; If enabled, the request will be allowed to complete even if the user aborts 327 | ; the request. Consider enabling it if executing long requests, which may end up 328 | ; being interrupted by the user or a browser timing out. PHP's default behavior 329 | ; is to disable this feature. 330 | ; http://php.net/ignore-user-abort 331 | ;ignore_user_abort = On 332 | 333 | ; Determines the size of the realpath cache to be used by PHP. This value should 334 | ; be increased on systems where PHP opens many files to reflect the quantity of 335 | ; the file operations performed. 336 | ; Note: if open_basedir is set, the cache is disabled 337 | ; http://php.net/realpath-cache-size 338 | ;realpath_cache_size = 4096k 339 | 340 | ; Duration of time, in seconds for which to cache realpath information for a given 341 | ; file or directory. For systems with rarely changing files, consider increasing this 342 | ; value. 343 | ; http://php.net/realpath-cache-ttl 344 | ;realpath_cache_ttl = 120 345 | 346 | ; Enables or disables the circular reference collector. 347 | ; http://php.net/zend.enable-gc 348 | zend.enable_gc = On 349 | 350 | ; If enabled, scripts may be written in encodings that are incompatible with 351 | ; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such 352 | ; encodings. To use this feature, mbstring extension must be enabled. 353 | ; Default: Off 354 | ;zend.multibyte = Off 355 | 356 | ; Allows to set the default encoding for the scripts. This value will be used 357 | ; unless "declare(encoding=...)" directive appears at the top of the script. 358 | ; Only affects if zend.multibyte is set. 359 | ; Default: "" 360 | ;zend.script_encoding = 361 | 362 | ;;;;;;;;;;;;;;;;; 363 | ; Miscellaneous ; 364 | ;;;;;;;;;;;;;;;;; 365 | 366 | ; Decides whether PHP may expose the fact that it is installed on the server 367 | ; (e.g. by adding its signature to the Web server header). It is no security 368 | ; threat in any way, but it makes it possible to determine whether you use PHP 369 | ; on your server or not. 370 | ; http://php.net/expose-php 371 | expose_php = On 372 | 373 | ;;;;;;;;;;;;;;;;;;; 374 | ; Resource Limits ; 375 | ;;;;;;;;;;;;;;;;;;; 376 | 377 | ; Maximum execution time of each script, in seconds 378 | ; http://php.net/max-execution-time 379 | ; Note: This directive is hardcoded to 0 for the CLI SAPI 380 | max_execution_time = 30 381 | 382 | ; Maximum amount of time each script may spend parsing request data. It's a good 383 | ; idea to limit this time on productions servers in order to eliminate unexpectedly 384 | ; long running scripts. 385 | ; Note: This directive is hardcoded to -1 for the CLI SAPI 386 | ; Default Value: -1 (Unlimited) 387 | ; Development Value: 60 (60 seconds) 388 | ; Production Value: 60 (60 seconds) 389 | ; http://php.net/max-input-time 390 | max_input_time = 60 391 | 392 | ; Maximum input variable nesting level 393 | ; http://php.net/max-input-nesting-level 394 | ;max_input_nesting_level = 64 395 | 396 | ; How many GET/POST/COOKIE input variables may be accepted 397 | ; max_input_vars = 1000 398 | 399 | ; Maximum amount of memory a script may consume (128MB) 400 | ; http://php.net/memory-limit 401 | memory_limit = 128M 402 | 403 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 404 | ; Error handling and logging ; 405 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 406 | 407 | ; This directive informs PHP of which errors, warnings and notices you would like 408 | ; it to take action for. The recommended way of setting values for this 409 | ; directive is through the use of the error level constants and bitwise 410 | ; operators. The error level constants are below here for convenience as well as 411 | ; some common settings and their meanings. 412 | ; By default, PHP is set to take action on all errors, notices and warnings EXCEPT 413 | ; those related to E_NOTICE and E_STRICT, which together cover best practices and 414 | ; recommended coding standards in PHP. For performance reasons, this is the 415 | ; recommend error reporting setting. Your production server shouldn't be wasting 416 | ; resources complaining about best practices and coding standards. That's what 417 | ; development servers and development settings are for. 418 | ; Note: The php.ini-development file has this setting as E_ALL. This 419 | ; means it pretty much reports everything which is exactly what you want during 420 | ; development and early testing. 421 | ; 422 | ; Error Level Constants: 423 | ; E_ALL - All errors and warnings (includes E_STRICT as of PHP 5.4.0) 424 | ; E_ERROR - fatal run-time errors 425 | ; E_RECOVERABLE_ERROR - almost fatal run-time errors 426 | ; E_WARNING - run-time warnings (non-fatal errors) 427 | ; E_PARSE - compile-time parse errors 428 | ; E_NOTICE - run-time notices (these are warnings which often result 429 | ; from a bug in your code, but it's possible that it was 430 | ; intentional (e.g., using an uninitialized variable and 431 | ; relying on the fact it is automatically initialized to an 432 | ; empty string) 433 | ; E_STRICT - run-time notices, enable to have PHP suggest changes 434 | ; to your code which will ensure the best interoperability 435 | ; and forward compatibility of your code 436 | ; E_CORE_ERROR - fatal errors that occur during PHP's initial startup 437 | ; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's 438 | ; initial startup 439 | ; E_COMPILE_ERROR - fatal compile-time errors 440 | ; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) 441 | ; E_USER_ERROR - user-generated error message 442 | ; E_USER_WARNING - user-generated warning message 443 | ; E_USER_NOTICE - user-generated notice message 444 | ; E_DEPRECATED - warn about code that will not work in future versions 445 | ; of PHP 446 | ; E_USER_DEPRECATED - user-generated deprecation warnings 447 | ; 448 | ; Common Values: 449 | ; E_ALL (Show all errors, warnings and notices including coding standards.) 450 | ; E_ALL & ~E_NOTICE (Show all errors, except for notices) 451 | ; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.) 452 | ; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) 453 | ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED 454 | ; Development Value: E_ALL 455 | ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT 456 | ; http://php.net/error-reporting 457 | error_reporting = E_ALL 458 | 459 | ; This directive controls whether or not and where PHP will output errors, 460 | ; notices and warnings too. Error output is very useful during development, but 461 | ; it could be very dangerous in production environments. Depending on the code 462 | ; which is triggering the error, sensitive information could potentially leak 463 | ; out of your application such as database usernames and passwords or worse. 464 | ; For production environments, we recommend logging errors rather than 465 | ; sending them to STDOUT. 466 | ; Possible Values: 467 | ; Off = Do not display any errors 468 | ; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) 469 | ; On or stdout = Display errors to STDOUT 470 | ; Default Value: On 471 | ; Development Value: On 472 | ; Production Value: Off 473 | ; http://php.net/display-errors 474 | display_errors = On 475 | 476 | ; The display of errors which occur during PHP's startup sequence are handled 477 | ; separately from display_errors. PHP's default behavior is to suppress those 478 | ; errors from clients. Turning the display of startup errors on can be useful in 479 | ; debugging configuration problems. We strongly recommend you 480 | ; set this to 'off' for production servers. 481 | ; Default Value: Off 482 | ; Development Value: On 483 | ; Production Value: Off 484 | ; http://php.net/display-startup-errors 485 | display_startup_errors = On 486 | 487 | ; Besides displaying errors, PHP can also log errors to locations such as a 488 | ; server-specific log, STDERR, or a location specified by the error_log 489 | ; directive found below. While errors should not be displayed on productions 490 | ; servers they should still be monitored and logging is a great way to do that. 491 | ; Default Value: Off 492 | ; Development Value: On 493 | ; Production Value: On 494 | ; http://php.net/log-errors 495 | log_errors = On 496 | 497 | ; Set maximum length of log_errors. In error_log information about the source is 498 | ; added. The default is 1024 and 0 allows to not apply any maximum length at all. 499 | ; http://php.net/log-errors-max-len 500 | log_errors_max_len = 1024 501 | 502 | ; Do not log repeated messages. Repeated errors must occur in same file on same 503 | ; line unless ignore_repeated_source is set true. 504 | ; http://php.net/ignore-repeated-errors 505 | ignore_repeated_errors = Off 506 | 507 | ; Ignore source of message when ignoring repeated messages. When this setting 508 | ; is On you will not log errors with repeated messages from different files or 509 | ; source lines. 510 | ; http://php.net/ignore-repeated-source 511 | ignore_repeated_source = Off 512 | 513 | ; If this parameter is set to Off, then memory leaks will not be shown (on 514 | ; stdout or in the log). This has only effect in a debug compile, and if 515 | ; error reporting includes E_WARNING in the allowed list 516 | ; http://php.net/report-memleaks 517 | report_memleaks = On 518 | 519 | ; This setting is on by default. 520 | ;report_zend_debug = 0 521 | 522 | ; Store the last error/warning message in $php_errormsg (boolean). 523 | ; This directive is DEPRECATED. 524 | ; Default Value: Off 525 | ; Development Value: Off 526 | ; Production Value: Off 527 | ; http://php.net/track-errors 528 | ;track_errors = Off 529 | 530 | ; Turn off normal error reporting and emit XML-RPC error XML 531 | ; http://php.net/xmlrpc-errors 532 | ;xmlrpc_errors = 0 533 | 534 | ; An XML-RPC faultCode 535 | ;xmlrpc_error_number = 0 536 | 537 | ; When PHP displays or logs an error, it has the capability of formatting the 538 | ; error message as HTML for easier reading. This directive controls whether 539 | ; the error message is formatted as HTML or not. 540 | ; Note: This directive is hardcoded to Off for the CLI SAPI 541 | ; Default Value: On 542 | ; Development Value: On 543 | ; Production value: On 544 | ; http://php.net/html-errors 545 | html_errors = On 546 | 547 | ; If html_errors is set to On *and* docref_root is not empty, then PHP 548 | ; produces clickable error messages that direct to a page describing the error 549 | ; or function causing the error in detail. 550 | ; You can download a copy of the PHP manual from http://php.net/docs 551 | ; and change docref_root to the base URL of your local copy including the 552 | ; leading '/'. You must also specify the file extension being used including 553 | ; the dot. PHP's default behavior is to leave these settings empty, in which 554 | ; case no links to documentation are generated. 555 | ; Note: Never use this feature for production boxes. 556 | ; http://php.net/docref-root 557 | ; Examples 558 | ;docref_root = "/phpmanual/" 559 | 560 | ; http://php.net/docref-ext 561 | ;docref_ext = .html 562 | 563 | ; String to output before an error message. PHP's default behavior is to leave 564 | ; this setting blank. 565 | ; http://php.net/error-prepend-string 566 | ; Example: 567 | ;error_prepend_string = "" 568 | 569 | ; String to output after an error message. PHP's default behavior is to leave 570 | ; this setting blank. 571 | ; http://php.net/error-append-string 572 | ; Example: 573 | ;error_append_string = "" 574 | 575 | ; Log errors to specified file. PHP's default behavior is to leave this value 576 | ; empty. 577 | ; http://php.net/error-log 578 | ; Example: 579 | ;error_log = php_errors.log 580 | ; Log errors to syslog (Event Log on Windows). 581 | ;error_log = syslog 582 | 583 | ;windows.show_crt_warning 584 | ; Default value: 0 585 | ; Development value: 0 586 | ; Production value: 0 587 | 588 | ;;;;;;;;;;;;;;;;; 589 | ; Data Handling ; 590 | ;;;;;;;;;;;;;;;;; 591 | 592 | ; The separator used in PHP generated URLs to separate arguments. 593 | ; PHP's default setting is "&". 594 | ; http://php.net/arg-separator.output 595 | ; Example: 596 | ;arg_separator.output = "&" 597 | 598 | ; List of separator(s) used by PHP to parse input URLs into variables. 599 | ; PHP's default setting is "&". 600 | ; NOTE: Every character in this directive is considered as separator! 601 | ; http://php.net/arg-separator.input 602 | ; Example: 603 | ;arg_separator.input = ";&" 604 | 605 | ; This directive determines which super global arrays are registered when PHP 606 | ; starts up. G,P,C,E & S are abbreviations for the following respective super 607 | ; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty 608 | ; paid for the registration of these arrays and because ENV is not as commonly 609 | ; used as the others, ENV is not recommended on productions servers. You 610 | ; can still get access to the environment variables through getenv() should you 611 | ; need to. 612 | ; Default Value: "EGPCS" 613 | ; Development Value: "GPCS" 614 | ; Production Value: "GPCS"; 615 | ; http://php.net/variables-order 616 | variables_order = "GPCS" 617 | 618 | ; This directive determines which super global data (G,P & C) should be 619 | ; registered into the super global array REQUEST. If so, it also determines 620 | ; the order in which that data is registered. The values for this directive 621 | ; are specified in the same manner as the variables_order directive, 622 | ; EXCEPT one. Leaving this value empty will cause PHP to use the value set 623 | ; in the variables_order directive. It does not mean it will leave the super 624 | ; globals array REQUEST empty. 625 | ; Default Value: None 626 | ; Development Value: "GP" 627 | ; Production Value: "GP" 628 | ; http://php.net/request-order 629 | request_order = "GP" 630 | 631 | ; This directive determines whether PHP registers $argv & $argc each time it 632 | ; runs. $argv contains an array of all the arguments passed to PHP when a script 633 | ; is invoked. $argc contains an integer representing the number of arguments 634 | ; that were passed when the script was invoked. These arrays are extremely 635 | ; useful when running scripts from the command line. When this directive is 636 | ; enabled, registering these variables consumes CPU cycles and memory each time 637 | ; a script is executed. For performance reasons, this feature should be disabled 638 | ; on production servers. 639 | ; Note: This directive is hardcoded to On for the CLI SAPI 640 | ; Default Value: On 641 | ; Development Value: Off 642 | ; Production Value: Off 643 | ; http://php.net/register-argc-argv 644 | register_argc_argv = Off 645 | 646 | ; When enabled, the ENV, REQUEST and SERVER variables are created when they're 647 | ; first used (Just In Time) instead of when the script starts. If these 648 | ; variables are not used within a script, having this directive on will result 649 | ; in a performance gain. The PHP directive register_argc_argv must be disabled 650 | ; for this directive to have any affect. 651 | ; http://php.net/auto-globals-jit 652 | auto_globals_jit = On 653 | 654 | ; Whether PHP will read the POST data. 655 | ; This option is enabled by default. 656 | ; Most likely, you won't want to disable this option globally. It causes $_POST 657 | ; and $_FILES to always be empty; the only way you will be able to read the 658 | ; POST data will be through the php://input stream wrapper. This can be useful 659 | ; to proxy requests or to process the POST data in a memory efficient fashion. 660 | ; http://php.net/enable-post-data-reading 661 | ;enable_post_data_reading = Off 662 | 663 | ; Maximum size of POST data that PHP will accept. 664 | ; Its value may be 0 to disable the limit. It is ignored if POST data reading 665 | ; is disabled through enable_post_data_reading. 666 | ; http://php.net/post-max-size 667 | post_max_size = 8M 668 | 669 | ; Automatically add files before PHP document. 670 | ; http://php.net/auto-prepend-file 671 | auto_prepend_file = 672 | 673 | ; Automatically add files after PHP document. 674 | ; http://php.net/auto-append-file 675 | auto_append_file = 676 | 677 | ; By default, PHP will output a media type using the Content-Type header. To 678 | ; disable this, simply set it to be empty. 679 | ; 680 | ; PHP's built-in default media type is set to text/html. 681 | ; http://php.net/default-mimetype 682 | default_mimetype = "text/html" 683 | 684 | ; PHP's default character set is set to UTF-8. 685 | ; http://php.net/default-charset 686 | default_charset = "UTF-8" 687 | 688 | ; PHP internal character encoding is set to empty. 689 | ; If empty, default_charset is used. 690 | ; http://php.net/internal-encoding 691 | ;internal_encoding = 692 | 693 | ; PHP input character encoding is set to empty. 694 | ; If empty, default_charset is used. 695 | ; http://php.net/input-encoding 696 | ;input_encoding = 697 | 698 | ; PHP output character encoding is set to empty. 699 | ; If empty, default_charset is used. 700 | ; See also output_buffer. 701 | ; http://php.net/output-encoding 702 | ;output_encoding = 703 | 704 | ;;;;;;;;;;;;;;;;;;;;;;;;; 705 | ; Paths and Directories ; 706 | ;;;;;;;;;;;;;;;;;;;;;;;;; 707 | 708 | ; UNIX: "/path1:/path2" 709 | ;include_path = ".:/php/includes" 710 | ; 711 | ; Windows: "\path1;\path2" 712 | ;include_path = ".;c:\php\includes" 713 | ; 714 | ; PHP's default setting for include_path is ".;/path/to/php/pear" 715 | ; http://php.net/include-path 716 | 717 | ; The root of the PHP pages, used only if nonempty. 718 | ; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root 719 | ; if you are running php as a CGI under any web server (other than IIS) 720 | ; see documentation for security issues. The alternate is to use the 721 | ; cgi.force_redirect configuration below 722 | ; http://php.net/doc-root 723 | doc_root = 724 | 725 | ; The directory under which PHP opens the script using /~username used only 726 | ; if nonempty. 727 | ; http://php.net/user-dir 728 | user_dir = 729 | 730 | ; Directory in which the loadable extensions (modules) reside. 731 | ; http://php.net/extension-dir 732 | ; extension_dir = "./" 733 | ; On windows: 734 | ; extension_dir = "ext" 735 | 736 | ; Directory where the temporary files should be placed. 737 | ; Defaults to the system default (see sys_get_temp_dir) 738 | ; sys_temp_dir = "/tmp" 739 | 740 | ; Whether or not to enable the dl() function. The dl() function does NOT work 741 | ; properly in multithreaded servers, such as IIS or Zeus, and is automatically 742 | ; disabled on them. 743 | ; http://php.net/enable-dl 744 | enable_dl = Off 745 | 746 | ; cgi.force_redirect is necessary to provide security running PHP as a CGI under 747 | ; most web servers. Left undefined, PHP turns this on by default. You can 748 | ; turn it off here AT YOUR OWN RISK 749 | ; **You CAN safely turn this off for IIS, in fact, you MUST.** 750 | ; http://php.net/cgi.force-redirect 751 | ;cgi.force_redirect = 1 752 | 753 | ; if cgi.nph is enabled it will force cgi to always sent Status: 200 with 754 | ; every request. PHP's default behavior is to disable this feature. 755 | ;cgi.nph = 1 756 | 757 | ; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape 758 | ; (iPlanet) web servers, you MAY need to set an environment variable name that PHP 759 | ; will look for to know it is OK to continue execution. Setting this variable MAY 760 | ; cause security issues, KNOW WHAT YOU ARE DOING FIRST. 761 | ; http://php.net/cgi.redirect-status-env 762 | ;cgi.redirect_status_env = 763 | 764 | ; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's 765 | ; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok 766 | ; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting 767 | ; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting 768 | ; of zero causes PHP to behave as before. Default is 1. You should fix your scripts 769 | ; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. 770 | ; http://php.net/cgi.fix-pathinfo 771 | ;cgi.fix_pathinfo=1 772 | 773 | ; if cgi.discard_path is enabled, the PHP CGI binary can safely be placed outside 774 | ; of the web tree and people will not be able to circumvent .htaccess security. 775 | ; http://php.net/cgi.dicard-path 776 | ;cgi.discard_path=1 777 | 778 | ; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate 779 | ; security tokens of the calling client. This allows IIS to define the 780 | ; security context that the request runs under. mod_fastcgi under Apache 781 | ; does not currently support this feature (03/17/2002) 782 | ; Set to 1 if running under IIS. Default is zero. 783 | ; http://php.net/fastcgi.impersonate 784 | ;fastcgi.impersonate = 1 785 | 786 | ; Disable logging through FastCGI connection. PHP's default behavior is to enable 787 | ; this feature. 788 | ;fastcgi.logging = 0 789 | 790 | ; cgi.rfc2616_headers configuration option tells PHP what type of headers to 791 | ; use when sending HTTP response code. If set to 0, PHP sends Status: header that 792 | ; is supported by Apache. When this option is set to 1, PHP will send 793 | ; RFC2616 compliant header. 794 | ; Default is zero. 795 | ; http://php.net/cgi.rfc2616-headers 796 | ;cgi.rfc2616_headers = 0 797 | 798 | ; cgi.check_shebang_line controls whether CGI PHP checks for line starting with #! 799 | ; (shebang) at the top of the running script. This line might be needed if the 800 | ; script support running both as stand-alone script and via PHP CGI<. PHP in CGI 801 | ; mode skips this line and ignores its content if this directive is turned on. 802 | ; http://php.net/cgi.check-shebang-line 803 | ;cgi.check_shebang_line=1 804 | 805 | ;;;;;;;;;;;;;;;; 806 | ; File Uploads ; 807 | ;;;;;;;;;;;;;;;; 808 | 809 | ; Whether to allow HTTP file uploads. 810 | ; http://php.net/file-uploads 811 | file_uploads = On 812 | 813 | ; Temporary directory for HTTP uploaded files (will use system default if not 814 | ; specified). 815 | ; http://php.net/upload-tmp-dir 816 | ;upload_tmp_dir = 817 | 818 | ; Maximum allowed size for uploaded files. 819 | ; http://php.net/upload-max-filesize 820 | upload_max_filesize = 2M 821 | 822 | ; Maximum number of files that can be uploaded via a single request 823 | max_file_uploads = 20 824 | 825 | ;;;;;;;;;;;;;;;;;; 826 | ; Fopen wrappers ; 827 | ;;;;;;;;;;;;;;;;;; 828 | 829 | ; Whether to allow the treatment of URLs (like http:// or ftp://) as files. 830 | ; http://php.net/allow-url-fopen 831 | allow_url_fopen = On 832 | 833 | ; Whether to allow include/require to open URLs (like http:// or ftp://) as files. 834 | ; http://php.net/allow-url-include 835 | allow_url_include = Off 836 | 837 | ; Define the anonymous ftp password (your email address). PHP's default setting 838 | ; for this is empty. 839 | ; http://php.net/from 840 | ;from="john@doe.com" 841 | 842 | ; Define the User-Agent string. PHP's default setting for this is empty. 843 | ; http://php.net/user-agent 844 | ;user_agent="PHP" 845 | 846 | ; Default timeout for socket based streams (seconds) 847 | ; http://php.net/default-socket-timeout 848 | default_socket_timeout = 60 849 | 850 | ; If your scripts have to deal with files from Macintosh systems, 851 | ; or you are running on a Mac and need to deal with files from 852 | ; unix or win32 systems, setting this flag will cause PHP to 853 | ; automatically detect the EOL character in those files so that 854 | ; fgets() and file() will work regardless of the source of the file. 855 | ; http://php.net/auto-detect-line-endings 856 | ;auto_detect_line_endings = Off 857 | 858 | ;;;;;;;;;;;;;;;;;;;;;; 859 | ; Dynamic Extensions ; 860 | ;;;;;;;;;;;;;;;;;;;;;; 861 | 862 | ; If you wish to have an extension loaded automatically, use the following 863 | ; syntax: 864 | ; 865 | ; extension=modulename 866 | ; 867 | ; For example: 868 | ; 869 | ; extension=mysqli 870 | ; 871 | ; When the extension library to load is not located in the default extension 872 | ; directory, You may specify an absolute path to the library file: 873 | ; 874 | ; extension=/path/to/extension/mysqli.so 875 | ; 876 | ; Note : The syntax used in previous PHP versions ('extension=.so' and 877 | ; 'extension='php_.dll') is supported for legacy reasons and may be 878 | ; deprecated in a future PHP major version. So, when it is possible, please 879 | ; move to the new ('extension=) syntax. 880 | ; 881 | ; Notes for Windows environments : 882 | ; 883 | ; - Many DLL files are located in the extensions/ (PHP 4) or ext/ (PHP 5+) 884 | ; extension folders as well as the separate PECL DLL download (PHP 5+). 885 | ; Be sure to appropriately set the extension_dir directive. 886 | ; 887 | ;extension=bz2 888 | ;extension=curl 889 | ;extension=fileinfo 890 | ;extension=gd2 891 | ;extension=gettext 892 | ;extension=gmp 893 | ;extension=intl 894 | ;extension=imap 895 | ;extension=interbase 896 | ;extension=ldap 897 | ;extension=mbstring 898 | ;extension=exif ; Must be after mbstring as it depends on it 899 | ;extension=mysqli 900 | ;extension=oci8_12c ; Use with Oracle Database 12c Instant Client 901 | ;extension=odbc 902 | ;extension=openssl 903 | ;extension=pdo_firebird 904 | ;extension=pdo_mysql 905 | ;extension=pdo_oci 906 | ;extension=pdo_odbc 907 | ;extension=pdo_pgsql 908 | ;extension=pdo_sqlite 909 | ;extension=pgsql 910 | ;extension=shmop 911 | 912 | ; The MIBS data available in the PHP distribution must be installed. 913 | ; See http://www.php.net/manual/en/snmp.installation.php 914 | ;extension=snmp 915 | 916 | ;extension=soap 917 | ;extension=sockets 918 | ;extension=sqlite3 919 | ;extension=tidy 920 | ;extension=xmlrpc 921 | ;extension=xsl 922 | 923 | ;;;;;;;;;;;;;;;;;;; 924 | ; Module Settings ; 925 | ;;;;;;;;;;;;;;;;;;; 926 | 927 | [CLI Server] 928 | ; Whether the CLI web server uses ANSI color coding in its terminal output. 929 | cli_server.color = On 930 | 931 | [Date] 932 | ; Defines the default timezone used by the date functions 933 | ; http://php.net/date.timezone 934 | ;date.timezone = 935 | 936 | ; http://php.net/date.default-latitude 937 | ;date.default_latitude = 31.7667 938 | 939 | ; http://php.net/date.default-longitude 940 | ;date.default_longitude = 35.2333 941 | 942 | ; http://php.net/date.sunrise-zenith 943 | ;date.sunrise_zenith = 90.583333 944 | 945 | ; http://php.net/date.sunset-zenith 946 | ;date.sunset_zenith = 90.583333 947 | 948 | [filter] 949 | ; http://php.net/filter.default 950 | ;filter.default = unsafe_raw 951 | 952 | ; http://php.net/filter.default-flags 953 | ;filter.default_flags = 954 | 955 | [iconv] 956 | ; Use of this INI entry is deprecated, use global input_encoding instead. 957 | ; If empty, default_charset or input_encoding or iconv.input_encoding is used. 958 | ; The precedence is: default_charset < intput_encoding < iconv.input_encoding 959 | ;iconv.input_encoding = 960 | 961 | ; Use of this INI entry is deprecated, use global internal_encoding instead. 962 | ; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. 963 | ; The precedence is: default_charset < internal_encoding < iconv.internal_encoding 964 | ;iconv.internal_encoding = 965 | 966 | ; Use of this INI entry is deprecated, use global output_encoding instead. 967 | ; If empty, default_charset or output_encoding or iconv.output_encoding is used. 968 | ; The precedence is: default_charset < output_encoding < iconv.output_encoding 969 | ; To use an output encoding conversion, iconv's output handler must be set 970 | ; otherwise output encoding conversion cannot be performed. 971 | ;iconv.output_encoding = 972 | 973 | [imap] 974 | ; rsh/ssh logins are disabled by default. Use this INI entry if you want to 975 | ; enable them. Note that the IMAP library does not filter mailbox names before 976 | ; passing them to rsh/ssh command, thus passing untrusted data to this function 977 | ; with rsh/ssh enabled is insecure. 978 | ;imap.enable_insecure_rsh=0 979 | 980 | [intl] 981 | ;intl.default_locale = 982 | ; This directive allows you to produce PHP errors when some error 983 | ; happens within intl functions. The value is the level of the error produced. 984 | ; Default is 0, which does not produce any errors. 985 | ;intl.error_level = E_WARNING 986 | ;intl.use_exceptions = 0 987 | 988 | [sqlite3] 989 | ; Directory pointing to SQLite3 extensions 990 | ; http://php.net/sqlite3.extension-dir 991 | ;sqlite3.extension_dir = 992 | 993 | ; SQLite defensive mode flag (only available from SQLite 3.26+) 994 | ; When the defensive flag is enabled, language features that allow ordinary 995 | ; SQL to deliberately corrupt the database file are disabled. This forbids 996 | ; writing directly to the schema, shadow tables (eg. FTS data tables), or 997 | ; the sqlite_dbpage virtual table. 998 | ; https://www.sqlite.org/c3ref/c_dbconfig_defensive.html 999 | ; (for older SQLite versions, this flag has no use) 1000 | ;sqlite3.defensive = 1 1001 | 1002 | [Pcre] 1003 | ;PCRE library backtracking limit. 1004 | ; http://php.net/pcre.backtrack-limit 1005 | ;pcre.backtrack_limit=100000 1006 | 1007 | ;PCRE library recursion limit. 1008 | ;Please note that if you set this value to a high number you may consume all 1009 | ;the available process stack and eventually crash PHP (due to reaching the 1010 | ;stack size limit imposed by the Operating System). 1011 | ; http://php.net/pcre.recursion-limit 1012 | ;pcre.recursion_limit=100000 1013 | 1014 | ;Enables or disables JIT compilation of patterns. This requires the PCRE 1015 | ;library to be compiled with JIT support. 1016 | ;pcre.jit=1 1017 | 1018 | [Pdo] 1019 | ; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" 1020 | ; http://php.net/pdo-odbc.connection-pooling 1021 | ;pdo_odbc.connection_pooling=strict 1022 | 1023 | ;pdo_odbc.db2_instance_name 1024 | 1025 | [Pdo_mysql] 1026 | ; If mysqlnd is used: Number of cache slots for the internal result set cache 1027 | ; http://php.net/pdo_mysql.cache_size 1028 | pdo_mysql.cache_size = 2000 1029 | 1030 | ; Default socket name for local MySQL connects. If empty, uses the built-in 1031 | ; MySQL defaults. 1032 | ; http://php.net/pdo_mysql.default-socket 1033 | pdo_mysql.default_socket= 1034 | 1035 | [Phar] 1036 | ; http://php.net/phar.readonly 1037 | ;phar.readonly = On 1038 | 1039 | ; http://php.net/phar.require-hash 1040 | ;phar.require_hash = On 1041 | 1042 | ;phar.cache_list = 1043 | 1044 | [mail function] 1045 | ; For Win32 only. 1046 | ; http://php.net/smtp 1047 | SMTP = localhost 1048 | ; http://php.net/smtp-port 1049 | smtp_port = 25 1050 | 1051 | ; For Win32 only. 1052 | ; http://php.net/sendmail-from 1053 | ;sendmail_from = me@example.com 1054 | 1055 | ; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). 1056 | ; http://php.net/sendmail-path 1057 | ;sendmail_path = 1058 | 1059 | ; Force the addition of the specified parameters to be passed as extra parameters 1060 | ; to the sendmail binary. These parameters will always replace the value of 1061 | ; the 5th parameter to mail(). 1062 | ;mail.force_extra_parameters = 1063 | 1064 | ; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename 1065 | mail.add_x_header = Off 1066 | 1067 | ; The path to a log file that will log all mail() calls. Log entries include 1068 | ; the full path of the script, line number, To address and headers. 1069 | ;mail.log = 1070 | ; Log mail to syslog (Event Log on Windows). 1071 | ;mail.log = syslog 1072 | 1073 | [ODBC] 1074 | ; http://php.net/odbc.default-db 1075 | ;odbc.default_db = Not yet implemented 1076 | 1077 | ; http://php.net/odbc.default-user 1078 | ;odbc.default_user = Not yet implemented 1079 | 1080 | ; http://php.net/odbc.default-pw 1081 | ;odbc.default_pw = Not yet implemented 1082 | 1083 | ; Controls the ODBC cursor model. 1084 | ; Default: SQL_CURSOR_STATIC (default). 1085 | ;odbc.default_cursortype 1086 | 1087 | ; Allow or prevent persistent links. 1088 | ; http://php.net/odbc.allow-persistent 1089 | odbc.allow_persistent = On 1090 | 1091 | ; Check that a connection is still valid before reuse. 1092 | ; http://php.net/odbc.check-persistent 1093 | odbc.check_persistent = On 1094 | 1095 | ; Maximum number of persistent links. -1 means no limit. 1096 | ; http://php.net/odbc.max-persistent 1097 | odbc.max_persistent = -1 1098 | 1099 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1100 | ; http://php.net/odbc.max-links 1101 | odbc.max_links = -1 1102 | 1103 | ; Handling of LONG fields. Returns number of bytes to variables. 0 means 1104 | ; passthru. 1105 | ; http://php.net/odbc.defaultlrl 1106 | odbc.defaultlrl = 4096 1107 | 1108 | ; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. 1109 | ; See the documentation on odbc_binmode and odbc_longreadlen for an explanation 1110 | ; of odbc.defaultlrl and odbc.defaultbinmode 1111 | ; http://php.net/odbc.defaultbinmode 1112 | odbc.defaultbinmode = 1 1113 | 1114 | ;birdstep.max_links = -1 1115 | 1116 | [Interbase] 1117 | ; Allow or prevent persistent links. 1118 | ibase.allow_persistent = 1 1119 | 1120 | ; Maximum number of persistent links. -1 means no limit. 1121 | ibase.max_persistent = -1 1122 | 1123 | ; Maximum number of links (persistent + non-persistent). -1 means no limit. 1124 | ibase.max_links = -1 1125 | 1126 | ; Default database name for ibase_connect(). 1127 | ;ibase.default_db = 1128 | 1129 | ; Default username for ibase_connect(). 1130 | ;ibase.default_user = 1131 | 1132 | ; Default password for ibase_connect(). 1133 | ;ibase.default_password = 1134 | 1135 | ; Default charset for ibase_connect(). 1136 | ;ibase.default_charset = 1137 | 1138 | ; Default timestamp format. 1139 | ibase.timestampformat = "%Y-%m-%d %H:%M:%S" 1140 | 1141 | ; Default date format. 1142 | ibase.dateformat = "%Y-%m-%d" 1143 | 1144 | ; Default time format. 1145 | ibase.timeformat = "%H:%M:%S" 1146 | 1147 | [MySQLi] 1148 | 1149 | ; Maximum number of persistent links. -1 means no limit. 1150 | ; http://php.net/mysqli.max-persistent 1151 | mysqli.max_persistent = -1 1152 | 1153 | ; Allow accessing, from PHP's perspective, local files with LOAD DATA statements 1154 | ; http://php.net/mysqli.allow_local_infile 1155 | ;mysqli.allow_local_infile = On 1156 | 1157 | ; Allow or prevent persistent links. 1158 | ; http://php.net/mysqli.allow-persistent 1159 | mysqli.allow_persistent = On 1160 | 1161 | ; Maximum number of links. -1 means no limit. 1162 | ; http://php.net/mysqli.max-links 1163 | mysqli.max_links = -1 1164 | 1165 | ; If mysqlnd is used: Number of cache slots for the internal result set cache 1166 | ; http://php.net/mysqli.cache_size 1167 | mysqli.cache_size = 2000 1168 | 1169 | ; Default port number for mysqli_connect(). If unset, mysqli_connect() will use 1170 | ; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the 1171 | ; compile-time value defined MYSQL_PORT (in that order). Win32 will only look 1172 | ; at MYSQL_PORT. 1173 | ; http://php.net/mysqli.default-port 1174 | mysqli.default_port = 3306 1175 | 1176 | ; Default socket name for local MySQL connects. If empty, uses the built-in 1177 | ; MySQL defaults. 1178 | ; http://php.net/mysqli.default-socket 1179 | mysqli.default_socket = 1180 | 1181 | ; Default host for mysql_connect() (doesn't apply in safe mode). 1182 | ; http://php.net/mysqli.default-host 1183 | mysqli.default_host = 1184 | 1185 | ; Default user for mysql_connect() (doesn't apply in safe mode). 1186 | ; http://php.net/mysqli.default-user 1187 | mysqli.default_user = 1188 | 1189 | ; Default password for mysqli_connect() (doesn't apply in safe mode). 1190 | ; Note that this is generally a *bad* idea to store passwords in this file. 1191 | ; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") 1192 | ; and reveal this password! And of course, any users with read access to this 1193 | ; file will be able to reveal the password as well. 1194 | ; http://php.net/mysqli.default-pw 1195 | mysqli.default_pw = 1196 | 1197 | ; Allow or prevent reconnect 1198 | mysqli.reconnect = Off 1199 | 1200 | [mysqlnd] 1201 | ; Enable / Disable collection of general statistics by mysqlnd which can be 1202 | ; used to tune and monitor MySQL operations. 1203 | ; http://php.net/mysqlnd.collect_statistics 1204 | mysqlnd.collect_statistics = On 1205 | 1206 | ; Enable / Disable collection of memory usage statistics by mysqlnd which can be 1207 | ; used to tune and monitor MySQL operations. 1208 | ; http://php.net/mysqlnd.collect_memory_statistics 1209 | mysqlnd.collect_memory_statistics = On 1210 | 1211 | ; Records communication from all extensions using mysqlnd to the specified log 1212 | ; file. 1213 | ; http://php.net/mysqlnd.debug 1214 | ;mysqlnd.debug = 1215 | 1216 | ; Defines which queries will be logged. 1217 | ; http://php.net/mysqlnd.log_mask 1218 | ;mysqlnd.log_mask = 0 1219 | 1220 | ; Default size of the mysqlnd memory pool, which is used by result sets. 1221 | ; http://php.net/mysqlnd.mempool_default_size 1222 | ;mysqlnd.mempool_default_size = 16000 1223 | 1224 | ; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. 1225 | ; http://php.net/mysqlnd.net_cmd_buffer_size 1226 | ;mysqlnd.net_cmd_buffer_size = 2048 1227 | 1228 | ; Size of a pre-allocated buffer used for reading data sent by the server in 1229 | ; bytes. 1230 | ; http://php.net/mysqlnd.net_read_buffer_size 1231 | ;mysqlnd.net_read_buffer_size = 32768 1232 | 1233 | ; Timeout for network requests in seconds. 1234 | ; http://php.net/mysqlnd.net_read_timeout 1235 | ;mysqlnd.net_read_timeout = 31536000 1236 | 1237 | ; SHA-256 Authentication Plugin related. File with the MySQL server public RSA 1238 | ; key. 1239 | ; http://php.net/mysqlnd.sha256_server_public_key 1240 | ;mysqlnd.sha256_server_public_key = 1241 | 1242 | [OCI8] 1243 | 1244 | ; Connection: Enables privileged connections using external 1245 | ; credentials (OCI_SYSOPER, OCI_SYSDBA) 1246 | ; http://php.net/oci8.privileged-connect 1247 | ;oci8.privileged_connect = Off 1248 | 1249 | ; Connection: The maximum number of persistent OCI8 connections per 1250 | ; process. Using -1 means no limit. 1251 | ; http://php.net/oci8.max-persistent 1252 | ;oci8.max_persistent = -1 1253 | 1254 | ; Connection: The maximum number of seconds a process is allowed to 1255 | ; maintain an idle persistent connection. Using -1 means idle 1256 | ; persistent connections will be maintained forever. 1257 | ; http://php.net/oci8.persistent-timeout 1258 | ;oci8.persistent_timeout = -1 1259 | 1260 | ; Connection: The number of seconds that must pass before issuing a 1261 | ; ping during oci_pconnect() to check the connection validity. When 1262 | ; set to 0, each oci_pconnect() will cause a ping. Using -1 disables 1263 | ; pings completely. 1264 | ; http://php.net/oci8.ping-interval 1265 | ;oci8.ping_interval = 60 1266 | 1267 | ; Connection: Set this to a user chosen connection class to be used 1268 | ; for all pooled server requests with Oracle 11g Database Resident 1269 | ; Connection Pooling (DRCP). To use DRCP, this value should be set to 1270 | ; the same string for all web servers running the same application, 1271 | ; the database pool must be configured, and the connection string must 1272 | ; specify to use a pooled server. 1273 | ;oci8.connection_class = 1274 | 1275 | ; High Availability: Using On lets PHP receive Fast Application 1276 | ; Notification (FAN) events generated when a database node fails. The 1277 | ; database must also be configured to post FAN events. 1278 | ;oci8.events = Off 1279 | 1280 | ; Tuning: This option enables statement caching, and specifies how 1281 | ; many statements to cache. Using 0 disables statement caching. 1282 | ; http://php.net/oci8.statement-cache-size 1283 | ;oci8.statement_cache_size = 20 1284 | 1285 | ; Tuning: Enables statement prefetching and sets the default number of 1286 | ; rows that will be fetched automatically after statement execution. 1287 | ; http://php.net/oci8.default-prefetch 1288 | ;oci8.default_prefetch = 100 1289 | 1290 | ; Compatibility. Using On means oci_close() will not close 1291 | ; oci_connect() and oci_new_connect() connections. 1292 | ; http://php.net/oci8.old-oci-close-semantics 1293 | ;oci8.old_oci_close_semantics = Off 1294 | 1295 | [PostgreSQL] 1296 | ; Allow or prevent persistent links. 1297 | ; http://php.net/pgsql.allow-persistent 1298 | pgsql.allow_persistent = On 1299 | 1300 | ; Detect broken persistent links always with pg_pconnect(). 1301 | ; Auto reset feature requires a little overheads. 1302 | ; http://php.net/pgsql.auto-reset-persistent 1303 | pgsql.auto_reset_persistent = Off 1304 | 1305 | ; Maximum number of persistent links. -1 means no limit. 1306 | ; http://php.net/pgsql.max-persistent 1307 | pgsql.max_persistent = -1 1308 | 1309 | ; Maximum number of links (persistent+non persistent). -1 means no limit. 1310 | ; http://php.net/pgsql.max-links 1311 | pgsql.max_links = -1 1312 | 1313 | ; Ignore PostgreSQL backends Notice message or not. 1314 | ; Notice message logging require a little overheads. 1315 | ; http://php.net/pgsql.ignore-notice 1316 | pgsql.ignore_notice = 0 1317 | 1318 | ; Log PostgreSQL backends Notice message or not. 1319 | ; Unless pgsql.ignore_notice=0, module cannot log notice message. 1320 | ; http://php.net/pgsql.log-notice 1321 | pgsql.log_notice = 0 1322 | 1323 | [bcmath] 1324 | ; Number of decimal digits for all bcmath functions. 1325 | ; http://php.net/bcmath.scale 1326 | bcmath.scale = 0 1327 | 1328 | [browscap] 1329 | ; http://php.net/browscap 1330 | ;browscap = extra/browscap.ini 1331 | 1332 | [Session] 1333 | ; Handler used to store/retrieve data. 1334 | ; http://php.net/session.save-handler 1335 | session.save_handler = files 1336 | 1337 | ; Argument passed to save_handler. In the case of files, this is the path 1338 | ; where data files are stored. Note: Windows users have to change this 1339 | ; variable in order to use PHP's session functions. 1340 | ; 1341 | ; The path can be defined as: 1342 | ; 1343 | ; session.save_path = "N;/path" 1344 | ; 1345 | ; where N is an integer. Instead of storing all the session files in 1346 | ; /path, what this will do is use subdirectories N-levels deep, and 1347 | ; store the session data in those directories. This is useful if 1348 | ; your OS has problems with many files in one directory, and is 1349 | ; a more efficient layout for servers that handle many sessions. 1350 | ; 1351 | ; NOTE 1: PHP will not create this directory structure automatically. 1352 | ; You can use the script in the ext/session dir for that purpose. 1353 | ; NOTE 2: See the section on garbage collection below if you choose to 1354 | ; use subdirectories for session storage 1355 | ; 1356 | ; The file storage module creates files using mode 600 by default. 1357 | ; You can change that by using 1358 | ; 1359 | ; session.save_path = "N;MODE;/path" 1360 | ; 1361 | ; where MODE is the octal representation of the mode. Note that this 1362 | ; does not overwrite the process's umask. 1363 | ; http://php.net/session.save-path 1364 | ;session.save_path = "/tmp" 1365 | 1366 | ; Whether to use strict session mode. 1367 | ; Strict session mode does not accept uninitialized session ID and regenerate 1368 | ; session ID if browser sends uninitialized session ID. Strict mode protects 1369 | ; applications from session fixation via session adoption vulnerability. It is 1370 | ; disabled by default for maximum compatibility, but enabling it is encouraged. 1371 | ; https://wiki.php.net/rfc/strict_sessions 1372 | session.use_strict_mode = 0 1373 | 1374 | ; Whether to use cookies. 1375 | ; http://php.net/session.use-cookies 1376 | session.use_cookies = 1 1377 | 1378 | ; http://php.net/session.cookie-secure 1379 | ;session.cookie_secure = 1380 | 1381 | ; This option forces PHP to fetch and use a cookie for storing and maintaining 1382 | ; the session id. We encourage this operation as it's very helpful in combating 1383 | ; session hijacking when not specifying and managing your own session id. It is 1384 | ; not the be-all and end-all of session hijacking defense, but it's a good start. 1385 | ; http://php.net/session.use-only-cookies 1386 | session.use_only_cookies = 1 1387 | 1388 | ; Name of the session (used as cookie name). 1389 | ; http://php.net/session.name 1390 | session.name = PHPSESSID 1391 | 1392 | ; Initialize session on request startup. 1393 | ; http://php.net/session.auto-start 1394 | session.auto_start = 0 1395 | 1396 | ; Lifetime in seconds of cookie or, if 0, until browser is restarted. 1397 | ; http://php.net/session.cookie-lifetime 1398 | session.cookie_lifetime = 0 1399 | 1400 | ; The path for which the cookie is valid. 1401 | ; http://php.net/session.cookie-path 1402 | session.cookie_path = / 1403 | 1404 | ; The domain for which the cookie is valid. 1405 | ; http://php.net/session.cookie-domain 1406 | session.cookie_domain = 1407 | 1408 | ; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript. 1409 | ; http://php.net/session.cookie-httponly 1410 | session.cookie_httponly = 1411 | 1412 | ; Handler used to serialize data. php is the standard serializer of PHP. 1413 | ; http://php.net/session.serialize-handler 1414 | session.serialize_handler = php 1415 | 1416 | ; Defines the probability that the 'garbage collection' process is started 1417 | ; on every session initialization. The probability is calculated by using 1418 | ; gc_probability/gc_divisor. Where session.gc_probability is the numerator 1419 | ; and gc_divisor is the denominator in the equation. Setting this value to 1 1420 | ; when the session.gc_divisor value is 100 will give you approximately a 1% chance 1421 | ; the gc will run on any give request. 1422 | ; Default Value: 1 1423 | ; Development Value: 1 1424 | ; Production Value: 1 1425 | ; http://php.net/session.gc-probability 1426 | session.gc_probability = 1 1427 | 1428 | ; Defines the probability that the 'garbage collection' process is started on every 1429 | ; session initialization. The probability is calculated by using the following equation: 1430 | ; gc_probability/gc_divisor. Where session.gc_probability is the numerator and 1431 | ; session.gc_divisor is the denominator in the equation. Setting this value to 1 1432 | ; when the session.gc_divisor value is 100 will give you approximately a 1% chance 1433 | ; the gc will run on any give request. Increasing this value to 1000 will give you 1434 | ; a 0.1% chance the gc will run on any give request. For high volume production servers, 1435 | ; this is a more efficient approach. 1436 | ; Default Value: 100 1437 | ; Development Value: 1000 1438 | ; Production Value: 1000 1439 | ; http://php.net/session.gc-divisor 1440 | session.gc_divisor = 1000 1441 | 1442 | ; After this number of seconds, stored data will be seen as 'garbage' and 1443 | ; cleaned up by the garbage collection process. 1444 | ; http://php.net/session.gc-maxlifetime 1445 | session.gc_maxlifetime = 1440 1446 | 1447 | ; NOTE: If you are using the subdirectory option for storing session files 1448 | ; (see session.save_path above), then garbage collection does *not* 1449 | ; happen automatically. You will need to do your own garbage 1450 | ; collection through a shell script, cron entry, or some other method. 1451 | ; For example, the following script would is the equivalent of 1452 | ; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): 1453 | ; find /path/to/sessions -cmin +24 -type f | xargs rm 1454 | 1455 | ; Check HTTP Referer to invalidate externally stored URLs containing ids. 1456 | ; HTTP_REFERER has to contain this substring for the session to be 1457 | ; considered as valid. 1458 | ; http://php.net/session.referer-check 1459 | session.referer_check = 1460 | 1461 | ; Set to {nocache,private,public,} to determine HTTP caching aspects 1462 | ; or leave this empty to avoid sending anti-caching headers. 1463 | ; http://php.net/session.cache-limiter 1464 | session.cache_limiter = nocache 1465 | 1466 | ; Document expires after n minutes. 1467 | ; http://php.net/session.cache-expire 1468 | session.cache_expire = 180 1469 | 1470 | ; trans sid support is disabled by default. 1471 | ; Use of trans sid may risk your users' security. 1472 | ; Use this option with caution. 1473 | ; - User may send URL contains active session ID 1474 | ; to other person via. email/irc/etc. 1475 | ; - URL that contains active session ID may be stored 1476 | ; in publicly accessible computer. 1477 | ; - User may access your site with the same session ID 1478 | ; always using URL stored in browser's history or bookmarks. 1479 | ; http://php.net/session.use-trans-sid 1480 | session.use_trans_sid = 0 1481 | 1482 | ; Set session ID character length. This value could be between 22 to 256. 1483 | ; Shorter length than default is supported only for compatibility reason. 1484 | ; Users should use 32 or more chars. 1485 | ; http://php.net/session.sid-length 1486 | ; Default Value: 32 1487 | ; Development Value: 26 1488 | ; Production Value: 26 1489 | session.sid_length = 26 1490 | 1491 | ; The URL rewriter will look for URLs in a defined set of HTML tags. 1492 | ;
is special; if you include them here, the rewriter will 1493 | ; add a hidden field with the info which is otherwise appended 1494 | ; to URLs. tag's action attribute URL will not be modified 1495 | ; unless it is specified. 1496 | ; Note that all valid entries require a "=", even if no value follows. 1497 | ; Default Value: "a=href,area=href,frame=src,form=" 1498 | ; Development Value: "a=href,area=href,frame=src,form=" 1499 | ; Production Value: "a=href,area=href,frame=src,form=" 1500 | ; http://php.net/url-rewriter.tags 1501 | session.trans_sid_tags = "a=href,area=href,frame=src,form=" 1502 | 1503 | ; URL rewriter does not rewrite absolute URLs by default. 1504 | ; To enable rewrites for absolute pathes, target hosts must be specified 1505 | ; at RUNTIME. i.e. use ini_set() 1506 | ; tags is special. PHP will check action attribute's URL regardless 1507 | ; of session.trans_sid_tags setting. 1508 | ; If no host is defined, HTTP_HOST will be used for allowed host. 1509 | ; Example value: php.net,www.php.net,wiki.php.net 1510 | ; Use "," for multiple hosts. No spaces are allowed. 1511 | ; Default Value: "" 1512 | ; Development Value: "" 1513 | ; Production Value: "" 1514 | ;session.trans_sid_hosts="" 1515 | 1516 | ; Define how many bits are stored in each character when converting 1517 | ; the binary hash data to something readable. 1518 | ; Possible values: 1519 | ; 4 (4 bits: 0-9, a-f) 1520 | ; 5 (5 bits: 0-9, a-v) 1521 | ; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") 1522 | ; Default Value: 4 1523 | ; Development Value: 5 1524 | ; Production Value: 5 1525 | ; http://php.net/session.hash-bits-per-character 1526 | session.sid_bits_per_character = 5 1527 | 1528 | ; Enable upload progress tracking in $_SESSION 1529 | ; Default Value: On 1530 | ; Development Value: On 1531 | ; Production Value: On 1532 | ; http://php.net/session.upload-progress.enabled 1533 | ;session.upload_progress.enabled = On 1534 | 1535 | ; Cleanup the progress information as soon as all POST data has been read 1536 | ; (i.e. upload completed). 1537 | ; Default Value: On 1538 | ; Development Value: On 1539 | ; Production Value: On 1540 | ; http://php.net/session.upload-progress.cleanup 1541 | ;session.upload_progress.cleanup = On 1542 | 1543 | ; A prefix used for the upload progress key in $_SESSION 1544 | ; Default Value: "upload_progress_" 1545 | ; Development Value: "upload_progress_" 1546 | ; Production Value: "upload_progress_" 1547 | ; http://php.net/session.upload-progress.prefix 1548 | ;session.upload_progress.prefix = "upload_progress_" 1549 | 1550 | ; The index name (concatenated with the prefix) in $_SESSION 1551 | ; containing the upload progress information 1552 | ; Default Value: "PHP_SESSION_UPLOAD_PROGRESS" 1553 | ; Development Value: "PHP_SESSION_UPLOAD_PROGRESS" 1554 | ; Production Value: "PHP_SESSION_UPLOAD_PROGRESS" 1555 | ; http://php.net/session.upload-progress.name 1556 | ;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" 1557 | 1558 | ; How frequently the upload progress should be updated. 1559 | ; Given either in percentages (per-file), or in bytes 1560 | ; Default Value: "1%" 1561 | ; Development Value: "1%" 1562 | ; Production Value: "1%" 1563 | ; http://php.net/session.upload-progress.freq 1564 | ;session.upload_progress.freq = "1%" 1565 | 1566 | ; The minimum delay between updates, in seconds 1567 | ; Default Value: 1 1568 | ; Development Value: 1 1569 | ; Production Value: 1 1570 | ; http://php.net/session.upload-progress.min-freq 1571 | ;session.upload_progress.min_freq = "1" 1572 | 1573 | ; Only write session data when session data is changed. Enabled by default. 1574 | ; http://php.net/session.lazy-write 1575 | ;session.lazy_write = On 1576 | 1577 | [Assertion] 1578 | ; Switch whether to compile assertions at all (to have no overhead at run-time) 1579 | ; -1: Do not compile at all 1580 | ; 0: Jump over assertion at run-time 1581 | ; 1: Execute assertions 1582 | ; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) 1583 | ; Default Value: 1 1584 | ; Development Value: 1 1585 | ; Production Value: -1 1586 | ; http://php.net/zend.assertions 1587 | zend.assertions = 1 1588 | 1589 | ; Assert(expr); active by default. 1590 | ; http://php.net/assert.active 1591 | ;assert.active = On 1592 | 1593 | ; Throw an AssertationException on failed assertions 1594 | ; http://php.net/assert.exception 1595 | ;assert.exception = On 1596 | 1597 | ; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active) 1598 | ; http://php.net/assert.warning 1599 | ;assert.warning = On 1600 | 1601 | ; Don't bail out by default. 1602 | ; http://php.net/assert.bail 1603 | ;assert.bail = Off 1604 | 1605 | ; User-function to be called if an assertion fails. 1606 | ; http://php.net/assert.callback 1607 | ;assert.callback = 0 1608 | 1609 | ; Eval the expression with current error_reporting(). Set to true if you want 1610 | ; error_reporting(0) around the eval(). 1611 | ; http://php.net/assert.quiet-eval 1612 | ;assert.quiet_eval = 0 1613 | 1614 | [COM] 1615 | ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs 1616 | ; http://php.net/com.typelib-file 1617 | ;com.typelib_file = 1618 | 1619 | ; allow Distributed-COM calls 1620 | ; http://php.net/com.allow-dcom 1621 | ;com.allow_dcom = true 1622 | 1623 | ; autoregister constants of a components typlib on com_load() 1624 | ; http://php.net/com.autoregister-typelib 1625 | ;com.autoregister_typelib = true 1626 | 1627 | ; register constants casesensitive 1628 | ; http://php.net/com.autoregister-casesensitive 1629 | ;com.autoregister_casesensitive = false 1630 | 1631 | ; show warnings on duplicate constant registrations 1632 | ; http://php.net/com.autoregister-verbose 1633 | ;com.autoregister_verbose = true 1634 | 1635 | ; The default character set code-page to use when passing strings to and from COM objects. 1636 | ; Default: system ANSI code page 1637 | ;com.code_page= 1638 | 1639 | [mbstring] 1640 | ; language for internal character representation. 1641 | ; This affects mb_send_mail() and mbstring.detect_order. 1642 | ; http://php.net/mbstring.language 1643 | ;mbstring.language = Japanese 1644 | 1645 | ; Use of this INI entry is deprecated, use global internal_encoding instead. 1646 | ; internal/script encoding. 1647 | ; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*) 1648 | ; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. 1649 | ; The precedence is: default_charset < internal_encoding < iconv.internal_encoding 1650 | ;mbstring.internal_encoding = 1651 | 1652 | ; Use of this INI entry is deprecated, use global input_encoding instead. 1653 | ; http input encoding. 1654 | ; mbstring.encoding_traslation = On is needed to use this setting. 1655 | ; If empty, default_charset or input_encoding or mbstring.input is used. 1656 | ; The precedence is: default_charset < intput_encoding < mbsting.http_input 1657 | ; http://php.net/mbstring.http-input 1658 | ;mbstring.http_input = 1659 | 1660 | ; Use of this INI entry is deprecated, use global output_encoding instead. 1661 | ; http output encoding. 1662 | ; mb_output_handler must be registered as output buffer to function. 1663 | ; If empty, default_charset or output_encoding or mbstring.http_output is used. 1664 | ; The precedence is: default_charset < output_encoding < mbstring.http_output 1665 | ; To use an output encoding conversion, mbstring's output handler must be set 1666 | ; otherwise output encoding conversion cannot be performed. 1667 | ; http://php.net/mbstring.http-output 1668 | ;mbstring.http_output = 1669 | 1670 | ; enable automatic encoding translation according to 1671 | ; mbstring.internal_encoding setting. Input chars are 1672 | ; converted to internal encoding by setting this to On. 1673 | ; Note: Do _not_ use automatic encoding translation for 1674 | ; portable libs/applications. 1675 | ; http://php.net/mbstring.encoding-translation 1676 | ;mbstring.encoding_translation = Off 1677 | 1678 | ; automatic encoding detection order. 1679 | ; "auto" detect order is changed according to mbstring.language 1680 | ; http://php.net/mbstring.detect-order 1681 | ;mbstring.detect_order = auto 1682 | 1683 | ; substitute_character used when character cannot be converted 1684 | ; one from another 1685 | ; http://php.net/mbstring.substitute-character 1686 | ;mbstring.substitute_character = none 1687 | 1688 | ; overload(replace) single byte functions by mbstring functions. 1689 | ; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), 1690 | ; etc. Possible values are 0,1,2,4 or combination of them. 1691 | ; For example, 7 for overload everything. 1692 | ; 0: No overload 1693 | ; 1: Overload mail() function 1694 | ; 2: Overload str*() functions 1695 | ; 4: Overload ereg*() functions 1696 | ; http://php.net/mbstring.func-overload 1697 | ;mbstring.func_overload = 0 1698 | 1699 | ; enable strict encoding detection. 1700 | ; Default: Off 1701 | ;mbstring.strict_detection = On 1702 | 1703 | ; This directive specifies the regex pattern of content types for which mb_output_handler() 1704 | ; is activated. 1705 | ; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) 1706 | ;mbstring.http_output_conv_mimetype= 1707 | 1708 | [gd] 1709 | ; Tell the jpeg decode to ignore warnings and try to create 1710 | ; a gd image. The warning will then be displayed as notices 1711 | ; disabled by default 1712 | ; http://php.net/gd.jpeg-ignore-warning 1713 | ;gd.jpeg_ignore_warning = 1 1714 | 1715 | [exif] 1716 | ; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. 1717 | ; With mbstring support this will automatically be converted into the encoding 1718 | ; given by corresponding encode setting. When empty mbstring.internal_encoding 1719 | ; is used. For the decode settings you can distinguish between motorola and 1720 | ; intel byte order. A decode setting cannot be empty. 1721 | ; http://php.net/exif.encode-unicode 1722 | ;exif.encode_unicode = ISO-8859-15 1723 | 1724 | ; http://php.net/exif.decode-unicode-motorola 1725 | ;exif.decode_unicode_motorola = UCS-2BE 1726 | 1727 | ; http://php.net/exif.decode-unicode-intel 1728 | ;exif.decode_unicode_intel = UCS-2LE 1729 | 1730 | ; http://php.net/exif.encode-jis 1731 | ;exif.encode_jis = 1732 | 1733 | ; http://php.net/exif.decode-jis-motorola 1734 | ;exif.decode_jis_motorola = JIS 1735 | 1736 | ; http://php.net/exif.decode-jis-intel 1737 | ;exif.decode_jis_intel = JIS 1738 | 1739 | [Tidy] 1740 | ; The path to a default tidy configuration file to use when using tidy 1741 | ; http://php.net/tidy.default-config 1742 | ;tidy.default_config = /usr/local/lib/php/default.tcfg 1743 | 1744 | ; Should tidy clean and repair output automatically? 1745 | ; WARNING: Do not use this option if you are generating non-html content 1746 | ; such as dynamic images 1747 | ; http://php.net/tidy.clean-output 1748 | tidy.clean_output = Off 1749 | 1750 | [soap] 1751 | ; Enables or disables WSDL caching feature. 1752 | ; http://php.net/soap.wsdl-cache-enabled 1753 | soap.wsdl_cache_enabled=1 1754 | 1755 | ; Sets the directory name where SOAP extension will put cache files. 1756 | ; http://php.net/soap.wsdl-cache-dir 1757 | soap.wsdl_cache_dir="/tmp" 1758 | 1759 | ; (time to live) Sets the number of second while cached file will be used 1760 | ; instead of original one. 1761 | ; http://php.net/soap.wsdl-cache-ttl 1762 | soap.wsdl_cache_ttl=86400 1763 | 1764 | ; Sets the size of the cache limit. (Max. number of WSDL files to cache) 1765 | soap.wsdl_cache_limit = 5 1766 | 1767 | [sysvshm] 1768 | ; A default size of the shared memory segment 1769 | ;sysvshm.init_mem = 10000 1770 | 1771 | [ldap] 1772 | ; Sets the maximum number of open links or -1 for unlimited. 1773 | ldap.max_links = -1 1774 | 1775 | [dba] 1776 | ;dba.default_handler= 1777 | 1778 | [opcache] 1779 | ; Determines if Zend OPCache is enabled 1780 | ;opcache.enable=1 1781 | 1782 | ; Determines if Zend OPCache is enabled for the CLI version of PHP 1783 | ;opcache.enable_cli=0 1784 | 1785 | ; The OPcache shared memory storage size. 1786 | ;opcache.memory_consumption=128 1787 | 1788 | ; The amount of memory for interned strings in Mbytes. 1789 | ;opcache.interned_strings_buffer=8 1790 | 1791 | ; The maximum number of keys (scripts) in the OPcache hash table. 1792 | ; Only numbers between 200 and 1000000 are allowed. 1793 | ;opcache.max_accelerated_files=10000 1794 | 1795 | ; The maximum percentage of "wasted" memory until a restart is scheduled. 1796 | ;opcache.max_wasted_percentage=5 1797 | 1798 | ; When this directive is enabled, the OPcache appends the current working 1799 | ; directory to the script key, thus eliminating possible collisions between 1800 | ; files with the same name (basename). Disabling the directive improves 1801 | ; performance, but may break existing applications. 1802 | ;opcache.use_cwd=1 1803 | 1804 | ; When disabled, you must reset the OPcache manually or restart the 1805 | ; webserver for changes to the filesystem to take effect. 1806 | ;opcache.validate_timestamps=1 1807 | 1808 | ; How often (in seconds) to check file timestamps for changes to the shared 1809 | ; memory storage allocation. ("1" means validate once per second, but only 1810 | ; once per request. "0" means always validate) 1811 | ;opcache.revalidate_freq=2 1812 | 1813 | ; Enables or disables file search in include_path optimization 1814 | ;opcache.revalidate_path=0 1815 | 1816 | ; If disabled, all PHPDoc comments are dropped from the code to reduce the 1817 | ; size of the optimized code. 1818 | ;opcache.save_comments=1 1819 | 1820 | ; Allow file existence override (file_exists, etc.) performance feature. 1821 | ;opcache.enable_file_override=0 1822 | 1823 | ; A bitmask, where each bit enables or disables the appropriate OPcache 1824 | ; passes 1825 | ;opcache.optimization_level=0xffffffff 1826 | 1827 | ;opcache.inherited_hack=1 1828 | ;opcache.dups_fix=0 1829 | 1830 | ; The location of the OPcache blacklist file (wildcards allowed). 1831 | ; Each OPcache blacklist file is a text file that holds the names of files 1832 | ; that should not be accelerated. The file format is to add each filename 1833 | ; to a new line. The filename may be a full path or just a file prefix 1834 | ; (i.e., /var/www/x blacklists all the files and directories in /var/www 1835 | ; that start with 'x'). Line starting with a ; are ignored (comments). 1836 | ;opcache.blacklist_filename= 1837 | 1838 | ; Allows exclusion of large files from being cached. By default all files 1839 | ; are cached. 1840 | ;opcache.max_file_size=0 1841 | 1842 | ; Check the cache checksum each N requests. 1843 | ; The default value of "0" means that the checks are disabled. 1844 | ;opcache.consistency_checks=0 1845 | 1846 | ; How long to wait (in seconds) for a scheduled restart to begin if the cache 1847 | ; is not being accessed. 1848 | ;opcache.force_restart_timeout=180 1849 | 1850 | ; OPcache error_log file name. Empty string assumes "stderr". 1851 | ;opcache.error_log= 1852 | 1853 | ; All OPcache errors go to the Web server log. 1854 | ; By default, only fatal errors (level 0) or errors (level 1) are logged. 1855 | ; You can also enable warnings (level 2), info messages (level 3) or 1856 | ; debug messages (level 4). 1857 | ;opcache.log_verbosity_level=1 1858 | 1859 | ; Preferred Shared Memory back-end. Leave empty and let the system decide. 1860 | ;opcache.preferred_memory_model= 1861 | 1862 | ; Protect the shared memory from unexpected writing during script execution. 1863 | ; Useful for internal debugging only. 1864 | ;opcache.protect_memory=0 1865 | 1866 | ; Allows calling OPcache API functions only from PHP scripts which path is 1867 | ; started from specified string. The default "" means no restriction 1868 | ;opcache.restrict_api= 1869 | 1870 | ; Mapping base of shared memory segments (for Windows only). All the PHP 1871 | ; processes have to map shared memory into the same address space. This 1872 | ; directive allows to manually fix the "Unable to reattach to base address" 1873 | ; errors. 1874 | ;opcache.mmap_base= 1875 | 1876 | ; Enables and sets the second level cache directory. 1877 | ; It should improve performance when SHM memory is full, at server restart or 1878 | ; SHM reset. The default "" disables file based caching. 1879 | ;opcache.file_cache= 1880 | 1881 | ; Enables or disables opcode caching in shared memory. 1882 | ;opcache.file_cache_only=0 1883 | 1884 | ; Enables or disables checksum validation when script loaded from file cache. 1885 | ;opcache.file_cache_consistency_checks=1 1886 | 1887 | ; Implies opcache.file_cache_only=1 for a certain process that failed to 1888 | ; reattach to the shared memory (for Windows only). Explicitly enabled file 1889 | ; cache is required. 1890 | ;opcache.file_cache_fallback=1 1891 | 1892 | ; Enables or disables copying of PHP code (text segment) into HUGE PAGES. 1893 | ; This should improve performance, but requires appropriate OS configuration. 1894 | ;opcache.huge_code_pages=0 1895 | 1896 | ; Validate cached file permissions. 1897 | ;opcache.validate_permission=0 1898 | 1899 | ; Prevent name collisions in chroot'ed environment. 1900 | ;opcache.validate_root=0 1901 | 1902 | ; If specified, it produces opcode dumps for debugging different stages of 1903 | ; optimizations. 1904 | ;opcache.opt_debug_level=0 1905 | 1906 | [curl] 1907 | ; A default value for the CURLOPT_CAINFO option. This is required to be an 1908 | ; absolute path. 1909 | ;curl.cainfo = 1910 | 1911 | [openssl] 1912 | ; The location of a Certificate Authority (CA) file on the local filesystem 1913 | ; to use when verifying the identity of SSL/TLS peers. Most users should 1914 | ; not specify a value for this directive as PHP will attempt to use the 1915 | ; OS-managed cert stores in its absence. If specified, this value may still 1916 | ; be overridden on a per-stream basis via the "cafile" SSL stream context 1917 | ; option. 1918 | ;openssl.cafile= 1919 | 1920 | ; If openssl.cafile is not specified or if the CA file is not found, the 1921 | ; directory pointed to by openssl.capath is searched for a suitable 1922 | ; certificate. This value must be a correctly hashed certificate directory. 1923 | ; Most users should not specify a value for this directive as PHP will 1924 | ; attempt to use the OS-managed cert stores in its absence. If specified, 1925 | ; this value may still be overridden on a per-stream basis via the "capath" 1926 | ; SSL stream context option. 1927 | ;openssl.capath= 1928 | 1929 | ; Local Variables: 1930 | ; tab-width: 4 1931 | ; End: 1932 | 1933 | [xdebug] 1934 | xdebug.remote_host=host.docker.internal 1935 | xdebug.remote_port=9000 1936 | xdebug.remote_connect_back=0 1937 | 1938 | xdebug.idekey=PHPSTORM 1939 | xdebug.default_enable=1 1940 | xdebug.remote_enable=1 1941 | xdebug.remote_handler=dbgp 1942 | -------------------------------------------------------------------------------- /.docker/scripts/setup.sh: -------------------------------------------------------------------------------- 1 | bin/console doctrine:database:create 2 | bin/console doctrine:schema:update --force 3 | bin/console doctrine:fixtures:load -------------------------------------------------------------------------------- /.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=b4a86337d2e2469bea677f02e96c5f50 8 | #TRUSTED_PROXIES=127.0.0.1,127.0.0.2 9 | #TRUSTED_HOSTS=localhost,example.com 10 | ###< symfony/framework-bundle ### 11 | 12 | ###> doctrine/doctrine-bundle ### 13 | # Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url 14 | # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" 15 | # Configure your db driver and server_version in config/packages/doctrine.yaml 16 | #DATABASE_DRIVER=pdo_sqlite 17 | #DATABASE_SERVER_VERSION=3.15 18 | #DATABASE_URL=sqlite:///%kernel.project_dir%/var/database.sqlite 19 | DATABASE_DRIVER=pdo_mysql 20 | DATABASE_SERVER_VERSION=5.7 21 | DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name 22 | ###< doctrine/doctrine-bundle ### 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | 4 | ###> symfony/framework-bundle ### 5 | .env 6 | /public/bundles/ 7 | /var/ 8 | /vendor/ 9 | ###< symfony/framework-bundle ### 10 | # Cache and logs (Symfony3) 11 | /var/cache/* 12 | /var/logs/* 13 | !var/cache/.gitkeep 14 | !var/logs/.gitkeep 15 | 16 | # Managed by Composer 17 | /var/bootstrap.php.cache 18 | /bin/* 19 | !bin/console 20 | !bin/symfony_requirements 21 | /vendor/ 22 | 23 | # Assets and user uploads 24 | /web/bundles/ 25 | /web/uploads/ 26 | 27 | # PHPUnit 28 | /app/phpunit.xml 29 | /phpunit.xml 30 | 31 | # Build data 32 | /build/ 33 | 34 | # Composer PHAR 35 | /composer.phar 36 | 37 | 38 | ###> symfony/phpunit-bridge ### 39 | .phpunit 40 | /phpunit.xml 41 | ###< symfony/phpunit-bridge ### 42 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Abenezer Mamo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /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 = ($_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 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "project", 3 | "license": "proprietary", 4 | "require": { 5 | "php": "^7.1.3", 6 | "ext-iconv": "*", 7 | "ext-pdo_sqlite": "^7.3", 8 | "doctrine/doctrine-bundle": "dev-master", 9 | "doctrine/orm": "^2.6", 10 | "friendsofsymfony/oauth-server-bundle": "dev-master", 11 | "nelmio/api-doc-bundle": "^3.0", 12 | "pagerfanta/pagerfanta": "^1.0", 13 | "samj/fractal-bundle": "^2.1", 14 | "sensio/framework-extra-bundle": "^5.1", 15 | "stof/doctrine-extensions-bundle": "^1.3", 16 | "symfony/asset": "^4.0", 17 | "symfony/console": "^4.0", 18 | "symfony/flex": "^1.0", 19 | "symfony/form": "^4.0", 20 | "symfony/framework-bundle": "^4.0", 21 | "symfony/templating": "^4.0", 22 | "symfony/translation": "^4.0", 23 | "symfony/twig-bundle": "^4.0", 24 | "symfony/validator": "^4.0", 25 | "symfony/var-dumper": "^4.0", 26 | "symfony/yaml": "^4.0" 27 | }, 28 | "require-dev": { 29 | "doctrine/doctrine-fixtures-bundle": "^3.0", 30 | "symfony/browser-kit": "^4.0", 31 | "symfony/dotenv": "^4.0", 32 | "symfony/maker-bundle": "^1.3", 33 | "fzaninotto/faker": "^1.4", 34 | "symfony/phpunit-bridge": "^4.0", 35 | "symfony/profiler-pack": "^1.0" 36 | }, 37 | "config": { 38 | "preferred-install": { 39 | "*": "dist" 40 | }, 41 | "sort-packages": true 42 | }, 43 | "autoload": { 44 | "psr-4": { 45 | "App\\": "src/" 46 | } 47 | }, 48 | "autoload-dev": { 49 | "psr-4": { 50 | "App\\Tests\\": "tests/" 51 | } 52 | }, 53 | "replace": { 54 | "symfony/polyfill-iconv": "*", 55 | "symfony/polyfill-php71": "*", 56 | "symfony/polyfill-php70": "*", 57 | "symfony/polyfill-php56": "*" 58 | }, 59 | "scripts": { 60 | "auto-scripts": { 61 | "cache:clear": "symfony-cmd", 62 | "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd" 63 | }, 64 | "post-install-cmd": [ 65 | "@auto-scripts" 66 | ], 67 | "post-update-cmd": [ 68 | "@auto-scripts" 69 | ] 70 | }, 71 | "conflict": { 72 | "symfony/symfony": "*" 73 | }, 74 | "extra": { 75 | "symfony": { 76 | "id": "01C88DV2M2ZT94PGZ7RB548FT1", 77 | "allow-contrib": false 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /config/bundles.php: -------------------------------------------------------------------------------- 1 | ['all' => true], 5 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], 6 | Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true], 7 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], 8 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], 9 | FOS\OAuthServerBundle\FOSOAuthServerBundle::class => ['all' => true], 10 | Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true], 11 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], 12 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], 13 | Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], 14 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], 15 | ]; 16 | -------------------------------------------------------------------------------- /config/packages/dev/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: true 4 | -------------------------------------------------------------------------------- /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: env(DATABASE_DRIVER) 12 | server_version: env(DATABASE_SERVER_VERSION) 13 | charset: utf8mb4 14 | 15 | url: '%env(resolve:DATABASE_URL)%' 16 | 17 | orm: 18 | auto_generate_proxy_classes: '%kernel.debug%' 19 | naming_strategy: doctrine.orm.naming_strategy.underscore 20 | auto_mapping: true 21 | mappings: 22 | Authorization: #FosOauthBundle 23 | is_bundle: false 24 | type: annotation 25 | dir: '%kernel.project_dir%/src/Authorization/Entity/Oauth2' 26 | prefix: 'App\Authorization\Entity\Oauth2' 27 | alias: App 28 | Project: 29 | is_bundle: false 30 | type: yml 31 | dir: '%kernel.project_dir%/src/Project/Resources/doctrine/mapping' 32 | prefix: 'App\Project\Domain' 33 | alias: App -------------------------------------------------------------------------------- /config/packages/fos_oauth_server.yaml: -------------------------------------------------------------------------------- 1 | # app/config/config.yml 2 | fos_oauth_server: 3 | db_driver: orm # Drivers available: orm, mongodb, or propel 4 | client_class: App\Authorization\Entity\Oauth2\Client 5 | access_token_class: App\Authorization\Entity\Oauth2\AccessToken 6 | refresh_token_class: App\Authorization\Entity\Oauth2\RefreshToken 7 | auth_code_class: App\Authorization\Entity\Oauth2\AuthCode -------------------------------------------------------------------------------- /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 | templating: 32 | engines: ['twig'] -------------------------------------------------------------------------------- /config/packages/nelmio_api_doc.yaml: -------------------------------------------------------------------------------- 1 | nelmio_api_doc: 2 | documentation: 3 | info: 4 | title: Project Article 5 | description: Article Api with Symfony DDD! 6 | version: 1.0.0 7 | securityDefinitions: 8 | api_key: 9 | type: apiKey 10 | description: Your Json Web Token 11 | name: authorization 12 | in: header 13 | security: 14 | - api_key: [] 15 | 16 | 17 | areas: # to filter documented routes 18 | path_patterns: 19 | - ^/api(?!/doc$) # Accepts routes under /api except /api/doc 20 | - ^/oauth # Accepts routes under /oauth 21 | -------------------------------------------------------------------------------- /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/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 | # activate different ways to authenticate 10 | 11 | # http_basic: true 12 | # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate 13 | 14 | # form_login: true 15 | # https://symfony.com/doc/current/security/form_login_setup.html 16 | 17 | api_doc: 18 | pattern: ^/api/doc 19 | security: false 20 | anonymous: true 21 | 22 | oauth_token: 23 | pattern: ^/oauth/v2/token 24 | security: false 25 | 26 | oauth_authorize: 27 | pattern: ^/oauth/v2/auth 28 | security: false 29 | 30 | search: 31 | pattern: ^/api/search 32 | anonymous: true 33 | security : false 34 | 35 | api: 36 | pattern: ^/api 37 | fos_oauth: true 38 | stateless: true 39 | security: true 40 | anonymous: false # can be omitted as its default value 41 | 42 | 43 | # Add your favorite authentication process here 44 | # Easy way to control access for large sections of your site 45 | # Note: Only the *first* access control that matches will be used 46 | access_control: 47 | # - { path: ^/admin, roles: ROLE_ADMIN } 48 | # - { path: ^/profile, roles: ROLE_USER } 49 | -------------------------------------------------------------------------------- /config/packages/test/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 | 15 | # With Symfony 3.3, remove the `resolve:` prefix 16 | url: 'mysql://root:twiscard@192.168.99.100:8004/symfony4_test' 17 | 18 | orm: 19 | auto_generate_proxy_classes: '%kernel.debug%' 20 | naming_strategy: doctrine.orm.naming_strategy.underscore 21 | auto_mapping: true 22 | mappings: 23 | Authorization: #FosOauthBundle 24 | is_bundle: false 25 | type: annotation 26 | dir: '%kernel.project_dir%/src/Authorization/Entity/Oauth2' 27 | prefix: 'App\Authorization\Entity\Oauth2' 28 | alias: App 29 | Project: 30 | is_bundle: false 31 | type: yml 32 | dir: '%kernel.project_dir%/src/Project/Resources/doctrine/mapping' 33 | prefix: 'App\Project\Domain' 34 | alias: App -------------------------------------------------------------------------------- /config/packages/test/framework.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | test: true 3 | session: 4 | storage_id: session.storage.mock_file 5 | -------------------------------------------------------------------------------- /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 | NelmioApiDocBundle: 2 | resource: "@NelmioApiDocBundle/Resources/config/routing/swaggerui.xml" 3 | prefix: / 4 | 5 | project: 6 | # loads routes from the YAML or XML files found in some bundle directory 7 | resource: '../src/Project/Resources/routing/' 8 | type: directory 9 | 10 | authorization: 11 | resource: '../src/Authorization/Controller/' 12 | type: annotation 13 | -------------------------------------------------------------------------------- /config/routes/annotations.yaml: -------------------------------------------------------------------------------- 1 | #controllers: 2 | # resource: ../../src/Controller/ 3 | # type: annotation 4 | -------------------------------------------------------------------------------- /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/routes/nelmio_api_doc.yaml: -------------------------------------------------------------------------------- 1 | # Requires the Asset component and the Twig bundle 2 | app.swagger_ui: 3 | path: /api/doc 4 | methods: GET 5 | defaults: { _controller: nelmio_api_doc.controller.swagger_ui } 6 | 7 | # To expose your documentation as JSON 8 | #app.swagger: 9 | # path: /api/doc.json 10 | # methods: GET 11 | # defaults: { _controller: nelmio_api_doc.controller.swagger } 12 | -------------------------------------------------------------------------------- /config/routes/oauth.yaml: -------------------------------------------------------------------------------- 1 | # app/config/routing.yml 2 | fos_oauth_server_token: 3 | resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml" 4 | 5 | fos_oauth_server_authorize: 6 | resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml" -------------------------------------------------------------------------------- /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 | siteUrl: 'http://127.0.0.1:9002/api' 6 | 7 | services: 8 | # default configuration for services in *this* file 9 | _defaults: 10 | autowire: true # Automatically injects dependencies in your services. 11 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. 12 | public: false # Allows optimizing the container by removing unused services; this also means 13 | # fetching services directly from the container via $container->get() won't work. 14 | # The best practice is to be explicit about your dependencies anyway. 15 | 16 | # # makes classes in src/ available to be used as services 17 | # # this creates a service per class whose id is the fully-qualified class name 18 | # App\: 19 | # resource: '../src/*' 20 | # exclude: '../src/{Entity,Migrations,Tests,Kernel.php}' 21 | # 22 | # # controllers are imported separately to make sure services can be injected 23 | # # as action arguments even if you don't extend any base controller class 24 | App\Project\Http\Controller\: 25 | resource: '../src/Project/Http/Controller' 26 | tags: ['controller.service_arguments'] 27 | 28 | ## Register commands 29 | App\Project\Console\: 30 | resource: '../src/Project/Console' 31 | 32 | App\Authorization\Console\: 33 | resource: '../src/Authorization/Console' 34 | 35 | ## Fixtures 36 | App\DataFixtures\: 37 | resource: '../src/DataFixtures' 38 | tags: ['doctrine.fixture.orm'] 39 | 40 | # add more service definitions when explicit configuration is needed 41 | # please note that last definitions always *replace* previous ones 42 | 43 | 44 | # fractal.service.on.kernel.response: 45 | # class: App\Project\App\EventListenter\KernelResponseListener 46 | # arguments: ["@project.fractal.manager"] 47 | # tags: 48 | # - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse } 49 | imports: 50 | - { resource: "../src/Project/Resources/config/services.yaml"} 51 | 52 | 53 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | 5 | php: 6 | build: .docker/php 7 | working_dir: /var/www/html 8 | volumes: 9 | - ./:/var/www/html 10 | environment: 11 | DATABASE_DRIVER: "pdo_sqlite" 12 | DATABASE_SERVER_VERSION: "3.15" 13 | DATABASE_URL: "sqlite:///%kernel.project_dir%/var/database.sqlite" 14 | command: bash -c "composer install && 15 | bash ./.docker/scripts/setup.sh && 16 | php -d variables_order=EGPCS -S 0.0.0.0:80 -t public" 17 | ports: 18 | - 80:80 19 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | tests/ 24 | 25 | 26 | 27 | 28 | 29 | ./src/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | load(__DIR__.'/../.env'); 16 | } 17 | 18 | $env = $_SERVER['APP_ENV'] ?? 'dev'; 19 | $debug = $_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.md: -------------------------------------------------------------------------------- 1 | ### Symfony 4 DDD Approach 2 | 3 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/bencagri/symfony4-ddd/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/bencagri/symfony4-ddd/?branch=master) 4 | [![Build Status](https://scrutinizer-ci.com/g/bencagri/symfony4-ddd/badges/build.png?b=master)](https://scrutinizer-ci.com/g/bencagri/symfony4-ddd/build-status/master) 5 | 6 | Article application with Symfony 4 and DDD Approach. 7 | 8 | Advantages of Domain-Driven Design 9 | 10 | * Eases Communication: With an early emphasis on establishing a common and ubiquitous language related to the domain model of the project, teams will often find communication throughout the entire development life cycle to be much easier. Typically, DDD will require less technical jargon when discussing aspects of the application, since the ubiquitous language established early on will likely define simpler terms to refer to those more technical aspects. 11 | * Improves Flexibility: Since DDD is so heavily based around the concepts of object-oriented analysis and design, nearly everything within the domain model will be based on an object and will, therefore, be quite modular and encapsulated. This allows for various components, or even the entire system as a whole, to be altered and improved on a regular, continuous basis. 12 | * Emphasizes Domain Over Interface: Since DDD is the practice of building around the concepts of domain and what the domain experts within the project advise, DDD will often produce applications that are accurately suited for and representative of the domain at hand, as opposed to those applications which emphasize the UI/UX first and foremost. While an obvious balance is required, the focus on domain means that a DDD approach can produce a product that resonates well with the audience associated with that domain. 13 | 14 | 15 | [Read more about DDD](https://airbrake.io/blog/software-design/domain-driven-design) 16 | 17 | #### Folder Structure 18 | 19 | ``` 20 | ├── bin 21 | ├── config 22 | │   ├── packages 23 | │   │   ├── dev 24 | │   │   ├── prod 25 | │   │   └── test 26 | │   └── routes 27 | │   └── dev 28 | ├── public 29 | ├── src 30 | │   ├── Authorization 31 | │   │   ├── Console 32 | │   │   ├── Controller 33 | │   │   └── Entity 34 | │   │   └── Oauth2 35 | │   ├── DataFixtures 36 | │   └── Project 37 | │   ├── App 38 | │      │   ├── EventListener 39 | │      │   ├── Interface 40 | │      │   ├── Support 41 | │      │   └── Trait 42 | │      ├── Console 43 | │      ├── Domain 44 | │      │   ├── Article 45 | │      │   │   └── Entity 46 | │      │   └── User 47 | │      │   ├── Contract 48 | │      │   └── Entity 49 | │      ├── Http 50 | │      │   └── Controller 51 | │      ├── Infrastructure 52 | │      │   ├── Article 53 | │      │   └── User 54 | │      └── Resources 55 | │      ├── config 56 | │      ├── doctrine 57 | │      │   └── mapping 58 | │      └── routing 59 | ├── templates 60 | ├── tests 61 | │   ├── functional 62 | │   ├── integration 63 | │   └── unit 64 | ├── translations 65 | └── var 66 | ├── cache 67 | └── log 68 | ``` 69 | 70 | 71 | 72 | #### Lets make it work 73 | 74 | ```bash 75 | git clone https://github.com/bencagri/symfony4-ddd-skeleton.git 76 | cd symfony4-ddd-skeleton 77 | composer install 78 | bin/console doctrine:database:create 79 | bin/console doctrine:schema:update --force 80 | bin/console doctrine:fixtures:load 81 | php -S 127.0.0.1:9002 -t public 82 | 83 | ``` 84 | 85 | then visit `127.0.0.1:9002/api/doc` you should see the documentation now. 86 | 87 |

88 | 89 |

90 | 91 | ### With Docker 92 | ``` 93 | # Start the application 94 | docker-compose up -d 95 | 96 | # View logs to monitor installation progress 97 | docker-compose logs -f 98 | 99 | # Stop the application 100 | docker-compose down 101 | 102 | ``` 103 | 104 | 105 | ### Making Request 106 | When you try to make a request you will get an error. Because to make a request you need `Access Token`. 107 | 108 | Lets try making a request; 109 | ```bash 110 | curl -X GET "http://127.0.0.1:9002/api/articles?page=1&per_page=10" -H "accept: application/json" 111 | ``` 112 | 113 | It should say; 114 | ```bash 115 | { 116 | "success": false, 117 | "error": { 118 | "code": 0, 119 | "message": "A Token was not found in the TokenStorage.", 120 | 121 | ... 122 | ``` 123 | This project is using Oauth2. So, first you need is to create a client. For this, it also has a command to create a oauth client. 124 | 125 | ```bash 126 | bin/console oauth:client:create 127 | ``` 128 | 129 | you should see something like; 130 | ``` 131 | Added a new client with public id 6_2x0l2r8t6e2o4sggww08wwk88gs8sggsog0wk8cow4w0gso0s0. 132 | ``` 133 | 134 | Go and check your `oauth_client` table on database. you will see your secret also. 135 | Basically we have `Authorization code`, `Password`, `Client Credentials` and `Refresh Token` grant types. You can read more on [Oauth Grant Types](https://oauth.net/2/grant-types/). 136 | 137 | In this case, I prefer to go with `Client Credentials` grant type. For this, I need `client_id` and `client_secret` 138 | 139 | I already know client id, it produced a client and told me the ID when I run the command. And my secret is on database. 140 | 141 | So, lets take an `Access Token` to make a request to api. 142 | 143 | ```bash 144 | 145 | curl -X GET \ 146 | 'http://127.0.0.1:9002/oauth/v2/token?client_id=6_2x0l2r8t6e2o4sggww08wwk88gs8sggsog0wk8cow4w0gso0s0&client_secret=4biwdp70w2yog4gs0s0c0808kww0c88sowoggggsg0swk48w08&grant_type=client_credentials' \ 147 | -H 'cache-control: no-cache' \ 148 | -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \ 149 | -F client_id=1_4v0w0kiec9s0osgs8w40og8o4okc4ws08cos84c0gw4csoc8ws \ 150 | -F client_secret=4biwdp70w2yog4gs0s0c0808kww0c88sowoggggsg0swk48w08 \ 151 | -F grant_type=client_credentials 152 | 153 | ``` 154 | 155 | And The Response 156 | ```bash 157 | { 158 | "access_token": "OWUyMTMxYzJjN2I5Nzg0ZTQ1N2NlZDNkMWYxZjFiZGE5N2RjMTA4ZmI1ZTU4ZGE0YWI4NmU3YmQxZjgyNTJkZg", 159 | "expires_in": 3600, 160 | "token_type": "bearer", 161 | "scope": null 162 | } 163 | ``` 164 | 165 | great. I have an access token to make a request. 166 | 167 | lets try to get an article now. 168 | 169 | ```bash 170 | curl -X GET \ 171 | http://127.0.0.1:9002/api/article/1 \ 172 | -H 'authorization: Bearer OWUyMTMxYzJjN2I5Nzg0ZTQ1N2NlZDNkMWYxZjFiZGE5N2RjMTA4ZmI1ZTU4ZGE0YWI4NmU3YmQxZjgyNTJkZg' \ 173 | -H 'cache-control: no-cache' \ 174 | -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \ 175 | -H 'postman-token: 8635975a-6197-b8c6-c055-907a4668c503' \ 176 | -F client_id=1_4v0w0kiec9s0osgs8w40og8o4okc4ws08cos84c0gw4csoc8ws \ 177 | -F client_secret=4biwdp70w2yog4gs0s0c0808kww0c88sowoggggsg0swk48w08 \ 178 | -F grant_type=client_credentials 179 | ``` 180 | 181 | And the response is; 182 | ```bash 183 | { 184 | "success": true, 185 | "data": { 186 | "type": "article", 187 | "id": "1", 188 | "attributes": { 189 | "title": "My Test Article 0", 190 | "body": "lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.lorem ipsum dolor sit amet.", 191 | "tags": {}, 192 | "createdAt": "2018-03-29" 193 | }, 194 | "links": { 195 | "self": "http://127.0.0.1:9002/api/article/1" 196 | } 197 | } 198 | } 199 | ``` 200 | 201 | Great, I got the article information with a request to `GET /api/article/1` 202 | 203 | This package was built around [JSON API](http://jsonapi.org/) to take advantage of its features around efficiently caching responses, sometimes eliminating network requests entirely. 204 | 205 | #### Packages 206 | - Symfony Flex 207 | - Doctrine ORM Bundle 208 | - Doctrine Fixtures 209 | - Twig Bundle 210 | - Fos Oauth Server Bundle 211 | - Nelmio Doc Bundle 212 | - Symfony Profiler (dev) 213 | - Framework Extra Bundle 214 | - Fractal (PhpLeague) 215 | - PagerFanta for Doctrine 216 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencagri/symfony-ddd/65a3baef893222b6565733b1c746399d4af44c72/screenshot.png -------------------------------------------------------------------------------- /src/Authorization/Console/ClientCreateCommand.php: -------------------------------------------------------------------------------- 1 | setName('oauth:client:create') 24 | ->setDescription('Creates a new client') 25 | ->addOption('redirect-uri', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_OPTIONAL, 'Sets the redirect uri. Use multiple times to set multiple uris.', []) 26 | ->addOption('grant-type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_OPTIONAL, 'Set allowed grant type. Use multiple times to set multiple grant types', 'client_credentials') 27 | ; 28 | } 29 | protected function execute(InputInterface $input, OutputInterface $output) 30 | { 31 | 32 | $this->clientManager = $this->getContainer()->get('fos_oauth_server.client_manager.default'); ; 33 | $client = $this->clientManager->createClient(); 34 | $client->setRedirectUris($input->getOption('redirect-uri')); 35 | $client->setAllowedGrantTypes([$input->getOption('grant-type')]); 36 | $this->clientManager->updateClient($client); 37 | $output->writeln(sprintf('Added a new client with public id %s.', $client->getPublicId())); 38 | } 39 | } -------------------------------------------------------------------------------- /src/Authorization/Controller/OAuthAuthorizeController.php: -------------------------------------------------------------------------------- 1 | request->get('grant_type')) { 106 | $request->request->set('grant_type', 'client_credentials'); 107 | } 108 | 109 | return parent::tokenAction($request); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Authorization/Entity/Oauth2/AccessToken.php: -------------------------------------------------------------------------------- 1 | setContributors( 20 | new ArrayCollection([$this->getReference(UserFixtures::TEST_USER)]) 21 | ); 22 | 23 | $article->setAuthor($this->getReference(UserFixtures::TEST_USER)); 24 | $article->setBody($faker->paragraph); 25 | $article->setTitle($faker->sentence); 26 | 27 | $manager->persist($article); 28 | $manager->flush(); 29 | } 30 | } 31 | 32 | /** 33 | * Get the order of this fixture 34 | * 35 | * @return integer 36 | */ 37 | public function getOrder() 38 | { 39 | return 2; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/DataFixtures/UserFixtures.php: -------------------------------------------------------------------------------- 1 | setUsername($faker->userName); 19 | $user->setEmail("user@example.com"); 20 | $user->setPassword(sha1('secret')); 21 | 22 | $manager->persist($user); 23 | $manager->flush(); 24 | 25 | $this->addReference(self::TEST_USER, $user); 26 | } 27 | 28 | /** 29 | * Get the order of this fixture 30 | * 31 | * @return integer 32 | */ 33 | public function getOrder() 34 | { 35 | return 1; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/Kernel.php: -------------------------------------------------------------------------------- 1 | getProjectDir().'/var/cache/'.$this->environment; 20 | } 21 | 22 | public function getLogDir() 23 | { 24 | return $this->getProjectDir().'/var/log'; 25 | } 26 | 27 | public function registerBundles() 28 | { 29 | $contents = require $this->getProjectDir().'/config/bundles.php'; 30 | foreach ($contents as $class => $envs) { 31 | if (isset($envs['all']) || isset($envs[$this->environment])) { 32 | yield new $class(); 33 | } 34 | } 35 | } 36 | 37 | protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) 38 | { 39 | // Feel free to remove the "container.autowiring.strict_mode" parameter 40 | // if you are using symfony/dependency-injection 4.0+ as it's the default behavior 41 | $container->setParameter('container.autowiring.strict_mode', true); 42 | $container->setParameter('container.dumper.inline_class_loader', true); 43 | $confDir = $this->getProjectDir().'/config'; 44 | 45 | $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); 46 | $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob'); 47 | $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); 48 | $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); 49 | } 50 | 51 | protected function configureRoutes(RouteCollectionBuilder $routes) 52 | { 53 | $confDir = $this->getProjectDir().'/config'; 54 | 55 | $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); 56 | $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob'); 57 | $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Project/App/EventListener/ApiExceptionListener.php: -------------------------------------------------------------------------------- 1 | isKernelDebug = $isKernelDebug; 19 | } 20 | 21 | public function onKernelException(GetResponseForExceptionEvent $event) 22 | { 23 | $throwedException = $event->getException(); 24 | 25 | $errorBody = [ 26 | 'code' => $throwedException->getCode(), 27 | 'message' => $throwedException->getMessage(), 28 | ]; 29 | 30 | if ($throwedException instanceof ValidatorException) { 31 | $errorBody['message'] = 'Invalid data has been sent'; 32 | } 33 | 34 | if ($this->isKernelDebug) { 35 | $errorBody['exception'] = [ 36 | 'class' => get_class($throwedException) 37 | ]; 38 | $errorBody['trace'] = $throwedException->getTrace(); 39 | } 40 | 41 | $event->setResponse(new JsonResponse(['success' => false, 'error' => $errorBody])); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Project/App/Interface/ValidationInterface.php: -------------------------------------------------------------------------------- 1 | baseUrl = $baseUrl; 21 | parent::__construct(); 22 | } 23 | 24 | /** 25 | * @param $resource 26 | * @param bool $success 27 | * @return array 28 | */ 29 | public function transform($resource, $success = true) 30 | { 31 | if ($resource instanceof ResourceInterface) { 32 | 33 | $this->setSerializer(new JsonApiSerializer($this->baseUrl)); 34 | 35 | //if there is an include, set transformer include 36 | if (isset($_GET['include']) && !empty($_GET['include'])) { 37 | $this->parseIncludes($_GET['include']); 38 | } 39 | 40 | $resource = $this->createData($resource); 41 | 42 | $response = array_merge(['success' => $success], $resource->toArray()); 43 | }else { 44 | $response = [ 45 | 'success' => $success, 46 | 'message' => $resource 47 | ]; 48 | } 49 | 50 | return $response; 51 | 52 | } 53 | 54 | protected function paginatorAdapter() 55 | { 56 | $paginatorAdapter = new PagerfantaPaginatorAdapter($paginator, function(int $page) use ($request, $router) { 57 | $route = $request->attributes->get('_route'); 58 | $inputParams = $request->attributes->get('_route_params'); 59 | $newParams = array_merge($inputParams, $request->query->all()); 60 | $newParams['page'] = $page; 61 | return $router->generate($route, $newParams, 0); 62 | }); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/Project/Console/ProjectTestCommand.php: -------------------------------------------------------------------------------- 1 | setName('hello:project') 17 | 18 | // the short description shown while running "php bin/console list" 19 | ->setDescription('Echo hello project') 20 | 21 | // the full command description shown when running the command with 22 | // the "--help" option 23 | ->setHelp('This command allows you to write hello project to screen') 24 | ; 25 | } 26 | 27 | public function execute(InputInterface $input, OutputInterface $output) 28 | { 29 | $output->writeln('Hello Project'); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Project/Domain/Article/ArticleService.php: -------------------------------------------------------------------------------- 1 | entityManager = $entityManager; 48 | $this->articleTransformer = $articleTransformer; 49 | $this->fractalService = $fractalService; 50 | } 51 | 52 | /** 53 | * @param Request $request 54 | * @param RouterInterface $router 55 | * @return Collection|Item 56 | */ 57 | public function getArticles(Request $request, RouterInterface $router) 58 | { 59 | $page = NULL !== $request->get('page') ? (int) $request->get('page') : 1; 60 | $perPage = NULL !== $request->get('per_page') ? (int) $request->get('per_page') : 10; 61 | 62 | $articles = $this->entityManager->getRepository(Article::class); 63 | 64 | $doctrineAdapter = new DoctrineORMAdapter($articles->getArticles()); 65 | $paginator = new Pagerfanta($doctrineAdapter); 66 | $paginator->setCurrentPage($page); 67 | $paginator->setMaxPerPage($perPage); 68 | 69 | $filteredResults = $paginator->getCurrentPageResults(); 70 | 71 | $paginatorAdapter = new PagerfantaPaginatorAdapter($paginator, function(int $page) use ($request, $router) { 72 | $route = $request->attributes->get('_route'); 73 | $inputParams = $request->attributes->get('_route_params'); 74 | $newParams = array_merge($inputParams, $request->query->all()); 75 | $newParams['page'] = $page; 76 | return $router->generate($route, $newParams, 0); 77 | }); 78 | 79 | $resource = new Collection($filteredResults, $this->articleTransformer, 'article'); 80 | $resource->setPaginator($paginatorAdapter); 81 | return $resource; 82 | } 83 | 84 | /** 85 | * @param $id 86 | * @return Item 87 | * @throws EntityNotFoundException 88 | */ 89 | public function getArticleById($id) 90 | { 91 | $article = $this->entityManager->getRepository(Article::class)->find($id); 92 | 93 | if ($article) { 94 | return new Item($article, $this->articleTransformer, 'article'); 95 | } 96 | 97 | throw new EntityNotFoundException("Article not found"); 98 | } 99 | 100 | /** 101 | * @param Request $request 102 | */ 103 | public function addArticle(Request $request) 104 | { 105 | var_dump($request); 106 | 107 | /** @var User $user */ 108 | $user = $this->entityManager->getReference(User::class, $request->request->get('user')); 109 | 110 | $article = new Article(); 111 | $article->setTitle($request->request->get('title')); 112 | $article->setBody($request->request->get('body')); 113 | $article->setAuthor($user); 114 | $article->setContributors(new ArrayCollection([$user])); 115 | 116 | //set tags 117 | if (is_array($request->request->get('tags'))) { 118 | foreach ($request->request->get('tags') as $tag) { 119 | $article->addTagFromName($tag); 120 | } 121 | } 122 | 123 | $this->entityManager->getRepository(Article::class)->save($article); 124 | 125 | } 126 | 127 | 128 | public function searchArticle(Request $request) 129 | { 130 | $resource = $this->entityManager->getRepository(Article::class)->searchArticle($request); 131 | 132 | $collection = new Collection($resource, $this->articleTransformer, 'article'); 133 | 134 | return $this->fractalService->transform($collection); 135 | } 136 | } -------------------------------------------------------------------------------- /src/Project/Domain/Article/ArticleTransformer.php: -------------------------------------------------------------------------------- 1 | $article->getId(), 20 | 'title' => $article->getTitle(), 21 | 'body' => $article->getBody(), 22 | 'tags' => $article->getTags(), 23 | 'createdAt' => date('Y-m-d') 24 | ]; 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/Project/Domain/Article/Entity/Article.php: -------------------------------------------------------------------------------- 1 | id; 54 | } 55 | 56 | /** 57 | * @return string 58 | */ 59 | public function getBody(): string 60 | { 61 | return $this->body; 62 | } 63 | 64 | /** 65 | * @param string $body 66 | */ 67 | public function setBody(string $body) 68 | { 69 | $this->body = $body; 70 | } 71 | 72 | /** 73 | * @return string 74 | */ 75 | public function getTitle(): string 76 | { 77 | return $this->title; 78 | } 79 | 80 | /** 81 | * @param string $title 82 | */ 83 | public function setTitle(string $title) 84 | { 85 | $this->title = $title; 86 | } 87 | 88 | /** 89 | * @return User 90 | */ 91 | public function getAuthor(): User 92 | { 93 | return $this->author; 94 | } 95 | 96 | /** 97 | * @param User $author 98 | */ 99 | public function setAuthor(User $author) 100 | { 101 | $this->author = $author; 102 | } 103 | 104 | /** 105 | * @return Tag|ArrayCollection 106 | */ 107 | public function getTags() 108 | { 109 | return $this->tags; 110 | } 111 | 112 | /** 113 | * @param Tag|ArrayCollection $tags 114 | */ 115 | public function setTags($tags) 116 | { 117 | $this->tags = $tags; 118 | } 119 | 120 | /** 121 | * @param Tag $tag 122 | */ 123 | public function addTag(Tag $tag) 124 | { 125 | if (!$this->tags->contains($tag)) { 126 | $this->tags->add($tag); 127 | } 128 | } 129 | 130 | public function addTagFromName($name) 131 | { 132 | $tag = new Tag(); 133 | $slug = Sluggable\Urlizer::urlize($name, '-'); 134 | $tag->setTitle($name); 135 | $tag->setSlug($slug); 136 | 137 | $this->tags->add($tag); 138 | } 139 | 140 | /** 141 | * @return ArrayCollection 142 | */ 143 | public function getImages(): ArrayCollection 144 | { 145 | return $this->images; 146 | } 147 | 148 | /** 149 | * @param ArrayCollection $images 150 | */ 151 | public function setImages(ArrayCollection $images) 152 | { 153 | $this->images = $images; 154 | } 155 | 156 | /** 157 | * @return User|ArrayCollection 158 | */ 159 | public function getContributors() 160 | { 161 | return $this->contributors; 162 | } 163 | 164 | /** 165 | * @param User|ArrayCollection $contributors 166 | */ 167 | public function setContributors($contributors) 168 | { 169 | $this->contributors = $contributors; 170 | } 171 | 172 | /** 173 | * @param User $contributor 174 | */ 175 | public function addContributor(User $contributor) 176 | { 177 | if (!$this->contributors->contains($contributor)) { 178 | $this->contributors->add($contributor); 179 | } 180 | } 181 | 182 | 183 | } -------------------------------------------------------------------------------- /src/Project/Domain/Article/Entity/Tag.php: -------------------------------------------------------------------------------- 1 | id; 31 | } 32 | 33 | 34 | /** 35 | * @return string 36 | */ 37 | public function getTitle(): string 38 | { 39 | return $this->title; 40 | } 41 | 42 | /** 43 | * @param string $title 44 | */ 45 | public function setTitle(string $title) 46 | { 47 | $this->title = $title; 48 | } 49 | 50 | /** 51 | * @return string 52 | */ 53 | public function getSlug(): string 54 | { 55 | return $this->slug; 56 | } 57 | 58 | /** 59 | * @param string $slug 60 | */ 61 | public function setSlug(string $slug) 62 | { 63 | $this->slug = $slug; 64 | } 65 | 66 | 67 | 68 | } -------------------------------------------------------------------------------- /src/Project/Domain/User/Contract/UserRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | id; 33 | } 34 | 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getUsername() 40 | { 41 | return $this->username; 42 | } 43 | 44 | /** 45 | * @param string $username 46 | */ 47 | public function setUsername($username) 48 | { 49 | $this->username = $username; 50 | } 51 | 52 | /** 53 | * @return string 54 | */ 55 | public function getEmail(): string 56 | { 57 | return $this->email; 58 | } 59 | 60 | /** 61 | * @param string $email 62 | */ 63 | public function setEmail(string $email) 64 | { 65 | $this->email = $email; 66 | } 67 | 68 | /** 69 | * @return string 70 | */ 71 | public function getPassword(): string 72 | { 73 | return $this->password; 74 | } 75 | 76 | /** 77 | * @param string $password 78 | */ 79 | public function setPassword(string $password) 80 | { 81 | $this->password = $password; 82 | } 83 | 84 | 85 | } -------------------------------------------------------------------------------- /src/Project/Domain/User/UserService.php: -------------------------------------------------------------------------------- 1 | entityManager = $entityManager; 45 | $this->fractalService = $fractalService; 46 | $this->userTransformer = $userTransformer; 47 | } 48 | 49 | public function listUsers(Request $request, RouterInterface $router) 50 | { 51 | $page = NULL !== $request->get('page') ? (int) $request->get('page') : 1; 52 | $perPage = NULL !== $request->get('per_page') ? (int) $request->get('per_page') : 10; 53 | 54 | $users = $this->entityManager->getRepository(User::class); 55 | 56 | $doctrineAdapter = new DoctrineORMAdapter($users->getUsers()); 57 | $paginator = new Pagerfanta($doctrineAdapter); 58 | $paginator->setCurrentPage($page); 59 | $paginator->setMaxPerPage($perPage); 60 | 61 | $filteredResults = $paginator->getCurrentPageResults(); 62 | 63 | $paginatorAdapter = new PagerfantaPaginatorAdapter($paginator, function(int $page) use ($request, $router) { 64 | $route = $request->attributes->get('_route'); 65 | $inputParams = $request->attributes->get('_route_params'); 66 | $newParams = array_merge($inputParams, $request->query->all()); 67 | $newParams['page'] = $page; 68 | return $router->generate($route, $newParams, 0); 69 | }); 70 | 71 | $resource = new Collection($filteredResults, $this->userTransformer, 'user'); 72 | $resource->setPaginator($paginatorAdapter); 73 | return $resource; 74 | } 75 | 76 | public function getUserById($id) 77 | { 78 | $user = $this->entityManager->getRepository(User::class)->find($id); 79 | 80 | if (!$user) { 81 | throw new EntityNotFoundException('user not found'); 82 | } 83 | 84 | return new Item($user, $this->userTransformer, 'user'); 85 | 86 | } 87 | } -------------------------------------------------------------------------------- /src/Project/Domain/User/UserTransformer.php: -------------------------------------------------------------------------------- 1 | $user->getId(), 15 | 'username' => $user->getUsername(), 16 | 'email' => $user->getEmail() 17 | ]; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Project/Http/Controller/AppController.php: -------------------------------------------------------------------------------- 1 | articleService = $articleService; 39 | $this->fractalService = $fractalService; 40 | $this->router = $router; 41 | } 42 | 43 | 44 | /** 45 | * @param Request $request 46 | * @return JsonResponse 47 | * @SWG\Response( 48 | * response=200, 49 | * description="Returns the article collection" 50 | * ) 51 | * @SWG\Parameter( 52 | * name="page", 53 | * in="query", 54 | * type="integer", 55 | * description="current page", 56 | * default="1" 57 | * ) 58 | * @SWG\Parameter( 59 | * name="per_page", 60 | * in="query", 61 | * type="integer", 62 | * description="limit per page", 63 | * default="10" 64 | * ) 65 | * @SWG\Tag(name="articles") 66 | */ 67 | public function index(Request $request) 68 | { 69 | $articles = $this->articleService->getArticles($request, $this->router); 70 | 71 | return new JsonResponse($this->fractalService->transform($articles)); 72 | } 73 | 74 | /** 75 | * @param $id 76 | * @return JsonResponse 77 | * @SWG\Response( 78 | * response=200, 79 | * description="Returns single article Item" 80 | * ) 81 | * @SWG\Response( 82 | * response=500, 83 | * description="Returns error" 84 | * ) 85 | * @SWG\Tag(name="articles") 86 | */ 87 | public function article($id) 88 | { 89 | try { 90 | $article = $this->articleService->getArticleById($id); 91 | return new JsonResponse($this->fractalService->transform($article)); 92 | }catch (\Exception $e) { 93 | return new JsonResponse($this->fractalService->transform($e->getMessage(), false), Response::HTTP_INTERNAL_SERVER_ERROR); 94 | } 95 | } 96 | 97 | /** 98 | * @param Request $request 99 | * @return JsonResponse 100 | * @SWG\Response( 101 | * response=200, 102 | * description="returns success message" 103 | * ) 104 | * @SWG\Response( 105 | * response=500, 106 | * description="Returns error" 107 | * ) 108 | * 109 | * @SWG\Parameter( 110 | * name="title", 111 | * in="formData", 112 | * type="string", 113 | * required=true, 114 | * description="article title" 115 | * ) 116 | * @SWG\Parameter( 117 | * name="body", 118 | * in="formData", 119 | * type="string", 120 | * required=true, 121 | * description="article body, markdown accepted" 122 | * ) 123 | * @SWG\Parameter( 124 | * name="user", 125 | * in="formData", 126 | * type="integer", 127 | * required=true, 128 | * description="user id from GET /users" 129 | * ) 130 | * @SWG\Parameter( 131 | * name="tags", 132 | * in="formData", 133 | * type="array", 134 | * required=false, 135 | * @SWG\Items( 136 | * type="string" 137 | * ), 138 | * description="post tags" 139 | * ) 140 | * @SWG\Tag(name="articles") 141 | */ 142 | public function create(Request $request) 143 | { 144 | try { 145 | $this->articleService->addArticle($request); 146 | return new JsonResponse($this->fractalService->transform('Article has been added'), Response::HTTP_OK); 147 | }catch (\Exception $exception) { 148 | return new JsonResponse($this->fractalService->transform($exception->getMessage(), false), Response::HTTP_INTERNAL_SERVER_ERROR); 149 | } 150 | 151 | } 152 | 153 | } -------------------------------------------------------------------------------- /src/Project/Http/Controller/HomeController.php: -------------------------------------------------------------------------------- 1 | $request->get('order')]); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Project/Http/Controller/SearchController.php: -------------------------------------------------------------------------------- 1 | articleService = $articleService; 26 | } 27 | 28 | /** 29 | * @param Request $request 30 | * @return JsonResponse 31 | * @SWG\Response( 32 | * response=200, 33 | * description="Returns the article collection" 34 | * ) 35 | * @SWG\Parameter( 36 | * name="query", 37 | * in="query", 38 | * type="string", 39 | * description="search query" 40 | * ) 41 | * @SWG\Tag(name="search") 42 | */ 43 | public function index(Request $request) 44 | { 45 | $resource = $this->articleService->searchArticle($request); 46 | 47 | return new JsonResponse($resource); 48 | 49 | } 50 | } -------------------------------------------------------------------------------- /src/Project/Http/Controller/UserController.php: -------------------------------------------------------------------------------- 1 | userService = $userService; 39 | $this->router = $router; 40 | $this->fractalService = $fractalService; 41 | } 42 | 43 | 44 | /** 45 | * @param Request $request 46 | * @return JsonResponse 47 | * @SWG\Response( 48 | * response=200, 49 | * description="Returns users collection with pagination" 50 | * ) 51 | * @SWG\Response( 52 | * response=500, 53 | * description="Returns error" 54 | * ) 55 | * @SWG\Parameter( 56 | * name="page", 57 | * in="query", 58 | * type="integer", 59 | * description="current page", 60 | * default="1" 61 | * ) 62 | * @SWG\Parameter( 63 | * name="per_page", 64 | * in="query", 65 | * type="integer", 66 | * description="limit per page", 67 | * default="10" 68 | * ) 69 | * @SWG\Tag(name="users") 70 | */ 71 | public function index(Request $request) 72 | { 73 | $resource = $this->userService->listUsers($request, $this->router); 74 | 75 | return new JsonResponse($this->fractalService->transform($resource)); 76 | } 77 | 78 | /** 79 | * @param $id 80 | * @return JsonResponse 81 | * @SWG\Response( 82 | * response=200, 83 | * description="Returns single user Item" 84 | * ) 85 | * @SWG\Response( 86 | * response=204, 87 | * description="Returns not found user" 88 | * ) 89 | * @SWG\Tag(name="users") 90 | */ 91 | public function user($id) 92 | { 93 | 94 | try { 95 | $user = $this->userService->getUserById($id); 96 | return new JsonResponse($this->fractalService->transform($user)); 97 | 98 | }catch (EntityNotFoundException $exception) { 99 | return new JsonResponse($this->fractalService->transform($exception->getMessage(), false), Response::HTTP_NO_CONTENT); 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /src/Project/Infrastructure/Article/ArticleRepository.php: -------------------------------------------------------------------------------- 1 | createQueryBuilder('a'); 16 | 17 | return $qb->getQuery(); 18 | } 19 | 20 | public function searchArticle(Request $request) 21 | { 22 | $qb = $this->createQueryBuilder('a') 23 | ->where('a.title LIKE :query') 24 | ->orWhere('a.body LIKE :query') 25 | ->setParameter('query', "%{$request->get('query')}%"); 26 | 27 | return $qb->getQuery()->getResult(); 28 | } 29 | 30 | 31 | 32 | public function save(Article $article) 33 | { 34 | $this->_em->persist($article); 35 | $this->_em->flush(); 36 | } 37 | } -------------------------------------------------------------------------------- /src/Project/Infrastructure/User/UserRepository.php: -------------------------------------------------------------------------------- 1 | createQueryBuilder('u')->getQuery(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Project/Resources/config/services.yaml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: "transformers.yaml"} 3 | 4 | services: 5 | ## here will be project's services 6 | 7 | project.event_listener.api_exception: 8 | class: App\Project\App\EventListener\ApiExceptionListener 9 | arguments: ['%%kernel.debug%%'] 10 | tags: 11 | - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 200 } 12 | 13 | ## Fractal Service 14 | project.fractal.manager: 15 | class: App\Project\App\Support\FractalService 16 | public: true 17 | arguments: ['%siteUrl%'] 18 | App\Project\App\Support\FractalService: '@project.fractal.manager' 19 | 20 | ## Project Article Service 21 | project.article.service: 22 | class: App\Project\Domain\Article\ArticleService 23 | public: true 24 | arguments: ['@doctrine.orm.entity_manager','@project.article.transformer','@project.fractal.manager'] 25 | App\Project\Domain\Article\ArticleService: '@project.article.service' 26 | 27 | ## Project User Service 28 | project.user.service: 29 | class: App\Project\Domain\User\UserService 30 | arguments: ['@doctrine.orm.entity_manager','@project.fractal.manager','@project.user.transformer'] 31 | App\Project\Domain\User\UserService: '@project.user.service' 32 | 33 | ## make fos oauth service public 34 | fos_oauth_server.client_manager.default: 35 | class: FOS\OAuthServerBundle\Entity\ClientManager 36 | public: true 37 | arguments: ['@Doctrine\ORM\EntityManagerInterface','%fos_oauth_server.model.client.class%'] 38 | 39 | FOS\OAuthServerBundle\Model\AccessTokenManagerInterface: 40 | alias: fos_oauth_server.access_token_manager.default -------------------------------------------------------------------------------- /src/Project/Resources/config/transformers.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | project.article.transformer: 3 | class: App\Project\Domain\Article\ArticleTransformer 4 | 5 | project.user.transformer: 6 | class: App\Project\Domain\User\UserTransformer -------------------------------------------------------------------------------- /src/Project/Resources/doctrine/mapping/Article.Entity.Article.orm.yml: -------------------------------------------------------------------------------- 1 | App\Project\Domain\Article\Entity\Article: 2 | type: entity 3 | table: articles 4 | repositoryClass: App\Project\Infrastructure\Article\ArticleRepository 5 | id: 6 | id: 7 | type: integer 8 | generator: { strategy: AUTO } 9 | fields: 10 | title: 11 | type: string 12 | length: 100 13 | 14 | body: 15 | type: text 16 | 17 | images: 18 | type: json 19 | nullable: true 20 | 21 | manyToMany: 22 | tags: 23 | targetEntity: App\Project\Domain\Article\Entity\Tag 24 | cascade: [ 'persist' ] 25 | fetch: EXTRA_LAZY 26 | indexBy: type 27 | joinTable: 28 | name: article_tags 29 | 30 | contributors: 31 | targetEntity: App\Project\Domain\User\Entity\User 32 | cascade: [ 'persist' ] 33 | fetch: EXTRA_LAZY 34 | indexBy: type 35 | joinTable: 36 | name: article_contributors 37 | 38 | 39 | manyToOne: 40 | author: 41 | targetEntity: App\Project\Domain\User\Entity\User 42 | cascade: [ 'persist' ] 43 | fetch: EAGER 44 | -------------------------------------------------------------------------------- /src/Project/Resources/doctrine/mapping/Article.Entity.Tag.orm.yml: -------------------------------------------------------------------------------- 1 | App\Project\Domain\Article\Entity\Tag: 2 | type: entity 3 | table: tags 4 | id: 5 | id: 6 | type: integer 7 | generator: { strategy: AUTO } 8 | fields: 9 | title: 10 | type: string 11 | length: 100 12 | slug: 13 | type: string 14 | length: 100 -------------------------------------------------------------------------------- /src/Project/Resources/doctrine/mapping/User.Entity.User.orm.yml: -------------------------------------------------------------------------------- 1 | App\Project\Domain\User\Entity\User: 2 | type: entity 3 | table: users 4 | repositoryClass: App\Project\Infrastructure\User\UserRepository 5 | id: 6 | id: 7 | type: integer 8 | generator: { strategy: AUTO } 9 | fields: 10 | username: 11 | type: string 12 | length: 100 13 | email: 14 | type: string 15 | password: 16 | type: string -------------------------------------------------------------------------------- /src/Project/Resources/routing/routes.yaml: -------------------------------------------------------------------------------- 1 | 2 | articles.get: 3 | path: "/api/articles" 4 | methods: GET 5 | controller: App\Project\Http\Controller\ArticleController:index 6 | 7 | articles.get.by.id: 8 | path: "/api/article/{id}" 9 | methods: GET 10 | controller: App\Project\Http\Controller\ArticleController:article 11 | 12 | articles.create: 13 | path: "/api/articles" 14 | methods: POST 15 | controller: App\Project\Http\Controller\ArticleController:create 16 | 17 | users.get: 18 | path: "/api/users" 19 | methods: GET 20 | controller: App\Project\Http\Controller\UserController:index 21 | 22 | users.get.by.id: 23 | path: "/api/user/{id}" 24 | methods: GET 25 | controller: App\Project\Http\Controller\UserController:user 26 | 27 | 28 | project.search: 29 | path: "/api/search" 30 | methods: GET 31 | controller: App\Project\Http\Controller\SearchController:index -------------------------------------------------------------------------------- /symfony.lock: -------------------------------------------------------------------------------- 1 | { 2 | "behat/transliterator": { 3 | "version": "v1.2.0" 4 | }, 5 | "doctrine/annotations": { 6 | "version": "1.0", 7 | "recipe": { 8 | "repo": "github.com/symfony/recipes", 9 | "branch": "master", 10 | "version": "1.0", 11 | "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672" 12 | } 13 | }, 14 | "doctrine/cache": { 15 | "version": "v1.7.1" 16 | }, 17 | "doctrine/collections": { 18 | "version": "v1.5.0" 19 | }, 20 | "doctrine/common": { 21 | "version": "v2.8.1" 22 | }, 23 | "doctrine/data-fixtures": { 24 | "version": "v1.3.0" 25 | }, 26 | "doctrine/dbal": { 27 | "version": "v2.6.3" 28 | }, 29 | "doctrine/doctrine-bundle": { 30 | "version": "1.6", 31 | "recipe": { 32 | "repo": "github.com/symfony/recipes", 33 | "branch": "master", 34 | "version": "1.6", 35 | "ref": "c407ab0b5e5a39b242a52d323a5e84e6d3b7e4c0" 36 | } 37 | }, 38 | "doctrine/doctrine-cache-bundle": { 39 | "version": "1.3.2" 40 | }, 41 | "doctrine/doctrine-fixtures-bundle": { 42 | "version": "3.0", 43 | "recipe": { 44 | "repo": "github.com/symfony/recipes", 45 | "branch": "master", 46 | "version": "3.0", 47 | "ref": "2ea6070ecf365f9a801ccaed4b31d4a3b7af5693" 48 | } 49 | }, 50 | "doctrine/event-manager": { 51 | "version": "v1.0.0" 52 | }, 53 | "doctrine/inflector": { 54 | "version": "v1.3.0" 55 | }, 56 | "doctrine/instantiator": { 57 | "version": "1.1.0" 58 | }, 59 | "doctrine/lexer": { 60 | "version": "v1.0.1" 61 | }, 62 | "doctrine/orm": { 63 | "version": "v2.6.1" 64 | }, 65 | "doctrine/persistence": { 66 | "version": "v1.1.0" 67 | }, 68 | "doctrine/reflection": { 69 | "version": "v1.0.0" 70 | }, 71 | "exsyst/swagger": { 72 | "version": "v0.4.0" 73 | }, 74 | "friendsofsymfony/oauth-server-bundle": { 75 | "version": "2.0-dev" 76 | }, 77 | "friendsofsymfony/oauth2-php": { 78 | "version": "1.2.3" 79 | }, 80 | "fzaninotto/faker": { 81 | "version": "v1.7.1" 82 | }, 83 | "gedmo/doctrine-extensions": { 84 | "version": "v2.4.33" 85 | }, 86 | "jdorn/sql-formatter": { 87 | "version": "v1.2.17" 88 | }, 89 | "league/fractal": { 90 | "version": "0.17.0" 91 | }, 92 | "nelmio/api-doc-bundle": { 93 | "version": "3.0", 94 | "recipe": { 95 | "repo": "github.com/symfony/recipes-contrib", 96 | "branch": "master", 97 | "version": "3.0", 98 | "ref": "d76d09603a98c2e2b78ef038ef8a961f51b86da0" 99 | } 100 | }, 101 | "nikic/php-parser": { 102 | "version": "v4.0.0" 103 | }, 104 | "pagerfanta/pagerfanta": { 105 | "version": "v1.0.5" 106 | }, 107 | "phpdocumentor/reflection-common": { 108 | "version": "1.0.1" 109 | }, 110 | "phpdocumentor/reflection-docblock": { 111 | "version": "4.3.0" 112 | }, 113 | "phpdocumentor/type-resolver": { 114 | "version": "0.4.0" 115 | }, 116 | "psr/cache": { 117 | "version": "1.0.1" 118 | }, 119 | "psr/container": { 120 | "version": "1.0.0" 121 | }, 122 | "psr/log": { 123 | "version": "1.0.2" 124 | }, 125 | "psr/simple-cache": { 126 | "version": "1.0.1" 127 | }, 128 | "samj/fractal-bundle": { 129 | "version": "2.1.0" 130 | }, 131 | "sensio/framework-extra-bundle": { 132 | "version": "4.0", 133 | "recipe": { 134 | "repo": "github.com/symfony/recipes", 135 | "branch": "master", 136 | "version": "4.0", 137 | "ref": "aaddfdf43cdecd4cf91f992052d76c2cadc04543" 138 | } 139 | }, 140 | "stof/doctrine-extensions-bundle": { 141 | "version": "1.2", 142 | "recipe": { 143 | "repo": "github.com/symfony/recipes-contrib", 144 | "branch": "master", 145 | "version": "1.2", 146 | "ref": "6c1ceb662f8997085f739cd089bfbef67f245983" 147 | } 148 | }, 149 | "symfony/asset": { 150 | "version": "v4.0.6" 151 | }, 152 | "symfony/browser-kit": { 153 | "version": "v4.0.6" 154 | }, 155 | "symfony/cache": { 156 | "version": "v4.0.6" 157 | }, 158 | "symfony/config": { 159 | "version": "v4.0.6" 160 | }, 161 | "symfony/console": { 162 | "version": "3.3", 163 | "recipe": { 164 | "repo": "github.com/symfony/recipes", 165 | "branch": "master", 166 | "version": "3.3", 167 | "ref": "c646e4b71af082e94b5014daca36ef6812bad076" 168 | } 169 | }, 170 | "symfony/contracts": { 171 | "version": "v1.0.2" 172 | }, 173 | "symfony/debug": { 174 | "version": "v4.0.6" 175 | }, 176 | "symfony/dependency-injection": { 177 | "version": "v4.0.6" 178 | }, 179 | "symfony/doctrine-bridge": { 180 | "version": "v4.0.6" 181 | }, 182 | "symfony/dom-crawler": { 183 | "version": "v4.0.6" 184 | }, 185 | "symfony/dotenv": { 186 | "version": "v4.0.6" 187 | }, 188 | "symfony/event-dispatcher": { 189 | "version": "v4.0.6" 190 | }, 191 | "symfony/filesystem": { 192 | "version": "v4.0.6" 193 | }, 194 | "symfony/finder": { 195 | "version": "v4.0.6" 196 | }, 197 | "symfony/flex": { 198 | "version": "1.0", 199 | "recipe": { 200 | "repo": "github.com/symfony/recipes", 201 | "branch": "master", 202 | "version": "1.0", 203 | "ref": "cc1afd81841db36fbef982fe56b48ade6716fac4" 204 | } 205 | }, 206 | "symfony/form": { 207 | "version": "v4.0.6" 208 | }, 209 | "symfony/framework-bundle": { 210 | "version": "3.3", 211 | "recipe": { 212 | "repo": "github.com/symfony/recipes", 213 | "branch": "master", 214 | "version": "3.3", 215 | "ref": "b9f462a47f7fd28d56c61f59c027fd7ad8e1aac8" 216 | } 217 | }, 218 | "symfony/http-foundation": { 219 | "version": "v4.0.6" 220 | }, 221 | "symfony/http-kernel": { 222 | "version": "v4.0.6" 223 | }, 224 | "symfony/inflector": { 225 | "version": "v4.0.6" 226 | }, 227 | "symfony/intl": { 228 | "version": "v4.0.6" 229 | }, 230 | "symfony/lts": { 231 | "version": "4-dev" 232 | }, 233 | "symfony/maker-bundle": { 234 | "version": "1.0", 235 | "recipe": { 236 | "repo": "github.com/symfony/recipes", 237 | "branch": "master", 238 | "version": "1.0", 239 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" 240 | } 241 | }, 242 | "symfony/options-resolver": { 243 | "version": "v4.0.6" 244 | }, 245 | "symfony/phpunit-bridge": { 246 | "version": "3.3", 247 | "recipe": { 248 | "repo": "github.com/symfony/recipes", 249 | "branch": "master", 250 | "version": "3.3", 251 | "ref": "41416370e732d1c8e7a0953a5ce815b641cfba0f" 252 | } 253 | }, 254 | "symfony/polyfill-ctype": { 255 | "version": "v1.11.0" 256 | }, 257 | "symfony/polyfill-intl-icu": { 258 | "version": "v1.7.0" 259 | }, 260 | "symfony/polyfill-mbstring": { 261 | "version": "v1.7.0" 262 | }, 263 | "symfony/polyfill-php72": { 264 | "version": "v1.7.0" 265 | }, 266 | "symfony/profiler-pack": { 267 | "version": "v1.0.3" 268 | }, 269 | "symfony/property-access": { 270 | "version": "v4.0.6" 271 | }, 272 | "symfony/property-info": { 273 | "version": "v4.0.6" 274 | }, 275 | "symfony/routing": { 276 | "version": "4.0", 277 | "recipe": { 278 | "repo": "github.com/symfony/recipes", 279 | "branch": "master", 280 | "version": "4.0", 281 | "ref": "cda8b550123383d25827705d05a42acf6819fe4e" 282 | } 283 | }, 284 | "symfony/security": { 285 | "version": "v4.0.6" 286 | }, 287 | "symfony/security-bundle": { 288 | "version": "3.3", 289 | "recipe": { 290 | "repo": "github.com/symfony/recipes", 291 | "branch": "master", 292 | "version": "3.3", 293 | "ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527" 294 | } 295 | }, 296 | "symfony/security-core": { 297 | "version": "v4.2.5" 298 | }, 299 | "symfony/security-csrf": { 300 | "version": "v4.2.5" 301 | }, 302 | "symfony/security-guard": { 303 | "version": "v4.2.5" 304 | }, 305 | "symfony/security-http": { 306 | "version": "v4.2.5" 307 | }, 308 | "symfony/stopwatch": { 309 | "version": "v4.0.6" 310 | }, 311 | "symfony/templating": { 312 | "version": "v4.0.6" 313 | }, 314 | "symfony/translation": { 315 | "version": "3.3", 316 | "recipe": { 317 | "repo": "github.com/symfony/recipes", 318 | "branch": "master", 319 | "version": "3.3", 320 | "ref": "6bcd6c570c017ea6ae5a7a6a027c929fd3542cd8" 321 | } 322 | }, 323 | "symfony/twig-bridge": { 324 | "version": "v4.0.6" 325 | }, 326 | "symfony/twig-bundle": { 327 | "version": "3.3", 328 | "recipe": { 329 | "repo": "github.com/symfony/recipes", 330 | "branch": "master", 331 | "version": "3.3", 332 | "ref": "f75ac166398e107796ca94cc57fa1edaa06ec47f" 333 | } 334 | }, 335 | "symfony/validator": { 336 | "version": "v4.0.6" 337 | }, 338 | "symfony/var-dumper": { 339 | "version": "v4.0.6" 340 | }, 341 | "symfony/var-exporter": { 342 | "version": "v4.2.5" 343 | }, 344 | "symfony/web-profiler-bundle": { 345 | "version": "3.3", 346 | "recipe": { 347 | "repo": "github.com/symfony/recipes", 348 | "branch": "master", 349 | "version": "3.3", 350 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6" 351 | } 352 | }, 353 | "symfony/yaml": { 354 | "version": "v4.0.6" 355 | }, 356 | "twig/twig": { 357 | "version": "v2.4.6" 358 | }, 359 | "webmozart/assert": { 360 | "version": "1.3.0" 361 | }, 362 | "zircote/swagger-php": { 363 | "version": "2.0.13" 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /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/bencagri/symfony-ddd/65a3baef893222b6565733b1c746399d4af44c72/tests/.gitignore -------------------------------------------------------------------------------- /tests/UnitTest.php: -------------------------------------------------------------------------------- 1 | "test"]); 24 | $this->container = self::$kernel->getContainer(); 25 | $this->em = $this->container->get('doctrine.orm.entity_manager'); 26 | $this->loadFixtures(); 27 | } 28 | 29 | public function loadFixtures() 30 | { 31 | $loader = new Loader(); 32 | $loader->loadFromDirectory(__DIR__ . '/../src/DataFixtures'); 33 | $purger = new ORMPurger($this->em); 34 | $executor = new ORMExecutor($this->em,$purger); 35 | $executor->execute($loader->getFixtures()); 36 | } 37 | 38 | public function test_sample() 39 | { 40 | $this->assertTrue(true); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/integration/ArticleServiceTest.php: -------------------------------------------------------------------------------- 1 | getContainer()->get('project.article.service'); 16 | 17 | $articleTitle = 'Test Title'; 18 | 19 | $user = $this->em->getRepository(User::class)->findOneBy(['username' => 'Project']); 20 | //create a request 21 | $request = new Request([],[ 22 | 'user' => $user->getId(), 23 | 'title' => $articleTitle, 24 | 'body' => 'this is html body' 25 | ]); 26 | 27 | $articleService->addArticle($request); 28 | 29 | //see in db 30 | /** @var Article $article */ 31 | $article = $this->em->getRepository(Article::class)->findOneBy(['title' => $articleTitle]); 32 | 33 | $this->assertEquals($article->getTitle(), $articleTitle); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /translations/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bencagri/symfony-ddd/65a3baef893222b6565733b1c746399d4af44c72/translations/.gitignore --------------------------------------------------------------------------------