Эта статья будет иметь более прикладной смысл, чем предыдущие. Мы создадим класс модели, который вы в принципе сможете использовать в своих проектах

Для начала переименуем класс Model в ideal/classes/Model.php в Registry и файл назовем также ideal/classes/Registry.php При разработке можете скидывать на этот класс все, что связано с настройками, с запросами, и т.п.

В местах его использования также все переименуем

<?php
class Registry{
	private $data = array();
	function __construct($data = array()) {
		$this->data = $data;
	}
	function __get($name){
		return isset($this->data[$name])?$this->data[$name]:null;
	}
	function __set($name,$value){
		$this->data[$name] = $value;
	}
}

в App.php

$this->config = new Registry(array_merge($default_config, $custom_config));
//...
$this->uri = new Registry(Router::gi()->parse($_SERVER['REQUEST_URI']));

и в application/models/user.php

class User extends Registry{

Теперь ничего нам не мешает создать новый класс ideal/classes/Model.php

<?php
class Model{
	private $_data = null;
	function __construct() {
		$this->_data = new stdClass();
	}
	function __set($name, $value) {
		$this->_data->$name = $value;
	}
	function __get($name) {
		return property_exists($this->_data, $name) ? $this->_data->$name : null;
	}
}

отличие от Registry пока лишь в том, что мы используем объект место ассоциативного массива.

Теперь при обращении к полю экземпляра такой модели

$model = new Model();
$model->id = 5;

вызывается магический метод __set и внутреннему объекту $data в поле $id записывается нужное значение.

Зачем это делать? - спросите вы

Ведь можно сделать так

$data = new stdObject();
$data->id = 5;

и все.

Далее вы поймете - зачем это было нужно

Дополним __set и __get нашего класса, еще парой условий

<?php
class Model{
	private $_data = null;

	function __construct() {
		$this->_data = new stdClass();
	}
	function __set($name, $value) {
		if (method_exists($this, 'set'.$name)) {
			return call_user_func(array($this,'set'.$name), $value);
		}
		return $this->_data->$name = $value;
	}
	function __get($name) {
		if (method_exists($this, 'get'.$name)) {
			return call_user_func(array($this,'get'.$name));
		}
		return property_exists($this->_data, $name) ? $this->_data->$name : null;
	}
}

теперь в наследниках этого класса можно делать следующее

class User extends Model{
	function getFullName() {
		return $this->name.' '.$this->surname;
	}
	function setFullName($value) {
		list($this->name, $this->surname) = explode(' ', $value);
	}

	// валидация
	function setEmail($value) {
		if (preg_match('#.+@.+#u', $value)) {
			$this->data->email = $value;
		}
	}
}

$user = new User();

$user->name = 'Иван';
$user->surname = 'Петров';
echo $user->fullname; //Иван Петров

$user->fullname = 'Ася Демидова';
echo $user->name; //Ася

$user->email = 'email';
echo $user->email; // пусто

$user->email = 'email@yandex.ru';
echo $user->email; // email@yandex.ru

Уже интереснее?!

Магия, да и только. Так вы можете не только обрабатывать существующие поля, чтобы в модель заносились только валидные данные, но добавлять сколько угодно не существующих полей, которые одним своим вызовом будут запускать целую плеяду событий. В одном из моих проектов были карты, у них были объекты. Просто добавляем метод getObjects, в нем изымаем все объекты карты и в любом месте программы, к объектам карты можно обратится по полю, print_r($map->objects);

Это еще не все волшебство.

Когда нам нужно добавить данные присланные из формы, в нашу модель, мы делали бы как-то так

$user = new User();
$user->login = $_POST['login'];
$user->password = $_POST['password'];
$user->status = $_POST['status'] ? 1 : 0;
$user->email = $_POST['email'];

Это просто, когда у нас всего 4 поля. А если их 10, 20, 50? Следить за всем этим зоопарком не будет ни времени ни возможности. Автоматизируем этот процесс.

<?php
class Model{
	private $_data = null;

