]> git.leonardobizzoni.com Git - highschool-graduation-project/commitdiff
Generic controllers + multiple layouts
authorLeonardoBizzoni <leo2002714@gmail.com>
Sun, 17 Apr 2022 10:55:11 +0000 (12:55 +0200)
committerLeonardoBizzoni <leo2002714@gmail.com>
Sun, 17 Apr 2022 10:55:11 +0000 (12:55 +0200)
14 files changed:
README.org
www/controllers/AuthController.php [new file with mode: 0644]
www/controllers/SiteController.php [new file with mode: 0644]
www/core/Application.php
www/core/BaseController.php [new file with mode: 0644]
www/core/Request.php
www/core/Router.php
www/pub/index.php
www/views/contact.php
www/views/home.php
www/views/layouts/auth.php [new file with mode: 0644]
www/views/layouts/main.php
www/views/login.php [new file with mode: 0644]
www/views/register.php [new file with mode: 0644]

index c2bf2a9491f68c280e8c43b8474840158e62276c..a70efaf5a18704a1a167b1ee1f8010d16b4f3b9c 100644 (file)
@@ -11,6 +11,7 @@
 - [[#realizzazione][Realizzazione]]
   - [[#entry-point---indexphp][Entry point - index.php]]
   - [[#core][Core]]
+  - [[#controllers][Controllers]]
   - [[#views][Views]]
 
 * Descrizione del progetto
@@ -141,16 +142,24 @@ La home page, si occupa di inizializzare l'applicazione ed impostare le route co
 #+begin_src php :tangle www/pub/index.php
 <?php
 require_once __DIR__."/../vendor/autoload.php";
+
+use app\controllers\AuthController;
+use app\controllers\SiteController;
 use app\core\Application;
 
 $app = new Application(dirname(__DIR__));
 
-$app->router->get("/", "home");
-$app->router->get("/contact", "contact");
+$app->router->get("/", [SiteController::class, "home"]);
+
+$app->router->get("/contact", [SiteController::class, "contact"]);
+$app->router->post("/contact", [SiteController::class, "handleContact"]);
+
+# User authentication
+$app->router->get("/login", [AuthController::class, "login"]);
+$app->router->post("/login", [AuthController::class, "login"]);
 
-$app->router->post("/contact", function() {
-    echo "handling submitted data";
-});
+$app->router->get("/register", [AuthController::class, "register"]);
+$app->router->post("/register", [AuthController::class, "register"]);
 
 $app->run();
 ?>
@@ -165,6 +174,8 @@ La classe principale, si occupa di instanziare il Router e la Request helper cla
 namespace app\core;
 
 class Application {
+    private BaseController $controller;
+
     public Router $router;
     public Request $req;
     public Response $res;
@@ -184,6 +195,14 @@ class Application {
     public function run() {
         echo $this->router->resolve();
     }
+
+    public function getController() {
+        return $this->controller;
+    }
+
+    public function setController(BaseController $controller) {
+        $this->controller = $controller;
+    }
 }
 ?>
 #+end_src
@@ -252,30 +271,39 @@ class Router
         $callback = $this->routes[$method][$path] ?? false;
 
         if (is_string($callback)) {
-            echo $this->renderView($callback);
-        } else if ($callback) {
-            return call_user_func($callback);
+            return $this->renderView($callback);
+        } else if (is_array($callback)) {
+            Application::$app->setController(new $callback[0]);
+            $callback[0] = Application::$app->getController();
         } else {
             $this->res->setStatusCode(404);
-            echo $this->renderView("404");
+            return $this->renderView("404");
         }
+
+        return call_user_func($callback, $this->req);
     }
 
-    public function renderView(string $view)
+    public function renderView(string $view, array $params = [])
     {
         $layoutContent = $this->loadLayoutContent();
-        $viewContent = $this->loadViewContent($view);
+        $viewContent = $this->loadViewContent($view, $params);
 
         return str_replace("{{content}}", $viewContent, $layoutContent);
     }
 
     private function loadLayoutContent() {
+        $layout = Application::$app->getController()->layout;
         ob_start();
-        include_once Application::$ROOT_DIR."/views/layouts/main.php";
+        include_once Application::$ROOT_DIR."/views/layouts/$layout.php";
         return ob_get_clean();
     }
 
-    private function loadViewContent(string $view) {
+    private function loadViewContent(string $view, array $params) {
+        # modo epico per creare variabili con lo stesso nome assegnato nell'array!!
+        foreach ($params as $key => $value) {
+            $$key = $value;
+        }
+
         ob_start();
         include_once Application::$ROOT_DIR."/views/$view.php";
         return ob_get_clean();
@@ -311,10 +339,22 @@ class Request {
     }
 
     public function getBody() {
-        # TODO
-    }
+        $body = [];
+
+        if ($this->getMethod() == "get") {
+            foreach ($_GET as $key => $value) {
+                $body[$key] = filter_input(INPUT_GET, $key, FILTER_SANITIZE_SPECIAL_CHARS);
+            }
+        }
+        else if ($this->getMethod() == "post") {
+            foreach ($_POST as $key => $value) {
+                $body[$key] = filter_input(INPUT_POST, $key, FILTER_SANITIZE_SPECIAL_CHARS);
+            }
+        }
+
+        return $body;
+        }
 }
-?>
 #+end_src
 
 *** Response class
@@ -330,29 +370,106 @@ class Response {
 ?>
 #+end_src
 
+*** Base controller class
+#+begin_src php :tangle www/core/BaseController.php
+<?php
+namespace app\core;
+
+class BaseController {
+    public string $layout = "main";
+
+    public function render(string $view, array $params = []) {
+        return Application::$app->router->renderView($view, $params);
+    }
+
+    public function setLayout(string $layout) {
+        $this->layout = $layout;
+    }
+}
+?>
+#+end_src
+
+** Controllers
+*** General controller
+#+begin_src php :tangle www/controllers/SiteController.php
+<?php
+namespace app\controllers;
+
+use app\core\BaseController;
+use app\core\Request;
+
+class SiteController extends BaseController {
+    public function home() {
+        $params = [
+            "name" => "Leonardo"
+        ];
+
+        return $this->render("home", $params);
+    }
+
+    public function contact() {
+        return $this->render("contact");
+    }
+
+    public function handleContact(Request $req) {
+        $body = $req->getBody();
+
+        # $body validation
+
+        return "Handling submitted data";
+    }
+}
+?>
+#+end_src
+
+*** Authentication controller
+#+begin_src php :tangle www/controllers/AuthController.php
+<?php
+namespace app\controllers;
+
+use app\core\BaseController;
+use app\core\Request;
+
+class AuthController extends BaseController{
+    public function login() {
+        $this->setLayout("auth");
+        return $this->render("login");
+    }
+
+    public function register(Request $req) {
+        $this->setLayout("auth");
+        if ($req->getMethod() == "post") {
+            return "Handling submitted data";
+        }
+        return $this->render("register");
+    }
+}
+#+end_src
+
 ** Views
 *** Home
 #+begin_src php :tangle www/views/home.php
 <h1>Hello, World!</h1>
+<h3>Welcome, <?php echo $name ?>!</h1>
 #+end_src
 
 *** Contact
 #+begin_src php :tangle www/views/contact.php
 <h1>Contact page</h1>
 
-    <div class="container">
+<div class="container">
 <form action="" method="post">
   <div class="mb-3">
     <label for="exampleInputEmail1" class="form-label">Email address</label>
-    <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
+    <input name="email" type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
     <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
   </div>
   <div class="mb-3">
     <label for="exampleInputPassword1" class="form-label">Password</label>
-    <input type="password" class="form-control" id="exampleInputPassword1">
+    <input name="pass" type="password" class="form-control" id="exampleInputPassword1">
   </div>
   <div class="mb-3 form-check">
-    <input type="checkbox" class="form-check-input" id="exampleCheck1">
+    <input name="check" type="checkbox" class="form-check-input" id="exampleCheck1">
     <label class="form-check-label" for="exampleCheck1">Check me out</label>
   </div>
   <button type="submit" class="btn btn-primary">Submit</button>
@@ -360,6 +477,67 @@ class Response {
 </div>
 #+end_src
 
+*** Login
+#+begin_src php :tangle www/views/login.php
+<h1>Login page</h1>
+
+<div class="container">
+<form action="" method="post">
+  <div class="mb-3">
+    <label for="exampleInputEmail1" class="form-label">Email address</label>
+    <input name="email" type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
+    <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
+  </div>
+  <div class="mb-3">
+    <label for="exampleInputPassword1" class="form-label">Password</label>
+    <input name="pass" type="password" class="form-control" id="exampleInputPassword1">
+  </div>
+  <div class="mb-3 form-check">
+    <input name="check" type="checkbox" class="form-check-input" id="exampleCheck1">
+    <label class="form-check-label" for="exampleCheck1">Check me out</label>
+  </div>
+  <button type="submit" class="btn btn-primary">Submit</button>
+</form>
+</div>
+#+end_src
+
+*** Register
+#+begin_src php :tangle www/views/register.php
+<h1>Registration page</h1>
+
+<div class="container">
+    <form method="POST" class="row g-3">
+        <div class="col-md-4">
+            <label class="form-label">Firstname</label>
+            <input name="name" type="text" class="form-control">
+        </div>
+        <div class="col-md-4">
+            <label class="form-label">Lastname</label>
+            <input name="lastname" type="text" class="form-control">
+        </div>
+        <div class="col-md-4">
+            <label class="form-label">Email</label>
+            <input name="email" type="email" class="form-control">
+        </div>
+        <div class="col-md-12">
+            <label class="form-label">Username</label>
+            <input name="username" type="text" class="form-control">
+        </div>
+        <div class="col-md-6">
+            <label class="form-label">Password</label>
+            <input name="pass" type="password" class="form-control">
+        </div>
+        <div class="col-md-6">
+            <label class="form-label">Password confirm</label>
+            <input name="passConf" name="pass" type="password" class="form-control">
+        </div>
+        <div class="col-12">
+            <button type="submit" class="btn btn-primary">Sign in</button>
+        </div>
+    </form>
+</div>
+#+end_src
+
 *** 404
 #+begin_src php :tangle www/views/404.php
 <h1>404 - File not found!</h1>
diff --git a/www/controllers/AuthController.php b/www/controllers/AuthController.php
new file mode 100644 (file)
index 0000000..e9b4da7
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+namespace app\controllers;
+
+use app\core\BaseController;
+use app\core\Request;
+
+class AuthController extends BaseController{
+    public function login() {
+        $this->setLayout("auth");
+        return $this->render("login");
+    }
+
+    public function register(Request $req) {
+        $this->setLayout("auth");
+        if ($req->getMethod() == "post") {
+            return "Handling submitted data";
+        }
+        return $this->render("register");
+    }
+}
diff --git a/www/controllers/SiteController.php b/www/controllers/SiteController.php
new file mode 100644 (file)
index 0000000..913bf56
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+namespace app\controllers;
+
+use app\core\BaseController;
+use app\core\Request;
+
+class SiteController extends BaseController {
+    public function home() {
+        $params = [
+            "name" => "Leonardo"
+        ];
+
+        return $this->render("home", $params);
+    }
+
+    public function contact() {
+        return $this->render("contact");
+    }
+
+    public function handleContact(Request $req) {
+        $body = $req->getBody();
+
+        # $body validation
+
+        return "Handling submitted data";
+    }
+}
+?>
index e5567c0605e027d3c447d144349489472fc232fc..9ffc41642e833d00b6f056cf8682d2e8a27d3499 100644 (file)
@@ -2,6 +2,8 @@
 namespace app\core;
 
 class Application {
+    private BaseController $controller;
+
     public Router $router;
     public Request $req;
     public Response $res;
@@ -21,5 +23,13 @@ class Application {
     public function run() {
         echo $this->router->resolve();
     }
+
+    public function getController() {
+        return $this->controller;
+    }
+
+    public function setController(BaseController $controller) {
+        $this->controller = $controller;
+    }
 }
 ?>
diff --git a/www/core/BaseController.php b/www/core/BaseController.php
new file mode 100644 (file)
index 0000000..3e9f34d
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+namespace app\core;
+
+class BaseController {
+    public string $layout = "main";
+
+    public function render(string $view, array $params = []) {
+        return Application::$app->router->renderView($view, $params);
+    }
+
+    public function setLayout(string $layout) {
+        $this->layout = $layout;
+    }
+}
+?>
index 05eb05c0062c941f624fae618ed33db174a7315d..e3ec72f93bc469a3573cee1072771ada9c1567a9 100644 (file)
@@ -17,7 +17,19 @@ class Request {
     }
 
     public function getBody() {
-        # TODO
-    }
+        $body = [];
+
+        if ($this->getMethod() == "get") {
+            foreach ($_GET as $key => $value) {
+                $body[$key] = filter_input(INPUT_GET, $key, FILTER_SANITIZE_SPECIAL_CHARS);
+            }
+        }
+        else if ($this->getMethod() == "post") {
+            foreach ($_POST as $key => $value) {
+                $body[$key] = filter_input(INPUT_POST, $key, FILTER_SANITIZE_SPECIAL_CHARS);
+            }
+        }
+
+        return $body;
+        }
 }
-?>
index 6589ac4c4098535795d376694f3c92eedf57efa6..1bda1fc5e5ff9fbb4fd68a950d7b96f8ef32a420 100644 (file)
@@ -33,30 +33,39 @@ class Router
         $callback = $this->routes[$method][$path] ?? false;
 
         if (is_string($callback)) {
-            echo $this->renderView($callback);
-        } else if ($callback) {
-            return call_user_func($callback);
+            return $this->renderView($callback);
+        } else if (is_array($callback)) {
+            Application::$app->setController(new $callback[0]);
+            $callback[0] = Application::$app->getController();
         } else {
             $this->res->setStatusCode(404);
-            echo $this->renderView("404");
+            return $this->renderView("404");
         }
+
+        return call_user_func($callback, $this->req);
     }
 
-    public function renderView(string $view)
+    public function renderView(string $view, array $params = [])
     {
         $layoutContent = $this->loadLayoutContent();
-        $viewContent = $this->loadViewContent($view);
+        $viewContent = $this->loadViewContent($view, $params);
 
         return str_replace("{{content}}", $viewContent, $layoutContent);
     }
 
     private function loadLayoutContent() {
+        $layout = Application::$app->getController()->layout;
         ob_start();
-        include_once Application::$ROOT_DIR."/views/layouts/main.php";
+        include_once Application::$ROOT_DIR."/views/layouts/$layout.php";
         return ob_get_clean();
     }
 
-    private function loadViewContent(string $view) {
+    private function loadViewContent(string $view, array $params) {
+        # modo epico per creare variabili con lo stesso nome assegnato nell'array!!
+        foreach ($params as $key => $value) {
+            $$key = $value;
+        }
+
         ob_start();
         include_once Application::$ROOT_DIR."/views/$view.php";
         return ob_get_clean();
index 5c05d91c5031f830b0d6176acd15a4de801a5e56..e2ef83fa3a23d2e98385d85d23176cf27c1afb25 100644 (file)
@@ -1,15 +1,23 @@
 <?php
 require_once __DIR__."/../vendor/autoload.php";
+
+use app\controllers\AuthController;
+use app\controllers\SiteController;
 use app\core\Application;
 
 $app = new Application(dirname(__DIR__));
 
-$app->router->get("/", "home");
-$app->router->get("/contact", "contact");
+$app->router->get("/", [SiteController::class, "home"]);
+
+$app->router->get("/contact", [SiteController::class, "contact"]);
+$app->router->post("/contact", [SiteController::class, "handleContact"]);
+
+# User authentication
+$app->router->get("/login", [AuthController::class, "login"]);
+$app->router->post("/login", [AuthController::class, "login"]);
 
-$app->router->post("/contact", function() {
-    echo "handling submitted data";
-});
+$app->router->get("/register", [AuthController::class, "register"]);
+$app->router->post("/register", [AuthController::class, "register"]);
 
 $app->run();
 ?>
index d1c4d6c421317ada07249805ac2383977e1e787f..2df0027c41fa94b90fb2aad3b64e334e551f61b1 100644 (file)
@@ -1,18 +1,18 @@
 <h1>Contact page</h1>
 
-    <div class="container">
+<div class="container">
 <form action="" method="post">
   <div class="mb-3">
     <label for="exampleInputEmail1" class="form-label">Email address</label>
-    <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
+    <input name="email" type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
     <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
   </div>
   <div class="mb-3">
     <label for="exampleInputPassword1" class="form-label">Password</label>
-    <input type="password" class="form-control" id="exampleInputPassword1">
+    <input name="pass" type="password" class="form-control" id="exampleInputPassword1">
   </div>
   <div class="mb-3 form-check">
-    <input type="checkbox" class="form-check-input" id="exampleCheck1">
+    <input name="check" type="checkbox" class="form-check-input" id="exampleCheck1">
     <label class="form-check-label" for="exampleCheck1">Check me out</label>
   </div>
   <button type="submit" class="btn btn-primary">Submit</button>
index f76d8e928f10c56e115b18d77a21a0305d1b5e2f..0fb3949f32e3dd113e6a185ec02204d758ae924e 100644 (file)
@@ -1 +1,2 @@
 <h1>Hello, World!</h1>
+<h3>Welcome, <?php echo $name ?>!</h1>
diff --git a/www/views/layouts/auth.php b/www/views/layouts/auth.php
new file mode 100644 (file)
index 0000000..9a0db66
--- /dev/null
@@ -0,0 +1,19 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8" />
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
+
+    <title>Document</title>
+</head>
+
+<body>
+    <div class="container">
+        {{content}}
+    </div>
+
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
+</body>
+
+</html>
index b394359c3d205411ff42e371871726b57072acc9..52b316eaf69516a7090c9bd868836d2b3a6b4e8a 100644 (file)
 <body>
     <nav class="navbar navbar-expand-lg navbar-light bg-light">
         <div class="container-fluid">
-            <a class="navbar-brand" href="#">Navbar</a>
+            <a class="navbar-brand" href="/">Navbar</a>
             <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                 <span class="navbar-toggler-icon"></span>
             </button>
-            <div class="collapse navbar-collapse" id="navbarNav">
+            <div class="collapse navbar-collapse" id="navbarNav" style="display: flex;">
                 <ul class="navbar-nav">
                     <li class="nav-item">
-                        <a class="nav-link active" aria-current="page" href="#">Home</a>
-                    </li>
-                    <li class="nav-item">
-                        <a class="nav-link" href="#">Features</a>
+                        <a class="nav-link" href="/contact">Contact</a>
                     </li>
+                </ul>
+
+                <ul class="navbar-nav" style="margin-right: 0px; margin-left: auto;">
                     <li class="nav-item">
-                        <a class="nav-link" href="#">Pricing</a>
+                        <a class="nav-link" href="/login">Login</a>
                     </li>
                     <li class="nav-item">
-                        <a class="nav-link disabled">Disabled</a>
+                        <a class="nav-link" href="/register">Register</a>
                     </li>
                 </ul>
             </div>
diff --git a/www/views/login.php b/www/views/login.php
new file mode 100644 (file)
index 0000000..5d48ec6
--- /dev/null
@@ -0,0 +1,20 @@
+<h1>Login page</h1>
+
+<div class="container">
+<form action="" method="post">
+  <div class="mb-3">
+    <label for="exampleInputEmail1" class="form-label">Email address</label>
+    <input name="email" type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
+    <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
+  </div>
+  <div class="mb-3">
+    <label for="exampleInputPassword1" class="form-label">Password</label>
+    <input name="pass" type="password" class="form-control" id="exampleInputPassword1">
+  </div>
+  <div class="mb-3 form-check">
+    <input name="check" type="checkbox" class="form-check-input" id="exampleCheck1">
+    <label class="form-check-label" for="exampleCheck1">Check me out</label>
+  </div>
+  <button type="submit" class="btn btn-primary">Submit</button>
+</form>
+</div>
diff --git a/www/views/register.php b/www/views/register.php
new file mode 100644 (file)
index 0000000..70dd009
--- /dev/null
@@ -0,0 +1,33 @@
+<h1>Registration page</h1>
+
+<div class="container">
+    <form method="POST" class="row g-3">
+        <div class="col-md-4">
+            <label class="form-label">Firstname</label>
+            <input name="name" type="text" class="form-control">
+        </div>
+        <div class="col-md-4">
+            <label class="form-label">Lastname</label>
+            <input name="lastname" type="text" class="form-control">
+        </div>
+        <div class="col-md-4">
+            <label class="form-label">Email</label>
+            <input name="email" type="email" class="form-control">
+        </div>
+        <div class="col-md-12">
+            <label class="form-label">Username</label>
+            <input name="username" type="text" class="form-control">
+        </div>
+        <div class="col-md-6">
+            <label class="form-label">Password</label>
+            <input name="pass" type="password" class="form-control">
+        </div>
+        <div class="col-md-6">
+            <label class="form-label">Password confirm</label>
+            <input name="passConf" name="pass" type="password" class="form-control">
+        </div>
+        <div class="col-12">
+            <button type="submit" class="btn btn-primary">Sign in</button>
+        </div>
+    </form>
+</div>