Skip to content

Commit

Permalink
Finalization [SLE-192]
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelgfeller committed May 16, 2024
1 parent 086b989 commit 4eb3a56
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 69 deletions.
108 changes: 59 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,30 @@
[![Quality Score](https://img.shields.io/scrutinizer/quality/g/samuelgfeller/slim-example-project.svg)](https://scrutinizer-ci.com/g/samuelgfeller/slim-example-project/?branch=master)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)

Real-world example of a modern [Slim 4](https://www.slimframework.com/) web application with a scalable
structure and a variety of components and features.

Current best practices and programming principles are applied throughout the project and
adhering to the Single Responsibility Principle
([SRP](https://github.com/samuelgfeller/slim-example-project/wiki/Single-Responsibility-Principle-(SRP)))
is a key focus.
External library dependencies are [kept to a minimum](https://github.com/samuelgfeller/slim-example-project/wiki/Libraries-and-Framework)
to facilitate maintenance and ensure long-term viability.

The [architecture](https://github.com/samuelgfeller/slim-example-project/wiki/Architecture)
is inspired by the Domain Driven Design ([DDD](https://en.wikipedia.org/wiki/Domain-driven_design))
Real-world example of a modern [Slim 4](https://www.slimframework.com/) web application with a scalable
structure and a variety of components and features.

Current best practices and programming principles are applied throughout the project, and
adhering to the Single Responsibility Principle
([SRP](https://github.com/samuelgfeller/slim-example-project/wiki/Single-Responsibility-Principle-(SRP)))
has been a key focus.
External library dependencies
are [kept to a minimum](https://github.com/samuelgfeller/slim-example-project/wiki/Libraries-and-Framework)
to facilitate maintenance and ensure long-term viability.

The [architecture](https://github.com/samuelgfeller/slim-example-project/wiki/Architecture)
is inspired by the Domain Driven Design ([DDD](https://en.wikipedia.org/wiki/Domain-driven_design))
and the [Vertical Slice Architecture](https://www.youtube.com/watch?v=L2Wnq0ChAIA).

The base for this project was the official
[Slim-Skeleton](https://github.com/slimphp/Slim-Skeleton) and the [slim4-skeleton](https://github.com/odan/slim4-skeleton).
The base for this project was the official
[Slim-Skeleton](https://github.com/slimphp/Slim-Skeleton) and
the [slim4-skeleton](https://github.com/odan/slim4-skeleton).

A detailed [**documentation**](https://github.com/samuelgfeller/slim-example-project/wiki) explains how the project is built,
A detailed [**documentation**](https://github.com/samuelgfeller/slim-example-project/wiki) explains how the project is
built,
components, design choices and features.

Stripped down versions of this repository are available as skeleton
Stripped down versions of this repository are available as skeleton
templates.
With frontend [**slim-starter**](https://github.com/samuelgfeller/slim-starter) or just for an API:
[**slim-api-starter**](https://github.com/samuelgfeller/slim-api-starter).
Expand All @@ -35,7 +38,8 @@ Please read the [**installation guide**](https://github.com/samuelgfeller/slim-e
to get started.

## Features
All the features were developed with an effort to ensure maximum user-friendliness.

All the features were developed with an effort to ensure maximum user-friendliness.
The frontend, intuitive, aesthetically pleasing, minimalistic, and functional.
The backend, efficient and secure.

Expand All @@ -46,27 +50,29 @@ to manage and maintain a record of communication through notes of people they he

* [Slim 4 micro-framework](https://github.com/slimphp/Slim)
* [Dependency Injection](https://github.com/samuelgfeller/slim-example-project/wiki/Dependency-Injection) - [PHP-DI](https://php-di.org/)
* [Session and flash messages](https://github.com/samuelgfeller/slim-example-project/wiki/Session-and-Flash-messages)
* [Template rendering](https://github.com/samuelgfeller/slim-example-project/wiki/Template-rendering) - [PHP-View](https://github.com/slimphp/PHP-View)
* [Logging](https://github.com/samuelgfeller/slim-example-project/wiki/Logging) - [Monolog](https://github.com/Seldaek/monolog)
* [Database migrations](https://github.com/samuelgfeller/slim-example-project/wiki/Database-Migrations) - [Phinx](https://phinx.org/)
* [Validation](https://github.com/samuelgfeller/slim-example-project/wiki/Validation) - [cakephp/validation](https://book.cakephp.org/4/en/core-libraries/validation.html)
* [Database migrations](https://github.com/samuelgfeller/slim-example-project/wiki/Database-Migrations) - [Phinx](https://phinx.org/)
* [Template rendering](https://github.com/samuelgfeller/slim-example-project/wiki/Template-rendering) - [PHP-View](https://github.com/slimphp/PHP-View)
* [Mailing](https://github.com/samuelgfeller/slim-example-project/wiki/Mailing) - [Symfony Mailer](https://symfony.com/doc/current/mailer.html)
* [Localization](https://github.com/samuelgfeller/slim-example-project/wiki/Translations) - [gettext](https://www.gnu.org/software/gettext/)
* [Query Builder](https://github.com/samuelgfeller/slim-example-project/wiki/Repository-and-Query-Builder) - [cakephp/database](https://book.cakephp.org/5/en/orm/query-builder.html)
* [Integration / unit testing](https://github.com/samuelgfeller/slim-example-project/wiki/Writing-Tests) - [PHPUnit](https://github.com/sebastianbergmann/phpunit/) - [test-traits](https://github.com/samuelgfeller/test-traits)
* [Session and flash messages](https://github.com/samuelgfeller/slim-example-project/wiki/Session-and-Flash-messages) - [odan/session](https://github.com/odan/session)
* [Error handling](https://github.com/samuelgfeller/slim-example-project/wiki/Error-Handling) - [slim-error-renderer](https://github.com/samuelgfeller/slim-error-renderer)
* [GitHub Actions](https://github.com/samuelgfeller/slim-example-project/wiki/GitHub-Actions) and [Scrutinizer](https://github.com/samuelgfeller/slim-example-project/wiki/How-to-set-up-Scrutinizer)
* [GitHub Actions](https://github.com/samuelgfeller/slim-example-project/wiki/GitHub-Actions)
and [Scrutinizer](https://github.com/samuelgfeller/slim-example-project/wiki/How-to-set-up-Scrutinizer)
* [Coding standards fixer](https://github.com/samuelgfeller/slim-example-project/wiki/Coding-Standards-Fixer) - [PHP-CS-Fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer)
* [Static code analysis](https://github.com/samuelgfeller/slim-example-project/wiki/PHPStan-Static-Code-Analysis) - [PHPStan](https://github.com/phpstan/phpstan)

**Functionalities demonstrating real-world features:**

* [Authentication](https://github.com/samuelgfeller/slim-example-project/wiki/Authentication) (login)
and [authorization](https://github.com/samuelgfeller/slim-example-project/wiki/Authorization) (permissions)
* Account verification and [password reset](https://github.com/samuelgfeller/slim-example-project/wiki/Authentication#password-forgotten)
* [Authentication](https://github.com/samuelgfeller/slim-example-project/wiki/Authentication) (login)
* [Authorization](https://github.com/samuelgfeller/slim-example-project/wiki/Authorization) (permissions)
* Account verification
and [password reset](https://github.com/samuelgfeller/slim-example-project/wiki/Authentication#password-forgotten)
via email link and token
* [Request throttling](https://github.com/samuelgfeller/slim-example-project/wiki/Security#request-throttling) -
* [Request throttling](https://github.com/samuelgfeller/slim-example-project/wiki/Security#request-throttling) -
protection against brute force and password spraying attacks
* User management for administrators
* 4 user roles and different permissions
Expand All @@ -78,7 +84,6 @@ to manage and maintain a record of communication through notes of people they he
* Dashboard with panels
* [Dark / light theme](https://github.com/samuelgfeller/slim-example-project/wiki/Dark-Theme)


<details>

<summary><b>Click to see demo</b></summary>
Expand All @@ -92,72 +97,77 @@ The database is regularly reset.

## Motivation to create this project

There is a ton of great content on the internet about learning how to write clean and sustainable code.
There is a ton of great content on the internet about learning how to write clean and sustainable code.
However, I found myself searching for more than just skeleton projects or general documentations
and tutorials when I wanted to learn how to do things within the scope of a potential real-world application.
I never found resources such as an open-source, efficient implementation of all the features surrounding a
full-sized project.

This is what I try to provide here.
This is what I try to provide here.
This project isn't just a skeleton, it contains a lot of opinionated
practical examples on how to
practical examples on how to
implement features that are often needed in real-world applications.

That includes authorization, integration testing, localization, validation,
That includes authorization, integration testing, localization, validation,
error handling, database migrations, mailing, console commands, request throttling,
lightweight PHP template rendering, GitHub Actions, and more along with detailed
lightweight PHP template rendering, GitHub Actions, and more along with detailed
explanations in the documentation.

But it's not just about the features.
But it's not just about the features.
Equally important
is the [architecture](https://github.com/samuelgfeller/slim-example-project/wiki/Architecture)
and how the components interact with each other, following modern principles such as the
[Single Responsibility Principle](https://github.com/samuelgfeller/slim-example-project/wiki/Single-Responsibility-Principle-(SRP)) and
[Single Responsibility Principle](https://github.com/samuelgfeller/slim-example-project/wiki/Single-Responsibility-Principle-(SRP))
and
[Dependency Injection](https://github.com/samuelgfeller/slim-example-project/wiki/Dependency-Injection).

Of course, there are big frameworks that have their own well-established set of programming conventions and
implementations of features.

However, I find them often
too complex, where the code makes too much "behind the scenes" and with lots of dependencies,
which can lead to time-consuming refactoring on version changes.
I also dislike having to follow the propitiatory rules of a framework [which often don't
follow best practices](https://www.reddit.com/r/PHP/comments/131t2k1/laravel_considered_harmful)
follow best practices](https://www.reddit.com/r/PHP/comments/131t2k1/laravel_considered_harmful)
and
much prefer the freedom of a micro-framework and carefully
[choosing the libraries](https://github.com/samuelgfeller/slim-example-project/wiki/Libraries-and-Framework#choosing-the-right-libraries) and structure
[choosing the libraries](https://github.com/samuelgfeller/slim-example-project/wiki/Libraries-and-Framework#choosing-the-right-libraries)
and structure
that make sense for the project.
This lets me stay in control of the codebase, keep it lightweight,
performant and tailored to the needs of the project, and it's easier to maintain
and adapt to new requirements.
This lets me stay in control of the codebase, keep it lightweight,
performant and tailored to the needs of the project, and it's easier to maintain
and adapt to new requirements.

## Disclaimer

This project and its documentation are the result of my personal learning process in the last 6 years
in trying to create the best possible template app with lots of real world examples.
Three of the 6 years were spent full time on this project alone.
I made what wish I had when I started getting seriously into web development.
I made what wish I had when I started getting seriously into web development.

The codebase is big and thus lots of subjective decisions had to be made that may not be the best
long-term solution for everybody.
long-term solution for everybody.

The main focus throughout the development was to make the code as long living as possible
with best practices and few dependencies so that it can be adapted to different needs and
The main focus throughout the development was to make the code as long living as possible
with best practices and few dependencies so that it can be adapted to different needs and
preferences.

Basically, this is my take on what an efficient, extensible, and maintainable web app could look like with today's
tech.

I worked closely with the software engineer and architect
I worked closely with the software engineer and architect
[Daniel Opitz](https://odan.github.io/about.html), who also reviewed this project.
I learned a lot during
I learned a lot during
[our exchanges](https://github.com/samuelgfeller/slim-example-project/wiki/Sources-of-knowledge#discussions)
and was inspired by his books, articles, tutorials and his slim
[skeleton-project](https://github.com/odan/slim4-skeleton).
and was inspired by his books, articles, tutorials and his slim
[skeleton-project](https://github.com/odan/slim4-skeleton).

## Support
Please read the [Support❤️](https://github.com/samuelgfeller/slim-example-project/wiki/Support❤️) page

Please read the [Support❤️](https://github.com/samuelgfeller/slim-example-project/wiki/Support❤️) page
if you value this project and its documentation and want to support it.

## License
This project is licensed under the MIT License — see the

This project is licensed under the MIT License — see the
[LICENSE](LICENSE) file for details.
6 changes: 3 additions & 3 deletions config/env/env.example.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
* Incorrect: $settings['db'] = [ 'key' => 'val', 'nextKey' => 'nextVal',];
*/

// $_ENV['APP_ENV'] should be set to "prod" in the secret env.php file of the prod server.
// APP_ENV should NOT be set to "dev" in the development secret env.php as it
// would override the phpunit.xml APP_ENV setting.
// $_ENV['APP_ENV'] should be set to "prod" in the secret env.php file on the prod server.
// APP_ENV must NOT be set to "dev" in the development secret env.php as it's already the default value
// and would override the phpunit.xml APP_ENV "test" setting.

// Database
$settings['db']['host'] = 'localhost';
Expand Down
Binary file modified resources/translations/de_CH/LC_MESSAGES/messages_de_CH.mo
Binary file not shown.
16 changes: 8 additions & 8 deletions resources/translations/de_CH/LC_MESSAGES/messages_de_CH.po
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
msgid ""
msgstr ""
"Project-Id-Version: slim-example-project\n"
"POT-Creation-Date: 2024-05-08 17:32+0200\n"
"PO-Revision-Date: 2024-05-08 17:35+0200\n"
"POT-Creation-Date: 2024-05-16 12:26+0200\n"
"PO-Revision-Date: 2024-05-16 12:26+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.3\n"
"X-Generator: Poedit 3.4.4\n"
"X-Poedit-Basepath: ../../../..\n"
"X-Poedit-KeywordsList: __\n"
"X-Poedit-SearchPath-0: src\n"
Expand Down Expand Up @@ -337,7 +337,7 @@ msgstr ""
"Posteingang auf eine ausführlichere Nachricht."

#: src/Domain/Authentication/Service/PasswordRecoveryEmailSender.php:72
#: templates/authentication/reset-password.html.php:54
#: templates/authentication/reset-password.html.php:58
msgid "Reset password"
msgstr "Passwort zurücksetzen"

Expand Down Expand Up @@ -644,12 +644,12 @@ msgstr "Ungültiges Passwort"

#: templates/authentication/login.html.php:73
#: templates/authentication/login.html.php:90
#: templates/authentication/reset-password.html.php:86
#: templates/authentication/reset-password.html.php:91
msgid "Login"
msgstr "Anmelden"

#: templates/authentication/login.html.php:80
#: templates/authentication/reset-password.html.php:67
#: templates/authentication/reset-password.html.php:72
#: templates/user/user-read.html.php:118
msgid "Password"
msgstr "Passwort"
Expand All @@ -662,11 +662,11 @@ msgstr "Passwort vergessen"
msgid "Request password"
msgstr "Passwort anfordern"

#: templates/authentication/reset-password.html.php:77
#: templates/authentication/reset-password.html.php:82
msgid "Repeat password"
msgstr "Passwort wiederholen"

#: templates/authentication/reset-password.html.php:91
#: templates/authentication/reset-password.html.php:96
msgid "Set new password"
msgstr "Neues Passwort festlegen"

Expand Down
Binary file modified resources/translations/fr_CH/LC_MESSAGES/messages_fr_CH.mo
Binary file not shown.
18 changes: 9 additions & 9 deletions resources/translations/fr_CH/LC_MESSAGES/messages_fr_CH.po
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
msgid ""
msgstr ""
"Project-Id-Version: slim-example-project\n"
"POT-Creation-Date: 2024-05-08 17:34+0200\n"
"PO-Revision-Date: 2024-05-08 17:35+0200\n"
"POT-Creation-Date: 2024-05-16 12:33+0200\n"
"PO-Revision-Date: 2024-05-16 12:33+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.3\n"
"X-Generator: Poedit 3.4.4\n"
"X-Poedit-Basepath: ../../../..\n"
"X-Poedit-KeywordsList: __\n"
"X-Poedit-SearchPath-0: src\n"
Expand Down Expand Up @@ -334,7 +334,7 @@ msgstr ""
"réception pour un message plus détaillé."

#: src/Domain/Authentication/Service/PasswordRecoveryEmailSender.php:72
#: templates/authentication/reset-password.html.php:54
#: templates/authentication/reset-password.html.php:58
msgid "Reset password"
msgstr "Réinitialiser mot de passe"

Expand Down Expand Up @@ -640,12 +640,12 @@ msgstr "Mot de passe incorrect"

#: templates/authentication/login.html.php:73
#: templates/authentication/login.html.php:90
#: templates/authentication/reset-password.html.php:86
#: templates/authentication/reset-password.html.php:91
msgid "Login"
msgstr "Login"

#: templates/authentication/login.html.php:80
#: templates/authentication/reset-password.html.php:67
#: templates/authentication/reset-password.html.php:72
#: templates/user/user-read.html.php:118
msgid "Password"
msgstr "Mot de passe"
Expand All @@ -658,11 +658,11 @@ msgstr "Mot de passe oublié"
msgid "Request password"
msgstr "Recevoir mot de passe"

#: templates/authentication/reset-password.html.php:77
#: templates/authentication/reset-password.html.php:82
msgid "Repeat password"
msgstr "Répéter le mot de passe"

#: templates/authentication/reset-password.html.php:91
#: templates/authentication/reset-password.html.php:96
msgid "Set new password"
msgstr "Enregistrer"

Expand Down Expand Up @@ -756,7 +756,7 @@ msgstr ""

#: templates/error/error-page.html.php:65
msgid "This is what I did before the error happened:"
msgstr "Qu'avez vous fait précisément avant que l'erreur ne se produise?"
msgstr "Voici ce que j'ai fait précisément avant que l'erreur ne se produise:"

#: templates/error/error-page.html.php:82
msgid "Report the issue"
Expand Down

0 comments on commit 4eb3a56

Please sign in to comment.