	function __construct() {
		$this->_data = new stdClass();
	}
	function __set($name, $value) {
		if ($name==='__attributes') {
			foreach ($value as $key=>$value) {
				$this->__set($key, $value);
			}
			return;
		}
		if (method_exists($this, 'set'.$name)) {
			return call_user_func(array($this,'set'.$name), $value);
		}
		return $this->_data->$name = $value;
	}
	function __get($name) {
		if ($name==='__attributes') {
			return &$this->_data;;
		}
		if (method_exists($this, 'get'.$name)) {
			return call_user_func(array($this,'get'.$name));
		}
		return property_exists($this->_data, $name) ? $this->_data->$name : null;
	}
}

теперь в коде, можно использовать свойство __attributes

<?php
$user = new User();
$user->__attributes = $_POST;
echo $user->login; // Иван

все что есть в $_POST заполнит нашу модель данными.

Вот тут настало время подумать о безопасности модели. Что если злоумышленник засунет в $_POST лишнее поле. Да что там злоумышленник, мы сами можем случайно добавить в форму не нужное поле. Конечно, в данном примере ничего страшного не произойдет, но что если нам нужно сохранить эти данные в таблицу?! Лишнее поле вызовет ошибку и добавит нам головной боли.

Поэтому при любом присваивании надо учитывать, необходимо ли нам такое поле или нет. Для этого подойдет массив названий поддерживаемых полей.

Добавим в класс Model поле

public $safe = array();

и в __set в конец добавим условия

if (in_array($value, $this->safe)) {
	$this->_data->$name = $value;
}

класс будет выглядеть так

?php
class Model{
	private $_data = null;
	public $safe = array();

