Создание php MVC приложения. Использование angular
В этом уроке мы будем использовать angularjs. Нашей задачей буде реализовать чтение информации о товарах из базы данных.
Отмечу, что в этой задаче нам понадобится angular-route. Удостоверьтесь, что используете одинаковые версии angular и angular-route. Если забыли, то можете посмотреть уроки по основам angular у меня в соответствующем разделе.
Роутинг (route.php)
<?php
/*
** Класс маршрутизации
** Урл http://cabinet.kamil-abzalov.ru/
** Урл http://cabinet.kamil-abzalov.ru/cabinet
** Урл http://cabinet.kamil-abzalov.ru/cabinet/users
** Урл http://cabinet.kamil-abzalov.ru/cabinet/orders/
** Урл http://cabinet.kamil-abzalov.ru/cabinet/orders?orderId=
*/
class Routing {
public static function buildRoute() {
/*Контроллер и action по умолчанию*/
$controllerName = "IndexController";
$modelName = "IndexModel";
$action = "index";
$route = explode("/", parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
$i = count($route)-1;
while($i>0) {
if($route[$i] != '') {
if(is_file(CONTROLLER_PATH. ucfirst($route[$i]). "Controller.php")) {
$controllerName = ucfirst($route[$i]). "Controller";
$modelName = ucfirst($route[$i]). "Model";
break;
} else {
$action = $route[$i];
}
}
$i--;
}
require_once CONTROLLER_PATH . $controllerName . ".php"; //IndexController.php
require_once MODEL_PATH . $modelName . ".php"; //IndexModel.php
$controller = new $controllerName();
$controller->$action(); // $controller->index();
}
public function errorPage() {
}
}
ProductsController
<?php
class ProductsController extends Controller {
private $pageTpl = "/views/products.tpl.php";
public function __construct() {
$this->model = new ProductsModel();
$this->view = new View();
}
public function index() {
if(!$_SESSION['user']) {
header("Location: /");
}
$this->pageData['products'] = $this->model->getAllProducts();
$this->pageData['title'] = "Товары";
$this->view->render($this->pageTpl, $this->pageData);
// При загрузки файлов надо обращать внимание на размер файла и время исполнения скрипта
if($_FILES) {
if($_FILES['csv']['type'] != 'application/octet-stream' || $_FILES['csv']['type'] == '') {
echo 0;
$this->pageData['errors'] = "Ошибка! Возможно, данный файл имеет некорректный формат";
} else {
if(move_uploaded_file($_FILES['csv']['tmp_name'], UPLOAD_DIR. $_FILES['csv']['name'])) {
$file = fopen(UPLOAD_DIR. $_FILES['csv']['name'], "r");
$row = 1;
while($data = fgetcsv($file, 200, ";")){
if($row == 1) {
$row++;
continue;
} else {
$this->model->addFromCSV($data);
}
}
fclose($file);
$this->model->getAllProducts();
}
}
}
}
public function getProduct() {
if(!$_SESSION['user']) {
header("Location: /");
return;
}
if(!isset($_GET['id'])) {
echo json_encode(array("success" => false));
} else {
$productId = $_GET['id'];
$produtInfo = json_encode($this->model->getProductById($productId));
echo $produtInfo;
}
}
}
app.js
var app = angular.module("products", ["ngRoute"]);
app.config(function($routeProvider, $locationProvider){
$routeProvider
.when("/:id", {
templateUrl: "/views/product.tpl.php"
});
$locationProvider.html5Mode(true);
});
app.controller('productsController', function($scope, $http){
$scope.getInfoByProductId = function(id) {
$http({
method: "GET",
url: "http://cabinet.kamil-abzalov.ru/cabinet/products/getProduct",
params: {id: id}
}).then(function(result){
$scope.productId = result.data.id;
$scope.productName = result.data.name;
$scope.productPrice = result.data.price;
})
}
$scope.saveProduct = function() {
// TODO: Дома - попробовать реализовать сохранение и удаление
}
});
products.tpl.php
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<base href="/cabinet/products/">
<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="#"><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-app="products" data-ng-controller="productsController">
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">Товары</h1>
</div>
<!-- /.col-lg-12 -->
<div class="col-lg-12" data-ng-view></div>
</div>
<!-- /.row -->
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<!-- /.panel -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bar-chart-o fa-fw"></i> Товары
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>ID товара</th>
<th>Наимнование товара</th>
<th>Цена</th>
</tr>
</thead>
<tbody>
<?php
foreach ($pageData['products'] as $key => $value) { ?>
<tr>
<td><?php echo $value['id']; ?></td>
<td><a data-ng-click="getInfoByProductId(<?php echo $value['id']; ?>)" href="<?php echo $value['id']; ?>"><?php echo $value['name']; ?></a></td>
<td><?php echo $value['price']; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<!-- /.table-responsive -->
</div>
<!-- /.col-lg-4 (nested) -->
<!-- /.col-lg-8 (nested) -->
</div>
<!-- /.row -->
</div>
<!-- /.panel-body -->
</div>
<!-- /.panel -->
<!-- /.panel -->
</div>
<!-- /.col-lg-8 -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<h2>Загрузить CSV файл с товарами</h2>
<form method="post" class="form-horizontal" enctype="multipart/form-data">
<label for="file">Загрузите CSV файл</label>
<input id="file" type="file" name="csv">
<button class="btn btn-default">Загрузить</button>
</form>
</div>
</div>
</div>
<!-- /#page-wrapper -->
</div>
<!-- /#wrapper -->
<!-- jQuery -->
<script src="/js/jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="/js/bootstrap.min.js"></script>
<!-- Angular framework -->
<script src="/js/angular.min.js"></script>
<script src="/js/angular-route.js"></script>
<script src="/js/admin/app.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>
product.tpl.php
<form class="form-horizontal" name="productInfo" data-ng-submit="saveProduct()">
<input type="hidden" id="productId" data-ng-model="productId">
<legend>Редактирование товара</legend>
<div class="form-group">
<label for="productName" class="col-sm-3">Наименование товара</label>
<div class="col-sm-9">
<input type="text" data-ng-model="productName" id="productName" class="form-control">
</div>
</div>
<div class="form-group">
<label for="productPrice" class="col-sm-3">Стоимость товара</label>
<div class="col-sm-9">
<input type="text" data-ng-model="productPrice" id="productPrice" class="form-control">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<button class="btn btn-default">Сохранить</button>
<button class="btn btn-danger">Удалить</button>
</div>
</div>
</form>
0 Комментариев