Создание PHP MVC приложения. Редактирование данных через модальное окно

Главная » Видеоуроки » PHP+MySQL » Создание PHP MVC приложения. Редактирование данных через модальное окно
Один из слушателей оставил комментарий с просьбой реализовать редактирование данных через модальное окно. В этом уроке я сделаю редактирование новостей в приложении через готовые angular директивы для bootstrap.
Для реализации модального bootstrap окна нужно подключить зависимость ui.bootstrap. После этого будет доступен сервис $uibModal, у которого есть один единственный метод open(), в который передается объект с различными параметрами. Внутри самого модального окна управление идет с помощью $uibModalInstance. Подробно рекомендую почитать документацию.

Код урока (news.tpl.php)

<!DOCTYPE html>
<html lang="ru" data-ng-app="news">
<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>
                        <li>
                            <a href="/cabinet/news"><i class="fa fa-newspaper-o"></i> Новости</a>
                        </li>
                    </ul>
                </div>
                <!-- /.sidebar-collapse -->
            </div>
            <!-- /.navbar-static-side -->
        </nav>

        <div id="page-wrapper" data-ng-controller="newsController">
            <div class="row">
                <div class="col-lg-12">
                    <h1 class="page-header"><?php echo $pageData['title']; ?></h1>
                </div>
                <!-- /.col-lg-12 -->
            </div>
            <!-- /.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">
                                    <?php foreach($pageData['news'] as $news) { ?>
                                    <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
                                        <div class="panel panel-default">
                                            <div class="panel-heading" role="tab" id="headingOne">
                                                <h4 class="panel-title">
                                                    <a data-ng-click="open(<?php echo $news['id']; ?>)" role="button" aria-expanded="true" aria-controls="collapseOne">
                                                    <?php echo $news['title']; ?>
                                                    </a>
                                                </h4>
                                            </div>
                                            <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
                                                <div class="panel-body">
                                                <?php echo $news['description']; ?>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <?php } ?>
                                </div>
                                <!-- /.col-lg-4 (nested) -->
                                <!-- /.col-lg-8 (nested) -->
                            </div>
                            <!-- /.row -->
                        </div>
                        <!-- /.panel-body -->
                    </div>
                    <!-- /.panel -->
                    <!-- /.panel -->
                </div>
                <!-- /.col-lg-8 -->
            </div>
            <!-- /.row -->
        </div>
        <!-- /#page-wrapper -->

    </div>
    <!-- /#wrapper -->

    <!-- jQuery -->
    <script src="/js/jquery.js"></script>

    <!-- Angular -->
    <script src="/js/angular.min.js"></script>
    <script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.min.js"></script>
    <script src="/js/admin/news.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>

Код урока (modal.tpl.php)

<div class="modal-content">
    <div class="modal-header">
        <h4 class="modal-title">Редактирование новости</h4>
    </div>
    <div class="modal-body">
        <form>
        <input type="hidden" data-ng-model="newsId" name="newsId">
            <div class="form-group">
                <input type="text" data-ng-model="newsTitle" name="newsTitle" class="form-control">
            </div>
            <div class="form-group">
                <textarea data-ng-model="newsDescription" name="newsDescription" class="form-control"></textarea>
            </div>
        </form>
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal" data-ng-click="close();">Закрыть</button>
        <button type="button" class="btn btn-primary" data-ng-click="save()">Сохранить</button>
    </div>
</div>

Код урока (news.js)

var news = angular.module('news', ['ui.bootstrap']);

news.controller('newsController', function($scope, $http, $uibModal) {

	$scope.open = function(id) {
		
		$http({
			method: "POST",
			url: "http://cabinet.kamil-abzalov.ru/cabinet/news/getNewsById",
			data: $.param({id: id}),
			headers: {"Content-Type": 'application/x-www-form-urlencoded'}
		}).then(function(result){
			console.log(result);
			if(result.data.success != false) {
				$scope.newsData = result.data;

				var modalWindow = $uibModal.open({
					animation: true,
					controller: "modalWindowController",
					templateUrl: '/views/modal.tpl.php',
					resolve: {
						newsData: function(){
							return $scope.newsData;
						}
					}
				})
			}
		});

	}

});