	function __construct() {
		$this->_data = new stdClass();
	}
	function __set($name, $value) {
		if ($name==='__attributes') {
			foreach ($value as $key=>$value) {
				$this->__set($key, $value);
			}
			return;
		}
		if (method_exists($this, 'set'.$name)) {
			return call_user_func(array($this,'set'.$name), $value);
		}
		
		if (in_array($value, $this->safe)) {
			$this->_data->$name = $value;
		}
	}
	function __get($name) {
		if ($name==='__attributes') {
			return &$this->_data;;
		}
		if (method_exists($this, 'get'.$name)) {
			return call_user_func(array($this,'get'.$name));
		}
		return property_exists($this->_data, $name) ? $this->_data->$name : null;
	}
}

теперь в наследниках надо прописывать этот массив валидных значений

class User extends Model{
	public $safe = array('id', 'login', 'password', 'email');
}
$user = new User();
$user->__attributes = array(
	'id'=>33,
	'login'=>'Иван',
	'sql'=>'trancate users;',
	'email'=>'sko@ya.ru'
);
echo $user->id;//33
echo $user->email;//sko@ya.ru

но

echo $user->sql;//null

Удобный класс? Теперь немного отвлечемся и подумаем, что же такое модель. Википедия дает нам такой ответ

Модель (англ. Model). Модель предоставляет знания: данные и методы работы с этими данными, реагирует на запросы, изменяя своё состояние. Не содержит информации, как эти знания можно визуализировать.

Определение верное. Модель не обязательно должна взаимодейтсвовать с базой данных или еще каким-то хранилищем. Модель вообще не означает хранение данных. Но она должна уметь обрабатывать данные и реагировать на изменение своих полей. Примером может стать простейший класс авторизации пользователя. Если у вас нет времени создавать полноценную аутентификатцию с солью, хешем и таблицей users в базе, то в single page приложениях можно ограничится таким классом авторизации.

?php
class User extends Model{
 function getAuth() {
  if ($_SESSION['auth']) {
   return true;
  }
  $_SESSION['auth'] = ($this->login=='ivan' and $this->password == 'parol') ? true : false;
  return $_SESSION['auth'];
 }
}

и далее в контроллере User добавляем метод login

<?php
class UserController extends Controller{
	function actionIndex(){
		$model = new User();
		$this->render('index',array('model'=>$model));
	}
	function actionLogin() {
		$user = new User();
		if (isset($_POST['login'])) {
			$user->>login = $_POST['login'];
			$user->password = $_POST['password'];
			if ($user->auth) {
				header('Location:/'); //в случае успеха переходим на главную
				exit();
			} else {
				$this->error = 'Не верный пользователь или пароль';
			}
		}
		$this->render('login',array('model'=>$user));
	}
}

это простейшая реализация авторизации на сайте. Безусловно она не подходит тогда, когда нам требуется сделать авторизацию для нескольких пользователей. Но вполне подойдет, когда вам быстро нужно сделать закрытое приложение на чистом php. После того как пользователь пройдет авторизацию, в любом месте фреймворка можно проверить зарегистрирован ли он, или это случайный пассажир.

$user = new user();
if (!$user->auth) {
	header('Location:/user/login');
	exit();
}

Но все же, когда речь заходит о моделях, в первую очередь вспоминают базы данных. Для того, чтобы модель взаимодейтсвовала с БД, ей нужно в этом помочь. Возьмем некий класс - оболочку, для нативных функций php с префиксом mysql_.

Я воспользуюсь собственной разработкой db.php, но вы вольны выбирать любую другую. Обычно используют какую-либо DBO реализацию. Оболочка должна уметь вытаскивать данные, и добавлять и обновлять их. В удобной форме.

Теперь научим нашу модель сохранять данные. Добавим в класс Model метод save и дадим ей возможность подключатся к БД. Для этого надо где-то инициировать подключение нашей оболочки и передать ее экземпляр в класс модели. Делать это для каждой модели будет накладно, потому как моделей может быть тысячи. Поэтому добавим экземпляр db в класс App и будем в модели использовать его.

Изменим конструктор App. Настройки подключения к БД мы заботливо положили в application/config.db.php и они доступны в App как $this->config->db или из любого места в приложении как App::gi()->config->db

public function __construct(){
	$this->initSystemHandlers();
	$default_config = include IDEAL.'config.php';
	$custom_config = include APP.'config.php';
        $this->config = new Registry(array_merge($default_config, $custom_config));
		
	include  IDEAL . 'classes/adapter/db.php';
	$this->db = new db;
	$this->db->connect($this->config->db);
}

теперь в любом месте фреймворка, можно использовать App::gi()->db, к примеру так

$users = App::gi()->db->query('select * from user')->rows();

Но настоятельно рекомендую вам не пользоваться SQL где-либо кроме моделей. Предыдущая строка вернет все записи из таблицы users, но это будут не модели User а всего-лишь объекты с полями. Чтобы эти объекты стали моделями, поиск должна производить сама модель User, и возвращать свои экземпляры. Забегая вперед скажу, что делать мы это будем так

$users = User::models()// выведет всех пользователей

Не применяйте SQL где-либо, кроме ваших моделей.

Мы отвлеклись. Вернемся в класс Model. Теперь надо научить его сохранять данные а базу. Для этого добавим ему свойство table и методы save и beforeSave

Второй метод необходим для проверки всех полей, и если он вернет true то сохраняем данные.

Плохая идея - класть все яйца в одну корзину; поэтому для работы с БД, создадим отдельный класс ModelTable сделаем его абстрактным. Чтобы никому из разработчиков, не пришло в голову, создавать его экземпляр напрямую. ideal/classes/ModelTable.php

?php
abstract class ModelTable extends Model{
	public $errors = array();
	public $table = '{table}';
	public $primary = 'id';
	
	function beforeSave () {
		return !count($this->errors);
	}

