Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
Introduction to Web Development
Frameworks
Problems with Web Dev.
• PHP started as a scripting language
• Very simple to start with
• Very easy to generate HTML
• Very easy to interface with DB
• Great for simple apps
Problems with Web Dev.
• During the years, user needs grew
• not only simple/dynamic web pages, but rather fully fledged apps
• PHP was not designed with the goal to support large applications
• Leads to unmaintainable, insecure code
Usual PHP code <?php // index.php $connection = new PDO("mysql:host=localhost;dbname=blog_db", 'myuser', 'mypassword');
$result = $connection->query('SELECT id, title FROM post'); ?>
<!DOCTYPE html> <html> <head> <title>List of Posts</title> </head> <body> <h1>List of Posts</h1> <ul> <?php while ($row = $result->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="/show.php?id=<?= $row['id'] ?>"> <?= $row['title'] ?> </a> </li> <?php endwhile ?> </ul> </body> </html>
<?php $connection = null; ?>
Problems with the above• Difficult to reuse code
• Multiple representations not easily possible, i.e. JSON and HTML
• Database access logic is intertwined with the display logic - hard to change one without affecting the other
• Hard to switch to another database (i.e. different databases in different environments)
• Highly coupled code
The need for structure• Separation of Concerns
• IP Stack
• HTML/CSS
• Why not PHP?
• Single Responsibility Principle
• A class or module should have one, and only one, reason to be changed.
Usual PHP Code
• Almost every web application has at least the following components:
• database access
• request processing
• data display (views)
MVC (Model - View - Controller)
• A pattern for separating concerns in web applications
• Model - Business logic layer
• View - Presentation layer - could be HTML, JSON, XML, CSV
• Controller - handles requests, invokes model and passes data to view
MVC
• One model - many views - many controllers
MVC in Action: Simple Blog in Flat PHP
<?php // index.php $connection = new PDO("mysql:host=localhost;dbname=blog_db", 'myuser', 'mypassword');
$result = $connection->query('SELECT id, title FROM post'); ?>
<!DOCTYPE html> <html> <head> <title>List of Posts</title> </head> <body> <h1>List of Posts</h1> <ul> <?php while ($row = $result->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="/show.php?id=<?= $row['id'] ?>"> <?= $row['title'] ?> </a> </li> <?php endwhile ?> </ul> </body> </html>
<?php $connection = null; ?>
MVC in Action: Isolating the Presentation
// index.php $connection = new PDO("mysql:host=localhost;dbname=blog_db", 'myuser', 'mypassword');
$result = $connection->query('SELECT id, title FROM post');
$posts = []; while ($row = $result->fetch(PDO::FETCH_ASSOC)) { $posts[] = $row; }
$connection = null;
// include the HTML presentation code require 'templates/list.php';
MVC in Action: Isolating the Presentation
<!-- templates/list.php --> <!DOCTYPE html> <html> <head> <title>List of Posts</title> </head> <body> <h1>List of Posts</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="/show.php?id=<?= $post['id'] ?>"> <?= $post['title'] ?> </a> </li> <?php endforeach ?> </ul> </body> </html>
MVC in Action: Isolating Application Logic
• What if the second page needs to use the same database connection?
• What if the second page needs to use the same posts array?
MVC in Action: Isolating Application Logic
// model.php function open_database_connection() { $connection = new PDO("mysql:host=localhost;dbname=blog_db", 'myuser', 'mypassword');
return $connection; }
function close_database_connection(&$connection) { $connection = null; }
function get_all_posts() { $connection = open_database_connection();
$result = $connection->query('SELECT id, title FROM post');
$posts = []; while ($row = $result->fetch(PDO::FETCH_ASSOC)) { $posts[] = $row; } close_database_connection($connection);
return $posts; }
MVC in Action: Isolating Application Logic
// index.php require_once 'model.php';
$posts = get_all_posts();
require 'templates/list.php';
MVC in Action
• The application has been refactored into three distinct pieces so that each one can be reused independently.
• However, once piece that can’t be reused is the layout, i.e. we need to copy & paste the same header/footer on each page.
MVC in Action: Isolating the layout
<!-- templates/layout.php --> <!DOCTYPE html> <html> <head> <title><?= $title ?></title> </head> <body> <?= $content ?> </body> </html>
MVC in Action: Isolating the Layout
<!-- templates/list.php --> <?php $title = 'List of Posts' ?>
<?php ob_start() ?> <h1>List of Posts</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="/show.php?id=<?= $post['id'] ?>"> <?= $post['title'] ?> </a> </li> <?php endforeach ?> </ul> <?php $content = ob_get_clean() ?>
<?php include 'layout.php' ?>
MVC in Action: Adding a blog show page
// model.php function get_post_by_id($id) { $connection = open_database_connection();
$query = 'SELECT created_at, title, body FROM post WHERE id=:id'; $statement = $connection->prepare($query); $statement->bindValue(':id', $id, PDO::PARAM_INT); $statement->execute();
$row = $statement->fetch(PDO::FETCH_ASSOC);
close_database_connection($connection);
return $row; }
MVC in Action: Adding a blog show page
// show.php require_once 'model.php';
$post = get_post_by_id($_GET['id']);
require 'templates/show.php';
MVC in Action: Adding a blog show page
<!-- templates/show.php --> <?php $title = $post['title'] ?>
<?php ob_start() ?> <h1><?= $post['title'] ?></h1>
<div class="date"><?= $post['created_at'] ?></div> <div class="body"> <?= $post['body'] ?> </div> <?php $content = ob_get_clean() ?>
<?php include 'layout.php' ?>
MVC in Action: Observations
• Creating a second page requires very little work and no code duplication
• Has some problems, such as a missing id param which would cause your application to crash - a 404 page would be nice
• Each controller must include a model.php file. What if we need to include another one to perform some security checks?
A “Front Controller” to the Rescue
• A single PHP file through which all requests are processed.
• The URIs change slightly, but start to become more flexible
• Allows you to centralize security handling, configuration loading, routing, etc.
• Without a front controller:
• /index.php - Blog list page
• /show.php - Blog show page
• With a front controller:
• /index.php - Blog list page
• /index.php/show - Blog show page
Creating a Front Controller
// index.php
// load and initialize any global libraries require_once 'model.php'; require_once 'controllers.php';
// route the request internally $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if ('/index.php' === $uri) { list_action(); } elseif ('/index.php/show' === $uri && isset($_GET['id'])) { show_action($_GET['id']); } else { header('HTTP/1.1 404 Not Found'); echo '<html><body><h1>Page Not Found</h1></body></html>'; }
controllers.php// controllers.php function list_action() { $posts = get_all_posts(); require 'templates/list.php'; }
function show_action($id) { $post = get_post_by_id($id); require 'templates/show.php'; }
MVC
Frameworks
• an essential supporting structure of a building, vehicle, or object.
Frameworks• Usually frameworks help us with the above, in
providing structural support as well as support form other components
• The whole idea is to minimize repetitive work, and delegate as many as possible responsibilities to the framework
• Because they provide the above advantages, frameworks require you to stick to some rules and conventions
Frameworks
• Several frameworks have sprung during the recent years
• Almost every language has a Web/MVC framework
• It is usually very easy to transition to another framework once you have a good grasp of the concepts involved.
Frameworks• PHP - CodeIgniter, Laravel, Symfony
• .NET - ASP MVC, ServiceStack
• Java - SpringBoot, Struts
• Python - Django, Flask
• Ruby - Rails, Sinatra
Typical Framework Components
• Routing
• Middleware
• Request / Response Model (no $_GET)
• Controllers
• Views
• Templating Engine (Blade)
• Models
• Direct DB Query
• ORM (Object Relational Mapper)
• Asset pipeline
• Multiple Environments
• Logging
• Security (CSRF, XSS)
Routing
• Gives you the ability to have RESTful URLs
• Maps routes to your Controller classes
• Allows for fine-grained route control, i.e. namespaces, etc.
Middleware
• Objects that pre-process or post-process requests before they arrive at your controllers
• Helpful for implementing security mechanisms such as authorization
Request / Response Model
• Gives you a clear, object-oriented, and easy to use interface for Request and Response objects
• No need for $_GET, $_POST, header(), etc.
Controllers
• Objects you can map to your routes and have the framework invoke them whenever a URL is matched
• Match specific actions to specific HTTP verbs
Views
• Usually frameworks provide a templating engine that helps you write cleaner view code, i.e. no <?php garbage. This is if you decide to have HTML representations.
• As for JSON or other content types, usually frameworks provide you with serializers or similar.
Views: Templating Engines
Models• Either direct db query
• DB.select(‘select * from something’)
• or ORM
• Post::all();
• $user = new User; $user->save();
Asset pipeline• Asset processing
• Image optimization
• JS minification, bundling
• SASS to CSS conversion
• etc…
Multiple environments• Usually frameworks give you the ability to have different
configurations for different environments
• For example:
• detailed logging in development but not in production
• asset minification in production but not in development
• different databases connection details for different environments
Logging
• Different levels of logging are usually supported
• Debug, Information, Warning, Critical
• Different levels of details depending on logging level such as request params, time spent, queries executed, and whatever you decide to log along the way
Security
• Out-of-the box protection for common attacks such as CSRF, XSS, SQL Injection
• Ready-made authentication mechanisms supporting username/password, tokens, etc.
• Authorization framework
Digging deeper• WebSockets and more…
• Caching
• File Storage
• Disk, or external services
• Mailers
• Queues
• Task Scheduling