https://github.com/ericneves/myfavoritebooks
App created with PHP, PostgreSQL, Angular, PrimeNG, SOLID Principles, Package-By-Feature and more...
https://github.com/ericneves/myfavoritebooks
angular package-by-feature php postgresql primeng use-cases
Last synced: 3 months ago
JSON representation
App created with PHP, PostgreSQL, Angular, PrimeNG, SOLID Principles, Package-By-Feature and more...
- Host: GitHub
- URL: https://github.com/ericneves/myfavoritebooks
- Owner: EricNeves
- License: mit
- Created: 2024-06-09T18:59:33.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-07-06T15:21:53.000Z (almost 2 years ago)
- Last Synced: 2025-06-01T18:39:35.014Z (about 1 year ago)
- Topics: angular, package-by-feature, php, postgresql, primeng, use-cases
- Language: PHP
- Homepage:
- Size: 648 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
Awesome Lists containing this project
README
My Favorite Books
Aplicação desenvolvida com PHP e Angular, porém, com o foco direcionado ao app em PHP que foi criado baseado nos princípios SOLID e na arquitetura package-by-feature, garantindo maior legibilidade e organização do código, bem como a implementação de testes automatizados.
Data de criação: Jun 9, 2024

#### Intro 📜
A aplicação com **PHP** adota princípios de design de software, como os **princípios SOLID**, e uma arquitetura modular baseada em funcionalidades (**package-by-feature**). Essa abordagem garante que o código seja bem estruturado, fácil de entender e manter, além de permitir uma escalabilidade e extensibilidade mais simples.
> [!NOTE]
> O **upload** das imagens é relativamente simples, com **validação** e salvas no formato **BLOB** (**Binary Large Object**), num **cenário real**, seriam salvas em uma **CDN** (**Content Delivery Network**).
#### Features 💡
- 📁 Padrão Package By Feature
- 🙍 User
- Criar usuário
- Autenticação - JWT
- Informações do Usuário
- Editar Usuário
- 📚 Book
- Criar livro
- Editar livro
- Informações de um livro
- Todos os livros
- Remover um livro
- ⚡ Dependencies:
- phpunit/phpunit: `^10.5`
- vlucas/phpdotenv: `^5.6`
- @angular/cli: `^17.3.8`
- primeng: `^17.18.1`,
- and more...
- 📡 DevOps
- NGINX
- Docker
#### Doc 📑
### Routes
>
> [!NOTE]
> Para adicionar uma nova **rota**, deve-se levar em consideração os **use cases**, **controllers** e as **factories**.
>
```
|-- routes
| |-- api.php
|-- config
| |-- factories.php
|-- UseCases
| |-- Intro
| | |-- WelcomeMessage
| | | |-- WelcomeMessageController.php
| | | |-- WelcomeMessageFactory.php
| | | |-- IWelcomeMessageUseCase.php
| | | |-- WelcomeMessageUseCase.php
```
Em `routes/api.php`, referencie o **controller** através do **namespace**. Porém, deve-se remover o `App\UseCases\`, mantendo apenas o restante, nesse caso, `Intro\WelcomeMessage\WelcomeMessageController`.
Exemplo:
```php
> [!NOTE]
> A `factory` é responsável por criar as **instâncias** e injetar as **depedências**.
>
```php
return [
'Intro\WelcomeMessage\WelcomeMessageController' => App\UseCases\Intro\WelcomeMessage\WelcomeMessageFactory::class
];
```
### Use Cases
De modo geral, será exemplificado a criação de um **use case** incluindo recursos como **banco de dados**.
```
|-- Providers
| |-- IUserPostgresProvider.php
| |-- Implementation
| | |-- UserPostgresProvider.php
|-- Repositories
| |-- UserRepository.php
|-- UseCases
| |-- User
| | |-- FetchUser
| | | |-- FetchUserController.php
| | | |-- FetchUserFactory.php
| | | |-- IFetchUserUseCase.php
| | | |-- FetchUserUseCase.php
```
> [!NOTE]
> `IUserPostgresProvider` será responsável por definir os contratos de consultas SQL.
>
```php
[!NOTE]
> `UserPostgresProvider` será responsável pela implementação das consultas SQL (`IUserPostgresProvider`).
> No **construtor** de `UserPostgresProvider` é passado como **injeção de depedência** a classe `PDO`.
>
```php
pdo->query("...");
}
}
```
> [!NOTE]
> `IUserRepository` será responsável por definir o contrato de persistência dos dados.
>
```php
[!NOTE]
> `UserRepository` será responsável por implementar os contratos definidos por `IUserRepository`.
> No **construtor** de `UserRepository` é passado como **inversão de depedência** a interface `IUserPostgresProvider`.
>
```php
database->fetch($id);
}
}
```
> [!NOTE]
> `IFetchUserUseCase` será responsável por definir o contrato do **use case**.
>
```php
[!NOTE]
> `FetchUserUseCase` será responsável por implementar `IFetchUserUseCase`, bem como as regras de negócio e nesse caso realizar operações através do **repository**.
> No **construtor** de `FetchUserUseCase` é passado como **inversão de depedência** o `IUserRepository`.
>
```php
userRepository->fetchUser($userId);
if (!$user) {
throw new Exception('Sorry, user not found.');
}
return $user;
}
}
```
> [!NOTE]
> No construtor do **controller** é passado como **inversão de depedência** a interface `IFetchUserUseCase`.
```php
json([
"data" => $this->fetchUserUseCase->execute($request->user()->id),
]);
}
}
```
> [!NOTE]
> Por último deve-se passar as implementações dos contratos na **factory** do **use case**.
>
```php
[!NOTE]
> `$databaseConfig` que é passado como paramêtro em `generateInstance`, é o array definido em `config/database.php`.
> Se quiser mudar o provider de **postgresql** para **mysql** por exemplo, será necessário definir as configurações do **novo banco**.
>
No exemplo será mostrado a configuração do **mysql** com **PDO**, mas, caso deseje usar **mysqlli** ou algum **ORM**, basta criar a conexão como no exemplo abaixo e implementar o **provider**.
`config/database.php`
```php
[
'host' => $_ENV['PG_HOST'],
'port' => $_ENV['PG_PORT'],
'database' => $_ENV['PG_DATABASE'],
'username' => $_ENV['PG_USERNAME'],
'password' => $_ENV['PG_PASSWORD'],
],
'mysql' => [
'host' => '...',
'database' => '...',
'username' => '...',
'password' => '...'
]
];
```
`Infrastructure/Mysql.php`
```php
json(['message' => 'Unauthorized'], 401);
}
}
}
```
O próximo passado será associar o **middleware** com uma **chave única** em `config/middlewares.php`.
```php
App\Middlewares\EnsureAuthenticatedMiddleware::class,
'equal' => App\Middlewares\NewMiddleware::class,
]
```
Por último é só usar o **middleware** na **rota**.
```php
Router::get('/users/fetch', 'User\FetchUser\FetchUserController')->middlewares('auth', 'equal');
```
#### Execution ⚙️
>
> [!NOTE]
> Siga os passos abaixo para a execução do projeto em **ambiente de desenvolvimento**.
O primeiro passo, é renomear o arquivo `.env.example` para `.env`, o mesmo se encontra em `/www`.
```sh
# Install deps www/
$ cd www && composer install
# Install deps web/
$ cd web && pnpm install
# Docker
$ docker compose -f "docker-compose-dev.yml" up -d --build
# Tests
$ cd www && composer test
```
#### Author 🦆
#### License 📋