	function save () {
		$modelname = get_called_class();
		if ($this->beforeSave()) {
			if (!$this->__get(self::$primary)) {
				$res = App::gi()->db->insert($modelname::$table, $this->_data);
				$this->__set($modelname::$primary, App::gi()->db->id());
				return $res;
			} else {
				return App::gi()->db->update(
					$modelname::$table, 
					$this->_data, 
					$modelname::$primary.'='.$this->__get(self::$primary)
				);
			}
		}
	}
}

теперь, чтобы создать запись в базе - нужно выполнить всего несколько шагов

class Post extends ModelTable{
	public $table = 'posts';
	public $safe = array('id','name','content');
	public function beforeSave() {
		if (strlen($this->name)<3) {
			$this->errors['name'] = 'Слишком короткий заголовок';
		}
		return parent::beforeSafe();
	}
}
$post = new Post();
$post->__attributes = $_POST;
if ($post->save()) {
	echo 'Данные сохранены';
} else {
	print_r($post->errors);
}

модель умеет себя добавлять и обновлять. Последнее, чему мы ее научим в рамках данного урока - это выбирать экземпляры себя из базы.

Добавим в ModelTable метод models и getQuery

static function getQuery() {
	$modelname = get_called_class();
	return 'select * from '.$modelname::$table;
}
static function models() {
	$items = App::gi()->db->query(self::getQuery())->rows();
	$results = array();
	$modelname = get_called_class();
	foreach ($items as $item) {
		$model = new $modelname();
		$model->__attributes = $item;
		$results[] = $model;
	}
	return $results;
}

метод getQuery вы будете переопределять в своих моделях и добавлять разбиение на страницы, фильтры, join-ы и т.д. все, что нужно для нормальной работы сайта с тысячами записей. Теперь, чтобы вытянуть из базы все посты, делаем так

$posts = Post::models();

модель умеет извлекать себе подобных, но не умеет выбирать саму себя. Добавим статичный метод model

static function model($id) {
		$modelname = get_called_class();
		$item = App::gi()->db->query('select * from '.$modelname::$table.
						' where '.$modelname::$primary.'='.App::gi()->db->_($id))->row();
		$model = new $modelname();
		$model->__attributes = $item;
		return $model;
	}

теперь, чтобы получить модель по ее id

$post = Post::model(55);

CRUD

CRUD — (англ. create, read, update, delete — «создание, чтение, обновление, удаление») сокращённое именование 4-х базовых функций, используемых при работе с персистентными хранилищами данных. Термин стал популярным благодаря книге Джеймса Мартина (англ. James Martin) «Managing the data-base environment», выпущенной в 1983 году

.

CRUD - это не какая-то технология, это просто набор действий, которые мы должны обеспечить, чтобы пользователь мог полноценно работать с какими-либо элементами сайта: пользователи, посты, фотографии и т.д.

В большинстве фреймворков, такими элементами заведуют модели, а значит в рамках данной статьи, мы просто обязаны рассмотреть, как создать полноценную CRUD систему, используя наши модели.

Тем более, что сделать эту уже настолько просто, насколько вообще возможно.

Первое, что мы сделаем - это добавим в базу данных таблицу Posts

CREATE TABLE  `posts` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 256 ) NOT NULL ,
`content` TEXT NOT NULL
);

Теперь опишем модель этой таблицы ideal/application/models/Post.php

<?php
class Post extends ModelTable{
	static public $table = 'posts';
	public $safe = array('id','name','content');
	public function beforeSave() {
		if (strlen($this->name)<3) {
			$this->errors['name'] = 'Слишком короткое название';
		}
		return parent::beforeSave();
	}
}

Тут, перед сохранением в БД, мы проверяем введено ли название поста, и достаточной ли оно длины. Это единственное условие. Вы можете добавить туда сколько угодно условий.

Теперь перейдем непосредственно к CRUD, который реализуется внутри контроллера

Создадим новый контроллер ideal/application/controllers/PostController.php

<?php
class PostController extends Controller{
	function actionIndex() {
		$this->render('index',array('items'=>Post::models()));
	}
	function actionCreate() {
		$post = new Post();
		if (isset($_POST['form'])) {
			$post->__attributes = $_POST['form'];
			if ($post->save()) {
				header('location:/post/index');
				exit();
			}
		}
		$this->render('form',array('item'=>$post));
	}
	function actionRead($id) {
		$id = (int)$id;
		$post = Post::model($id);
		$this->render('read',array('item'=>$post));
	}
	function actionUpdate($id) {
		$id = (int)$id ? (int)$id : (int)$_POST['form']['id'];
		$post = Post::model($id);
		if ($post->id) {
			if (isset($_POST['form'])) {
				$post->__attributes = $_POST['form'];
				if ($post->save()) {
					header('location:/post/index');
					exit();
				}
			}
			$this->render('form',array('item'=>$post));
		} else {
			throw new Except('Запись не найдена');
		}
	}
}

