An open API service indexing awesome lists of open source software.

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...

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


Github



#### 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 🦆








Eric Neves















#### License 📋