news.controller('modalWindowController', function($scope, $http, $window, $uibModalInstance, newsData) {

	$scope.newsId = newsData.id;
	$scope.newsTitle = newsData.title;
	$scope.newsDescription = newsData.description;

	$scope.save = function() {

	}

	$scope.close = function() {
		$uibModalInstance.dismiss('cancel');
	}


	$scope.save = function() {
		$http({
			method: "POST",
			url: "http://cabinet.kamil-abzalov.ru/cabinet/news/save",
			data: $.param({id: $scope.newsId, title: $scope.newsTitle, text: $scope.newsDescription}),
			headers: {"Content-Type": 'application/x-www-form-urlencoded'}
		}).then(function(result){
			alert(result.data.text);
			$uibModalInstance.close();
			$window.location.href = 'cabinet/news';
		})
	}

})

Код урока (NewsController.php)

<?php

class NewsController extends Controller {

	private $pageTpl = '/views/news.tpl.php';

	public function __construct() {
		$this->model = new NewsModel();
		$this->view = new View();
	}

	public function index() {
		if(!$_SESSION['user']) {
			header("Location: /");
		}

		$this->pageData['title'] = "Новости";

		$news = $this->model->getNews();
		$this->pageData['news'] = $news;

		$this->view->render($this->pageTpl, $this->pageData);
	}

	public function getNewsById() {
		if(!$_SESSION['user']) {
			header("Location: /");
		}

		if(isset($_POST['id'])) {
			$newsId = $_POST['id'];
			if($newsInfo = $this->model->getNewsById($newsId)) {
				echo json_encode($newsInfo);
			} else {
				echo json_encode(array("success" => false, "text" => "Новость не найдена"));
			}
		} else {
			echo json_encode(array("success" => false, "text" => "Ошибка"));
		}
	}

	public function save() {
		if(!$_SESSION['user']) {
			header("Location: /");
		}

		if(!empty($_POST) && !empty($_POST['title']) && !empty($_POST['text'])) {
			$newsId = $_POST['id'];
			$newsTitle = $_POST['title'];
			$newsText = $_POST['text'];
			$this->model->saveNews($newsId, $newsTitle, $newsText);
			echo json_encode(array("success" => true, "text" => "Новость сохранена"));
		} else {
			echo json_encode(array("success" => false, "text" => "Ошибка"));
		}
	}

}

Код урока (NewsModel.php)

<?php

class NewsModel extends Model {

	public function getNews() {
		$sql = "SELECT * FROM news";
		$stmt = $this->db->prepare($sql);
		$stmt->execute();

		$result = array();
		while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
			$result[$row['id']] = $row;
		}

		return $result;
	}

	public function getNewsById($id) {
		$sql = "SELECT * FROM news WHERE id= :id";
		$stmt = $this->db->prepare($sql);
		$stmt->bindValue(":id", $id, PDO::PARAM_INT);
		$stmt->execute();

		$result = array();

		$result = $stmt->fetch(PDO::FETCH_ASSOC);
		if(empty($result)) {
			return false;
		} else {
			return $result;
		}
	}

	public function saveNews($id, $title, $text) {
		$sql = "UPDATE news
				SET title = :title, description = :text
				WHERE id =:id
				";
		$stmt = $this->db->prepare($sql);
		$stmt->bindValue(":title", $title, PDO::PARAM_STR);
		$stmt->bindValue(":text", $text, PDO::PARAM_STR);
		$stmt->bindValue(":id", $id, PDO::PARAM_INT);
		$stmt->execute();

	}

}

2 комментария

  1. Евгений

    Камиль, доброго времени суток! Спасибо за Вашу работу, много нужного нашел для себя. Есть вопрос по этому уроку: как реализовать выбор данных из связанных select в модальном окне (вроде бы это называется динамический select)? К примеру, в базе есть таблица городов и таблица с улицами этих городов, в записи улицы есть поле с id города. Как реализовать в одном select выбор города и связанной с ним улицы во втором select, все это в модальном окне с возможностью редактирования и сохранения данных в базе? Как можно это реализовать через тот же angular? Если можно, приведите пример, хотя бы с одним select, к примеру, выбор только города. Заранее благодарю, Евгений.

    Ответить
    • Камиль

      Здравствуйте, Евгений. Спасибо за отзыв. Если мне не изменяет память, то в одном из уроков данной серии я реализовывал динамический select при создании директивы angularjs. Посмотрите — это то, что вас интересует? Если нет, оставьте свое пожелание на странице — http://kamil-abzalov.ru/useful-resources/write-your-wish/

      Ответить

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *


Срок проверки reCAPTCHA истек. Перезагрузите страницу.

Pin It on Pinterest

Share This