Три действия, которые реализуют CRU и одно - для просмотра всего списка постов. Все, что осталось сделать - это создать три файла представления: index, read и form

Форма для создания и обновления ideal/application/views/post/form.php

<form action="/post/<?=App::gi()->uri->action?>" method="post">
  <div class="form-group">
    <label for="name">Название</label>
    <input type="text" class="form-control" id="name" name="form[name]" placeholder="Введите название поста" value="<?=htmlspecialchars($item->name)?>">
  </div>
  <div class="form-group">
    <label for="content">Текст</label>
    <textarea type="password" class="form-control" name="form[content]" id="content"><?=htmlspecialchars($item->content)?></textarea>
  </div>
  <input type="hidden" name="form[id]" value="<?=intval($item->id)?>">
  <button type="submit" class="btn btn-default"><?=($item->id ? 'Сохранить' : 'Создать')?></button>
</form>

Файл для вывода списка всех объектов в виде таблицы ideal/application/views/post/index.php

<a href="/post/create">Добавить запись</a>
<table class="table table-bordered">
<tr>
	<th>ID</th>
	<th>Название</th>
	<th>Текст</th>
	<th>Редактировать</th>
</tr>
<?
foreach($items as $item) {?>
	<tr>
		<td class="col-md-1"><?=$item->id?></td>
		<td class="col-md-4"><?=$item->name?></td>
		<td class="col-md-7"><?=$item->content?></td>
		<td class="col-md-7"><a href="/post/update/<?=$item->id?>" class="glyphicon glyphicon-pencil"></a></td>
	</tr>
<?};?>
</table>

Посмотреть, как работает CRUD можно здесь

На первый взгляд это семечки, и такое вы можете написать без всяких моделей, за 1 час. Но это всего лишь демонстрация. В реальных моделях могут быть десятки полей и правил. В вашем написанном за час скрипте бы пришлось править сотню мест, а здесь мы будем исправлять только форму и модель. Все остальное будет неизменным.

Файл read.php напишите сами, он ничем не примечателен и похож по сути на form, только без полей

Исходные коды урока посмотреть и скачать

Исходные коды конечного фреймворка посмотреть и скачать

Данный цикл статей продолжиться. В следующей статье разовьем тему авторизации сделаем полноценную ролевую систему

Оставлять комментарии могут только зарегистрированные пользователи

Комментарии  

Макс
# Макс 30.03.2015 17:23
Спасибо за статью, очень познавательно. С нетерпением жду продолжения. :-)
Макс
# Макс 30.03.2015 19:37
Комментарии методов класса db не помешали бы...
mike
# mike 06.04.2015 17:15
Спасибо, интересно!
Если сайт находится не в корне, а в папке (на пример http://xdan.ru/ideal/), можно ли обойтись настройками?
Ещё не хватает постраничного вывода.
Leroy
# Leroy 07.04.2015 09:22
Да вполне будет работать и в подпапке. Без каких либо манипуляций. В шаблоне с путями будут проблемы, тут надо сделать какой-нибудь класс, который будет выозвращать url корня сайта. У большинста фреймворков такой метод есть.
Постраничный вывод сделать не так сложно. рассмотрим в следующем уроке
Михаил
# Михаил 01.05.2015 04:12
Отличный материал!!!
Правда есть ошибки ,но они мобилизуют от тупого копипаста.
Спасибо!
Есть предложения:
Дополнить main.php
session_start();
и
define( "SECFW", true );

для последующей вставки в каждый php файл проверки:
defined('SECFW') or die('Прямой доступ к файлу закрыт.');
Макс
# Макс 03.05.2015 17:20
Было бы интересно узнать больше о безопасности сайта.
З.Ы. Зайдя на http://ideal.xdan.ru/post попадаем на порносайт :oops:
Михаил
# Михаил 03.05.2015 17:34
Хммм а что тут узнавать?
php запускается с любого места
данные сильно не валидятся и т.д.

Можно прикрутить например mysqli_real_escape_string
для валидации или те же preg_* и т.д. насколько хватает фантазии.
А вообще для начала сделать хотя бы один вход (я постил выше).

Автор только показал направление, остальное флаг вам в руки.
Leroy
# Leroy 05.05.2015 07:11
Да уж) Следующий пост видимо будет про безопасность) Я хотел написать только про аутентификацию, теперь затронем еще и защиту от подобного рода штук. Спасибо вам)
Михаил
# Михаил 05.05.2015 14:46
Про безопасность - хороший пост! Ждем.

