PHP + AngularJS: Первый сайт не комом. Часть 2.2 Админ часть добавление в базу данных

Для того чтобы научиться программировать нужно пробовать программировать самые простые, но функциональные вещи. Чтобы лучше понять как сделать «свой первый самый лучший в мире» сайт — рассмотрим пример элементарного сайта из одного уровня объектов — страниц. Нам нужно

Готовый код, по которому будет идти рассказ что где и почему. Пример простейшего сайта с админкой в связке PHP + AngularJS, первая часть описания

Форма добавления со стороны браузера

На списке страниц поставим кнопку

<a href="#/pages/add" class="btn btn-default">Добавить страницу</a>

Привяжем действие в роутере

		when('/pages/add', {
			templateUrl: 'blocks/page/page-add.html',
			controller:  'adminPageAddCtrl'
		})

Создадим контроллер

adminControllers.controller('adminPageAddCtrl', function ($scope, $http) {
	$scope.new = {};
	$scope.saveNew = function() {
		$http.post('api/pages/add.json', $scope.new).success(function (data) {
			if (data == 1) {
				window.location.hash = 'pages';
			}
		});
	}
});

И собственно сама форма

<div class="page-header">
    <h1>Создание новой страницы <small>для создания новой страницы на сайте</small></h1> <a href="#pages">Назад ко всем страницам</a>
</div>
<div class="container-fluid">
    <form role="form">
        <div class="form-group">
            <label>Название</label>
            <br/>
            <input class="form-control" type="text" ng-model="new.title" value="" placeholder="введите название"/>
        </div>
        <div class="form-group">
            <label>Url</label>
            <br/>
            <input class="form-control" type="text" ng-model="new.url" value="" placeholder="введите url"/>
        </div>
        <div class="form-group">
            <label>Информация</label><br/>
            <textarea class="form-control" ng-model="new.info" placeholder="введите информацию для списка страниц"></textarea>
        </div>
        <div class="form-group">
            <label>Вступление</label><br/>
            <textarea class="form-control" ng-model="new.intro" placeholder="введите вступление (первая часть страницы)"></textarea>
        </div>
        <div class="form-group">
            <label>Продолжение</label><br/>
            <textarea class="form-control" ng-model="new.full" placeholder="введите продолжение (вторая часть страницы)"></textarea>
        </div>
        <button ng-click="saveNew()" type="submit" class="btn btn-default glyphicon glyphicon-plus-sign">Добавить</button>
    </form>
</div>

Форма добавления со стороны базы данных

Собственно главное в этой статье! Если до этого Вы уже по схеме предыдущей знаете куда файлы разбросать, то теперь, наконец-то, мы сделаем интеграцию с пхп и базой данных. Что же скрывается за постом на ссылку api/pages/add.json?

Роутинг ПХП

Для передачи «псевдоурла» мы создаем файл роутер Наша Админка/api/.htaccess

RewriteEngine on
RewriteRule ^.htaccess$ - [F]
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /Наша админка/api/index.php?q=$1 [L,QSA]

И его перехватчик Наша Админка/api/index.php. Обращаю Ваше внимание — подключается файл высоко вверху — это где наши главные пхп файлы лежат, я вообще в паблик, доступный снаружи не люблю код выкладывать классов и тд. Хорошая привычка, если есть возможность — то убирайте вовсе. Подробнее тут

Router::route — маленький простой роутер, первый параметр это запрос, второй неймспейс из которого брать контроллеры, и третий — контроллер по умолчанию. Код роутера я цитировать не буду — он есть в общем архиве, главная идея — по запросу взять что мы хотим выполнить cp\api\Pages->add

<?php
header('Content-Type: text/html; charset=utf-8');
include_once dirname(dirname(__DIR__)) . '/!app/init.php'; //
 
use vegcoders\app_small\Router;
use vegcoders\core\funcs\F;
 
try {
	$result = Router::route(F::get('q'), 'cp\\api\\', 'Pages'); 
	echo json_encode($result);
} catch (Exception $e) {
	vegcoders\core\debug\Error::getUserMessage($e);
}

Контроллер для работы с БД

Так как мы не только страницы потом хотим обрабатывать, то сразу выделим главный контроллер. ООП страшная штука.
!app\cp\api\libs\ ApiController.class.php

<?php
namespace cp\api\libs;
 
use vegcoders\core\db\DB;
 
class ApiController
{
	var $class = 'Menu';
	var $model = false;
        //так как мы ООП программисты - то создадим модель для работы с БД
	public function __construct()
	{
		$classname = 'cp\\api\\libs\\' . $this->class;
		$this->model = new $classname();
	}
	//из переданных данных - нормальные) тоже не только один раз
	public function _getData() {
		return json_decode(file_get_contents('php://input'), true);
	}
	public function add()
	{
		if ($this->model->add($this->_getData())) return 1;
		echo DB::debug(); //это только на случай беды, потом уберем когда все заработает
		return false;
	}
}

Главная задача нашего контроллера страниц теперь — сказать чем он отличается от любого другого контроллера) А что наследует.
!app\cp\api\controllers\PagesController.class.php

<?php
namespace cp\api\controllers;
use cp\api\libs\ApiController;
class PagesController extends ApiController
{
	var $class = 'Page';
}

Модель для работы с БД

Для всех таблиц очень похожая логика, только разные поля, поэтому мы опять поиграем в ООП на похожих моделях. Применяемый тут класс DB также есть в полных исходниках, а о логике его создания можно прочитать в описании его очень ранней версии. Почему я против PDO я попробую описать отдельно, но примите как факт — если Вы используете чужую магию вместо прямых и красивых sql, то теряете не только производительность и стабильность, а еще и рискуете налететь на мегабаги PDO при масштабировании базы.

<?php
namespace cp\api\libs;
 
use vegcoders\core\db\DB;
use vegcoders\core\funcs\F;
 
class BasicOne
{
	public $_fields_required    = array();
	public $_fields_add         = array();
 
	private function _prepSave(&$save, $value)
	{
		foreach($this->_fields_required AS $field => $type) {
			$save[$field] = F::get($field, $type, '', $value);
			if (!$save[$field]) {
				return false;
			}
		}
		foreach($this->_fields_add AS $field => $type) {
			$save[$field] = F::get($field, $type, '', $value);
		}
	}
	public function add($value)
	{
		if (!is_array($value)) {
			return false;
		}
		$save = array('crtime' => 'NOW()');
		$this->_prepSave($save, $value);
		return DB::insert($this->_db_table, $save) ? 1 : 0;
	}
}

И опять у нас очень маленький класс-наследник, только с настройками
!app\cp\api\libs\Page.class.php

<?php
namespace cp\api\libs;
 
class Page extends BasicOne
{
	public $_db_table          = DB_TABLE_PAGES;
	public $_fields_required   = array('title' => PARAM_STRING);
	public $_fields_add        = array('url' => PARAM_STRING, 'info' => PARAM_TEXTAREA, 'intro' => PARAM_TEXTAREA, 'full' => PARAM_TEXTAREA);
}

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

XHTML: Вы можете использовать такие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">