#+TITLE: Containers
* Contenuti :TOC:
+- [[#perchè-i-container][Perchè i container]]
- [[#gestione-containers][Gestione containers]]
- [[#creazione-ed-esecuzione-containers][Creazione ed esecuzione containers]]
+* Perchè i container
+Ho deciso di realizzare questo progetto utilizzando i container per poter separare i processi server in esecuzione dall'ambiente di sviluppo.
+In questo modo ho a disposizione 3 container isolati, con il proprio file system, che sono facilmente spostabili ad altre macchine.
+
+Un'alternativa ai container poteva essere l'utilizzo delle virtual machine che però possono causare svariati problemi:
+- utilizzo maggiore delle risorse hardware, dato che una virtual machine ha il proprio hardware virtuale, il proprio sistema operativo, i propri driver e servizi in esecuzione
+- maggiore difficoltà nell'installazione e configurazione dei server, tramite Dockerfile e docker-compose configurare ed installare i server nel container è molto semplice a differenza delle VM dove è necessario eseguire tutto manualmente
+
* Gestione containers
La creazione e gestione dei container viene effettuata tramite *docker-compose* ed il file di configurazione [[./docker-compose.yml][docker-compose.yml]].
Il file di configurazione utilizza il linguaggio markup YAML ed è composto da 2 parti principali:
* Realizzazione
La web app è strutturata seguendo il *Model View Controller* framework.
+Quando un utente visita la pagina, viene inizializzato il core dell'applicazione.
+Il core è dotato di diversi classi fondamentali per il corretto funzionamento della web app, tra cui:
+- Application
+- Router
+- Session
+- Le base class per model e controller
+
Per gestire le dipendenze e namespaces di PHP viene utilizzato *composer*.
** Entry point - index.php
-La home page, si occupa di inizializzare l'applicazione ed impostare le route con annesso array [Controller, metodo].
+La home page, si occupa di inizializzare l'applicazione ed impostare le route.
+Una route è formata da:
+- *metodo*: rappresentato dal metodo della classe router utilizzato (/come in esempio/)
+- *path*: il primo parametro da passare al metodo get/post del router (nell'esempio "/")
+- *callback*: il secondo parametro da passare al metodo e può essere:
+ + una funzione che verrà eseguita quando l'utente visita il path specificato
+ + il nome di una *view*, deve coincidere con un file nella directory view
+ + un array formato da [ *ControllerClass*, "*metodo*" ]
#+begin_src php
$app = new Application(dirname(__DIR__));
-$app->router->get("/", [SiteController::class, "home"]);
-#+end_src
-** Core
-*** Main application class
-La classe principale, si occupa di istanziare:
-- la Router class
-- la Request helper class
-- la Response helper class
+# Esempio con funzione
+$app->router->get("/esempio0", function () {
+ echo "hello world!";
+});
-Rappresenta il fulcro della web app.
-Rende possibile l'accesso a tutte le classi da essa istaziate tramite la viariabile statica "$app".
+# Esempio con sola view
+$app->router->get("/esempio1", "home");
+
+# Esempio con controller
+$app->router->get("/esempio2", [SiteController::class, "home"]);
+#+end_src
-Gestisce tutti i controller tramite "BaseController".
+Una volta impostate tutte le route disponibili viene chiamato il metodo "run()".
+Questo metodo a sua volta chiama il router per risolvere la richiesta effettuata utente.
+** Core
*** Router class
Una delle classi principali è il Router, gestisce l'array associativo "$routes" e la risoluzione delle varie request effettuate.
#+end_src
*** Database class
-Il compito della Database class è quello di effettuare una connessione al server mariadb in esecuzione sul docker container ed applicare delle [[./www/Migrations][migration]].
-Sia le credenziali di accesso al database che il domain service name (DSN) sono salvate nel file "www/.env" (vedi [[./www/.env.example][.env.example]]) e per leggerle si utilizza il package [[https://github.com/vlucas/phpdotenv][phpdotenv]].
+Il compito della Database class è quello di effettuare una connessione al server mariadb in esecuzione sul docker container ed applicare delle [[./Migrations][migration]].
+Sia le credenziali di accesso al database che il domain service name (DSN) sono salvate nel file "www/.env" (vedi [[./.env.example][.env.example]]) e per leggerle si utilizza il package [[https://github.com/vlucas/phpdotenv][phpdotenv]].
Installazione phpdotenv:
#+begin_src bash
- selezionare le migration presenti nella migration table
- per ogni migration non presente nel DB, creare un'istanza ed esegue il metodo "up()"
-*** Database model class
-La classe DbModel si basa sulla base Database class ma viene trattata come l'effettiva SQL table.
-
** Migrations
-
È importante che le migration class siano ordinate e che seguano tutte lo stesso stile di nomeclatura.
-La creazione di una migration class può essere effettuata tramite lo script [[./scripts/createMigration.sh][createMigration]].
+La creazione di una migration class può essere effettuata tramite lo script [[../scripts/createMigration.sh][createMigration]].
#+begin_src bash
./scripts/createMigration pathToMigrationsDir migrationName
#+end_src
- "down()": esegue del codice SQL per annullare la modifica
** Models
-Le classi "Model" gestiscono i dati presenti nel database e controlla che i dati seguano delle determinate regole.
+Le classi "Model" gestiscono i dati presenti nel database o inseriti dall'utente e controllano che i dati seguano delle determinate regole.
Tutte le classi Model derivano dalla classe "BaseModel" o "DbModel".
*** Registration model - User model
Simile al model di registrazione ma con 2 importanti metodi:
- *getVtuberInfo()*: controlla che il link inserito sia l'URL ad un canale twitch o youtube ed utilizzando i rispettivi API(Twitch o Google) recupara le informazioni della vtuber in questione
-- *isLive()*: controlla se la vtuber in questione è live o no, utilizzando l'API Twitch o tramite curl request per canali YT
+- *isLive()*: controlla se la vtuber in questione è live o no
** Controllers
-Le classi "Controller" svolgono il ruolo di ponte.
+Le classi "Controller" svolgono il ruolo di ponte tra:
+- view <-> utente
+- view <-> model
+
Esse permettono ai dati di apparire nella View richiesta dall'utente una volta prelevati dal database o di venirvi inseriti tramite una form.
*** Authentication controller
-L'authentication controller ha 2 compiti fondamentali:
-- registrare nuovi utenti con l'aiuto della classe "RegisterModel"
-- permettere l'accesso ad utenti già registrati
+L'authentication controller ha 3 compiti fondamentali:
+- registrare nuovi utenti (register)
+- permettere l'accesso ad utenti già registrati (login)
+- permettere ad utente registrati di uscire dal proprio account (logout)
+
+*** SiteController
+Questo controller è il controller principale della pagina, implementa infatti i 2 metodi:
+- *list()*: effettua il check dei dati in trasito verso la pagina contente la lista di vtuber preferite dell'utente
+- *live()*: effettua il check dei dati in trasito verso la pagina principale
class SiteController extends BaseController
{
- public function list()
+ public function list(Request $req)
{
Application::$app->router->title = "WeebSite - Your top vtubers";
$this->setLayout("list");
+
+ if ($req->getMethod() == "post") {
+ if (isset($req->getBody()["rem"])) {
+ $stmt = Application::$app->db->pdo->prepare("DELETE FROM favoriteVtuber WHERE _userID=" . Application::$app->user->id . " AND _vtuberID=" . $req->getBody()["rem"]);
+ $stmt->execute();
+ } else if (isset($req->getBody()["notNotify"])) {
+ $stmt = Application::$app->db->pdo->prepare("UPDATE favoriteVtuber SET notify=0 WHERE _vtuberID=" . $req->getBody()["notNotify"]);
+ $stmt->execute();
+ } else if (isset($req->getBody()["notify"])) {
+ $stmt = Application::$app->db->pdo->prepare("UPDATE favoriteVtuber SET notify=1 WHERE _vtuberID=" . $req->getBody()["notify"]);
+ $stmt->execute();
+ }
+ }
+
return $this->render("list");
}
$statement->execute();
foreach ($statement->fetchAll() as $vtuber) {
- $params[] = [ $vtuber, $vtuberModel->isLive($vtuber["login"], $vtuber["link"]) ];
+ $params[] = [$vtuber, $vtuberModel->isLive($vtuber["login"], $vtuber["link"])];
if ($singleVtuber) {
- Application::$app->router->title = "WeebSite - ".$vtuber["username"];
+ Application::$app->router->title = "WeebSite - " . $vtuber["username"];
}
}
}
use app\core\Application;
-if (!Application::isGuest()) :
-?>
+if (!Application::isGuest()) {
+ $stmt = Application::$app->db->pdo->prepare("
+SELECT vtubers.id, img, vtubers.username, notify
+FROM users, vtubers, favoriteVtuber
+WHERE users.id = _userID
+AND vtubers.id = _vtuberID
+AND users.id = ". Application::$app->user->id);
+ $stmt->execute();
+ while ($row = $stmt->fetch()) {
+ if ($row["notify"] == 1) {
+ $disable = "";
+ $enable = "disabled";
+ } else {
+ $disable = "disabled";
+ $enable = "";
+ }
-<?php
-else:
- Application::$app->res->redirect("/");
+ echo "
+<tr>
+<td><img class='vtuber-img' src=\"{$row["img"]}\"/></td>
+<td>{$row["username"]}</td>
+<td>
+ <form method='POST'>
+ <button type='submit' name='rem' value='{$row["id"]}' class='btn btn-outline-danger'>Remove from favorites</button>
+ </form>
+</td>
+<td>
+ <form method='POST'>
+ <button type='submit' name='notNotify' value='{$row["id"]}' class='btn btn-outline-danger' ". $disable .">Disable notifications</button>
+ </form>
+</td>
+<td>
+ <form method='POST'>
+ <button type='submit' name='notify' value='{$row["id"]}' class='btn btn-outline-primary' $enable>Enable notifications</button>
+ </form>
+</td>
+</tr>
+";
+ }
-endif; ?>
+}
+else {
+ Application::$app->res->redirect("/");
+}
+?>