Про аутентификацию... - может лучше сделать модулем и пагинатор и ещё много всего.
Лучше сделать механизм для модулей.
Михаил
# Михаил 06.05.2015 07:14
Да и ещё кстати не мешало бы перейти с mysql функций на mysqli .
Михаил
# Михаил 06.05.2015 07:17
Кому интересно может почитать
http://phpclub.ru/detail/article/mysqli

коротко о главном - увеличение скорости работы иногда в 40 раз - надеюсь убедил :lol:
Leroy
# Leroy 07.05.2015 06:53
да обычно тормоза идут на стороне мускула из-за кривых запросов без индексов
Михаил
# Михаил 08.05.2015 10:23
Потратил целых 2е минуты на переделку адаптера для mysqli :lol:

Вот ещё вопрос возник - про рендер и main.php (который во views) - как то не правильно это....
Может сделать какой нибудь базовый контроллер с базовым видом и от него наследоваться другим контролерам. А то как то не наглядно. Получается main.php к ядру привязан.
Михаил
# Михаил 08.05.2015 10:48
То есть метод renderPage в Controller.php, в нём жёстко привязан main.php из пользовательского приложения-вида (считаю это офигенным неудобством).
Сделать класс например абстрактный BaseController с методом before(внутри вызов main.php) . Ну и абстрактный(!) класс контролера с вызовом этого метода первым в рендере. Как то так...
Михаил
# Михаил 08.05.2015 15:01
Вот пример - если кому интересно:
Меняем в ..\ideal\classes\Controller.php

public $tplFileName = ''; //Добавляем переменную будет имя нашего главного шаблона

public function renderPage($content)
{
//Если существует шаблон - действуем как ранее иначе просто вывод вида контролера
$html = (!empty($this->tplFileName))?$this->_renderPartial ($this->tplPath.$this->tplFileName,array('content' =>$content), false):$content;

Ну и в приложении создаем ..\application\controllers\BaseController.php :
Михаил
# Михаил 08.05.2015 15:03
abstract class BaseController extends Controller{
public $tplFileName = 'main.php';
}

И все наши контроллеры наследуем от него.
Михаил
# Михаил 08.05.2015 15:06
Это всё для использования например технологии ajax, когда не нужен главный шаблон.
И всё прозрачно + можно ковырять своё базовый шаблон или ещё там что.
Макс
# Макс 19.05.2015 08:25
А как вызвать метод контроллера с помощью ajax?
Михаил
# Михаил 20.05.2015 16:10
Да очень просто - загуглите $.post для jquery. (как пример, можно get)
Получается js отправляет запрос на сервер к вашему контроллеру - получить список чего то (например), а он - не хороший, помимо списка, ещё и базовый шаблон вам обратно выдаёт :D
И вам приходиться вставлять сиё с html тэгами - внутрь html тэгов вашей страницы - что есть бред.
Вот что бы такого не было - одни контролеры наследуются от базового контроллера с базовым шаблоном, другие наследуются от чистого контроллера и выдают только то что нужно для ajax.
Михаил
# Михаил 20.05.2015 16:20
Подумал....ещё один вариант ответа - с помощью адресной строки разумеется:
$.post("/controller/method", { name: "John", time: "2pm" },
function(data){
alert("Data Loaded: " + data);
});
Макс
# Макс 20.05.2015 18:23
Хмм... А если что-то вроде этого:
$.ajax({
type: "POST",
url: path + "?ajaxSend=1",
...})
А в акшене:
if (isset($_GET["ajaxSend"]) && $_GET["ajaxSend"] == "1") {
die(print_r($_POST));
}

Такой велосипед поедет?)
Михаил
# Михаил 21.05.2015 03:24
Если вы POST используете, то тогда правильней:
$.ajax({
type: "POST",
url: path,
data: "ajaxSend=1",
...});
А в акшене - условие isset - избыточное, ну собствено POST:
if ($_POST["ajaxSend"] == "1") {
die(print_r($_POST));
}

