Создание PHP MVC приложения. Одобрение и удаление заказа
В сегодняшнем уроке мы поработаем со страницей заказа — напишем функции удаления и одобрения заказа. Функция одобрения заказа будет отправлять email письмо владельцу заказа.
Код урока (orders.tpl.php)
<!DOCTYPE html>
<html lang="ru" data-ng-app="order">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo $pageData['title']; ?></title>
<!-- Bootstrap Core CSS -->
<link href="/css/bootstrap.min.css" rel="stylesheet">
<!-- MetisMenu CSS -->
<link href="/css/admin/metisMenu.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="/css/admin/sb-admin-2.css" rel="stylesheet">
<!-- Morris Charts CSS -->
<link href="/css/admin/morris.css" rel="stylesheet">
<!-- Custom Fonts -->
<link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div id="wrapper">
<!-- Navigation -->
<nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">Кабинет</a>
</div>
<!-- /.navbar-header -->
<ul class="nav navbar-top-links navbar-right">
<!-- /.dropdown -->
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-user fa-fw"></i> <i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="/cabinet/profile"><i class="fa fa-user fa-fw"></i> Профиль</a>
</li>
<li class="divider"></li>
<li><a href="/cabinet/logout"><i class="fa fa-sign-out fa-fw"></i> Выйти</a>
</li>
</ul>
<!-- /.dropdown-user -->
</li>
<!-- /.dropdown -->
</ul>
<!-- /.navbar-top-links -->
<div class="navbar-default sidebar" role="navigation">
<div class="sidebar-nav navbar-collapse">
<ul class="nav" id="side-menu">
<li>
<a href="/cabinet"><i class="fa fa-area-chart"></i> Статистика</a>
</li>
<li>
<a href="/cabinet/products"><i class="fa fa-cart-plus"></i> Товары</a>
</li>
<li>
<a href="/cabinet/users"><i class="fa fa-user-o"></i> Пользователи</a>
</li>
</ul>
</div>
<!-- /.sidebar-collapse -->
</div>
<!-- /.navbar-static-side -->
</nav>
<div id="page-wrapper" data-ng-controller="orderController">
<?php if(isset($_GET['orderId']) && $_GET['orderId'] != '' && !empty($pageData['orderInfo'])) { ?>
<div class="row">
<div class="col-md-12">
<h2><?php echo $pageData['title']; ?></h2>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Состав заказа</h3>
<table class="table table-bordered">
<tr>
<th>Товар</th>
<th>Цена (руб.)</th>
</tr>
<?php foreach($pageData['orderInfo'] as $val) { ?>
<tr>
<td><?php echo $val['name']; ?></td>
<td><?php echo $val['price']; ?></td>
</tr>
<?php } ?>
<tr>
<td><strong>Итого:</strong></td>
<td><?php echo $pageData['orderInfo'][0]['amount']; ?></td>
</tr>
</table>
<h3>Покупатель:</h3>
<p class="lead">ФИО: <strong><?php echo $pageData['orderInfo'][0]['fullName']; ?></strong></p>
<p class="lead">Email: <strong><?php echo $pageData['orderInfo'][0]['email']; ?></strong></p>
<button class="btn btn-success" data-ng-click="checkOrder(<?php echo $_GET['orderId']; ?>)">Одобрить</button>
<button class="btn btn-danger" data-ng-click="deleteOrder(<?php echo $_GET['orderId']; ?>)">Удалить</button>
</div>
</div>
<?php } else { ?>
<div class="row">
<div class="col-md-12">
<h2>Заказ не найден</h2>
</div>
</div>
<?php } ?>
</div>
<!-- /#page-wrapper -->
</div>
<!-- /#wrapper -->
<!-- jQuery -->
<script src="/js/jquery.js"></script>
<!-- Angular -->
<script src="/js/angular.min.js"></script>
<script src="/js/admin/order.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="/js/bootstrap.min.js"></script>
<!-- Metis Menu Plugin JavaScript -->
<script src="/js/admin/metisMenu.js"></script>
<!-- Custom Theme JavaScript -->
<script src="/js/admin/sb-admin-2.js"></script>
</body>
</html>
Код урока (orders.js)
var order = angular.module("order", []);
order.controller("orderController", function($scope, $http, $window){
$scope.checkOrder = function(id) {
$http({
method: "POST",
url: "http://cabinet.codetogether.ru/cabinet/orders/checkOrder",
data: $.param({id: id}),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(function(result){
alert(result.data.text);
$window.location.href = '/cabinet';
})
}
$scope.deleteOrder = function(id) {
$http({
method: "POST",
url: "http://cabinet.codetogether.ru/cabinet/orders/deleteOrder",
data: $.param({id: id}),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(function(result){
alert(result.data.text);
$window.location.href = '/cabinet';
})
}
});
Код урока (checkOrder.tpl.html)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Новая учетная запись</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div style="width:640px; margin: 0 auto; font-family: Arial, sans-serif; font-size: 14px;">
<h1>Уважаемый %fullName%! Ваш заказ на сумму %amount% одобрен</h1>
<p>Состав заказа:</p>
</div>
</body>
</html>
Код урока (OrdersController.php)
<?php
class OrdersController extends Controller {
private $pageTpl = "/views/order.tpl.php";
private $mailTpl = "/views/mail/checkOrder.tpl.html";
public function __construct() {
$this->model = new OrdersModel();
$this->view = new View();
}
public function sendCheckOrderMail($fullName, $email, $amount, $products, $prices) {
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=UTF-8' . "\r\n";
$emailText = file_get_contents(ROOT . $this->mailTpl);
$emailText = str_replace('%fullName%', $fullName, $emailText);
$emailText = str_replace('%amount%', $amount, $emailText);
$emailText .= "<ul style='margin:0; padding:0'>";
for($i=0; $i<count($products); $i++) {
$emailText .= "<li>" . $products[$i] . " - " . $prices[$i] . "</li>";
}
$emailText .= "</ul>";
mail($email, "Ваш заказ одобрен", $emailText, $headers);
}
public function index() {
if(!$_SESSION['user']) {
header("Location: /");
}
$this->pageData['title'] = "Детали заказа";
if(isset($_GET['orderId'])) {
$orderId = intval($_GET['orderId']);
if($orderId > 0) {
$this->pageData['orderInfo'] = $this->model->getOrderInfoByOrderId($orderId);
}
}
$this->view->render($this->pageTpl, $this->pageData);
}
public function checkOrder() {
if(isset($_POST['id'])) {
$orderId = $_POST['id'];
$orderInfo = $this->model->getOrderInfoByOrderId($orderId);
$fullName = $orderInfo[0]['fullName'];
$email = $orderInfo[0]['email'];
$amount = $orderInfo[0]['amount'];
$productsArr = array();
$productsPricesArr = array();
foreach($orderInfo as $item) {
array_unshift($productsArr, $item['name']);
array_unshift($productsPricesArr, $item['price']);
}
$this->sendCheckOrderMail($fullName, $email, $amount, $productsArr, $productsPricesArr);
echo json_encode(array("success" => true, "text" => "Заказ одобрен"));
} else {
echo json_encode(array("success" => true, "text" => "Ошибка"));
}
}
public function deleteOrder() {
if(isset($_POST['id'])) {
$orderId = $_POST['id'];
$this->model->deleteOrder($orderId);
echo json_encode(array("success" => true, "text" => "Заказ удален"));
} else {
echo json_encode(array("success" => true, "text" => "Не удалось удалить заказ"));
}
}
}
?>
Код урока (OrdersModel.php)
<?php
class OrdersModel extends Model {
public function getOrderInfoByOrderId($orderId) {
$result = array();
$sql = "SELECT users.fullName, users.email, orders.amount, products.name, products.price FROM users
INNER JOIN orders ON orders.user_id = users.id
INNER JOIN productsInOrders ON orders.id = productsInOrders.order_id
INNER JOIN products ON productsInOrders.product_id = products.id
WHERE orders.id = :orderId";
$stmt = $this->db->prepare($sql);
$stmt->bindValue(":orderId", $orderId, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchAll();
return $result;
}
public function deleteOrder($orderId) {
$sql = "DELETE FROM productsInOrders WHERE order_id = :orderId;
DELETE FROM orders WHERE id = :id
";
$stmt = $this->db->prepare($sql);
$stmt->bindValue(":orderId", $orderId, PDO::PARAM_INT);
$stmt->bindValue(":id", $orderId, PDO::PARAM_INT);
$stmt->execute();
}
}
Добрый день! Спасибо за Вашу работу, уроки очень полезны и познавательны. А как реализовать работу по добавлению/изменению/удалению данных из таблиц, ну, скажем, тех же пользователей, в модальных окнах? Может стоит сделать пример? Заранее благодарю.
Здравствуйте, Евгений. Спасибо большое.
Реализовать можно через ajax метод (jquery), либо через готовые директивы для bootstrap UI. Примером подкреплю обязательно.