Что то в этом роде....
Михаил
# Михаил 21.05.2015 03:35
Если вы имели ввиду совместить get и post - тогда правильней всё же разрулить через маршруты и отказаться от GET.
Я например сделал себе такую возможность маршрутов:
http://my.ru/conroller/action/id1/id2/id3/id4
И заруливаю всё в такой url:
http://my.ru/conroller_id1_id2_id3_id4.html
Поисковики просто рады :lol:
Собственно ради отказа от GET наверно и придумали маршруты...
Макс
# Макс 21.05.2015 08:51
Я не об этом. Акшион должен узнать является ли запрос аякс. Для этого он проверяет переменную в get если значение переменной 1, то это аякс запрос и акшион отдает данные, если 0, то он рендерит страницу.
Костыль если лень создавать класс для обработки аякс запросов.
Михаил
# Михаил 21.05.2015 15:32
Хмммм ну акшинов то может быть сколько угодно - сделать акшин для аякса? Зачем акшину узнавать что это запрос аяксовый??? :o Это аякс должен знать какому контроллеру и методу он его отсылает. ;-)
А вообще - нужен отдельный контролер для аякса (например) и у него методы для различных аяксов с различными видами(форматами возвращаемых данных) - ведь данные не просто кучей отсылаются, а с тэгами.
Михаил
# Михаил 21.05.2015 15:37
В данных пост и гет - должныть быть данные от пользователя. Всё остальное, типа служебные гет пост, должны быть заменены роутингом. Собственно ради этого здесь сегодня все мы собрались :lol:
Макс
# Макс 31.05.2015 03:34
метод getQuery вы будете переопределять в своих моделях и добавлять разбиение на страницы, фильтры, join-ы и т.д. все, что нужно для нормальной работы сайта с тысячами записей.

Для этого надо
static function models() {
$items = App::gi()->db->query(self::getQuery())->rows();

заменить на:
static function models() {
$items = App::gi()->db->query(static::getQuery())->rows();
Михаил
# Михаил 03.06.2015 08:34
Как то запутано... и зачем getQuery() нужен?
Можно в App::gi()->db->query() сразу запрос писать.
Leroy
# Leroy 03.06.2015 15:03
Затем чтобы не менять файл фреймворка. Вы переопределяете у себя в модели метод getQuery и создаете в нем какой угодно запрос. К примеру реализуете логику пагинации и фильтров. Больше ничего делать не надо. Модель загрузит данные уже сама
Михаил
# Михаил 03.06.2015 16:23
Получается вся логика работы с данными из модели перемещается в контроллер?

То есть работа модели ограничивается созданием нужного запроса и получения-передачи данных в контроллер?
Leroy
# Leroy 04.06.2015 08:38
нет, метод getQuery вы переопределяете в моделях. И всю логику работы с данными тоже нужно производить в них. Контроллер в идеале только вьюхи и модели нужные подключает и все. Больше ничего контроллер не делает. Единственный момент, я иногда ленюсь и в контроллер засовываю json выдачу ajax. Чтобы не делать лишних view. Но это не верный подход
Михаил
# Михаил 04.06.2015 13:12
Ок. Как тогда мне получить конкретные данные из базы именно в модели?
Можно примерчик?
Макс
# Макс 04.06.2015 15:47
В статье аж три примерчика)
Михаил
# Михаил 04.06.2015 16:40
Там всё не то. Мне нужно именно в модели получить результат запроса и с ним работать.
Dmitriy
# Dmitriy 09.06.2015 04:42
А как удалять поля?Помогте пожалуйста неполучается.
-.-
# -.- 24.06.2015 19:28
Не работает и не понимаю в чем дело.
Перелопатил весь код, ошибки не вижу.
Вот такая ошибка:
Class 1Controller no exist! (C:\Server\OpenServer\domains\localhost\1\ideal\classes\Singleton.php:14)

#0 C:\Server\OpenServer\domains\localhost\1\ideal\cla sses\Singleton.php(17): Singleton::getInstance('1Controller')
#1 C:\Server\OpenServer\domains\localhost\1\ideal\cla sses\App.php(17): Singleton::gI('1Controller')
#2 C:\Server\OpenServer\domains\localhost\1\main.php( 6): App->start()
#3 {main}

Одно из предположений, что где-то слеша нету или путь не так прописан.
Подскажете в чем дело?
-.-
# -.- 24.06.2015 19:31
Фрейм очень приятный, долго искал подобное.
Спасибо автору за проделанную работу :-)
Есть от чего отталкиваться.
Leroy
# Leroy 25.06.2015 09:44
У Вас довольно подробно описано какая ошибка произошла. Вы запускаете фреймворк с подпапки, , надо либо в htaccess прописать новое правило, либо в правилах роутера переделать, что контроллер идет на второй позиции от корня
-.-
# -.- 26.06.2015 00:41
Спасибо, ошибку я уже нашел и исправил)
Теперь можно опробовать.

У меня nginx, ошибка была в контроллере.
-.-
# -.- 26.06.2015 00:46
Мне понравился фрем, я заинтересовался в его развитии.
Довольно шустрый, вполне понятный и более менее грамотно написан.
Не знаю как он проявит себя на реальном проекте, в любом случаи чем я могу помочь?
Дмитрий23
# Дмитрий23 16.08.2015 19:55
Здравствуйте! Хотелось бы узнать как на счет 6-го урока, про авторизацию или разработка фреймворка прекратилась?
Anonymous Anonymous
# Anonymous Anonymous 28.12.2015 17:49
А когда будет урок про ролевую систему?
Anonymous Anonymous
# Anonymous Anonymous 28.12.2015 18:30
В исходниках "class User extends Registry", а в статьи "class User extends Model". Это что за фишка?
Anonymous Anonymous
# Anonymous Anonymous 29.12.2015 01:07
Fatal error: Class 'ModelTable' not found in /home/u711306859/public_html/application/models/Po st.php on line 2

От Model норм наследуется, а от ModelTable не хочет. Что вы изменили в коде и не написали в блоге?
Anonymous Anonymous
# Anonymous Anonymous 29.12.2015 05:14
Как на может приходит пустой POST с всех форм? var_dump($_POST['regis']) или print_r($_POST) и пусто!
Leroy
# Leroy 29.12.2015 12:34
Может метод стоит не post?
Anonymous Anonymous
# Anonymous Anonymous 31.12.2015 02:54
Цитирую Leroy:
Может метод стоит не post?

Стоить пост. Может это особенности моего хостинга?
А зачем класс Регистри, если есть Модел?
Anonymous Anonymous
# Anonymous Anonymous 08.01.2016 03:20
Для чего надо было создавать клас Registry?
Anonymous Anonymous
# Anonymous Anonymous 14.01.2016 01:27
Понял
Anonymous Anonymous
# Anonymous Anonymous 14.01.2016 01:28
Когда будет 6-й урок?
_Alex
# _Alex 04.02.2016 13:24
Да, очень хотелось бы продолжить развитие!!!!
Алексей Владимирович
# Алексей Владимирович 01.03.2016 15:45
С нетерпением ждём продолжения! Буду на основе вашего фреймворка писать проект
Алексей Владимирович
# Алексей Владимирович 15.03.2016 14:38
Тема ролевой системы была ох как кстати :-)
Kosik
# Kosik 18.03.2016 09:58
Здравствуйте! Очень интересный материал! Будет ли продолжение?
Алексей PHP
# Алексей PHP 10.06.2016 09:18
Жаль что автор забросил эту тему..