Помогите разобраться с классами в PHP

1 23
K
На сайте с 03.06.2015
Offline
45
#21

Ну то есть модель существует, в неявном виде, как метод класса. Чтобы ее не приходилось размножать под разнообразный контекст, мы разбираем запрос, или пишем класс конструктора запроса, который можно заюзать для аналогичных иерархичных отношений в БД. Самый простой конструктор для самых простых запросов состоит из методов одноименных кляузам SQL. Например


protected function select($item=null){
return 'select id, title, subttle';
}

protected function from($item=null){
return ' from news';
}

protected function where($item=null){
if($item['pid']!=0)
return ' where pid='.$item['id'];
}

protected function order(){
$ord = new COrder();
return $ord->sql();
}

protected function limit(){
$this->pgn= new CPagination();
return $this->pgn->calc_limit();
}

protected function query($item=null){
$sql=$this->select($item)
.$this->from($item)
.$this->where($item)
.$this->order()
.$this->limit();
$this->data=$this->mysqli->query_use($sql)->fetch_all(MYSQLI_ASSOC);
}

Такой класс будет выдавать листинг всего что есть в таблице News по страницам в порядке определенном параметрами в search string. Если определена категория - то по категории. Теперь под любой контекст можно унаследоваться и поменять/модифицировать методы контруктора запроса используя одну и ту же "модель" - метод query(); Например для одной статьи нам нужен еще и текст:


protected function select($item=null){
return parent::select($item).',text';
}

protected function where($item=null){
return ' where id='.$item['id'];
}

Методы рендера в том же самом классе. Обычный паттерн методов before_render(), render(), after_render() - вызывается из __toString() в охвате try-catch на случай вывести текстом глюки.

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

Где-то в классе каталога в фазе подготовки данных (модели) профтыкаем


$news = new CSearchNews();
$news->query($item);

И теперь когда этот $news окажется в конкатенации рендера каталога, то, если там есть что показать - $news покажет через свой __toString(), а если нечего - покажет пусто.

$item = это небольшой массив который делается по запросу к классу отвечающему за урлы. Мы же должны из example.com/news/article_foo_about_bar_and_some_baz получить соответствующие данные из дерева сайта. Получаем и кладем в $item. Имя сугубо условное.

MYSQL PHP JS HTML CSS SEO TXT США СССР
Sly32
На сайте с 29.03.2012
Offline
303
#22

Супер. Одна небольшая тема в форуме мне помогла продвинуться вперед быстрее и качественнее, чем 2-х недельное лопаченье литературы. Спасибо еще раз.

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

K
На сайте с 03.06.2015
Offline
45
#23

Можно передавать что угодно, в том числе и стили, генерально такая передачка называется - конфиг. Однако когда у вас есть класс из которого делается объект, этот объект сам может достать нужный ему конфиг. Дилемма pull or push решается по обстоятельствам и не нуждается в паттерне, если, конечно, вы не запутаетесь где тянуть, а где вставлять.

В литературе, особенно в русской, все старье. PHP это не Паскаль, по нему программирование изучать можно, но получится двойная работа. Сначала вы учите программировать на давным-давно устаревших кодах, потом учитесь применять навыки с новыми кодами. А вот если вы учитесь программировать на Паскале - типа латыни для программистов, то учитесь вечному вообще, абстрактно, а потом уже на любом другом языке ищите соответствующие средства и конструкции.

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

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

Насчет как передать стили. Да вот как хотя бы $news = new CNews(); и потом где-то перед рендером $news->style='foo-bar'; чтобы __toString() уже знал какой css-класс назначить чему-то там, потому что в туСтринг передать параметры нельзя. А если без волшебства, то элементарно $news->render_list('foo-bar'); в том месте, где список должен быть именно в этом стиле,

---------- Добавлено 08.06.2015 в 09:33 ----------

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

Mad_Man
На сайте с 10.11.2008
Offline
162
#24
kostyanet:
Ну то есть модель существует, в неявном виде, как метод класса. Чтобы ее не приходилось размножать под разнообразный контекст, мы разбираем запрос, или пишем класс конструктора запроса, который можно заюзать для аналогичных иерархичных отношений в БД. Самый простой конструктор для самых простых запросов состоит из методов одноименных кляузам SQL. Например


protected function select($item=null){
return 'select id, title, subttle';
}

protected function from($item=null){
return ' from news';
}

protected function where($item=null){
if($item['pid']!=0)
return ' where pid='.$item['id'];
}

protected function order(){
$ord = new COrder();
return $ord->sql();
}

protected function limit(){
$this->pgn= new CPagination();
return $this->pgn->calc_limit();
}

protected function query($item=null){
$sql=$this->select($item)
.$this->from($item)
.$this->where($item)
.$this->order()
.$this->limit();
$this->data=$this->mysqli->query_use($sql)->fetch_all(MYSQLI_ASSOC);
}


Такой класс будет выдавать листинг всего что есть в таблице News по страницам в порядке определенном параметрами в search string. Если определена категория - то по категории. Теперь под любой контекст можно унаследоваться и поменять/модифицировать методы контруктора запроса используя одну и ту же "модель" - метод query(); Например для одной статьи нам нужен еще и текст:


protected function select($item=null){
return parent::select($item).',text';
}

protected function where($item=null){
return ' where id='.$item['id'];
}


Методы рендера в том же самом классе. Обычный паттерн методов before_render(), render(), after_render() - вызывается из __toString() в охвате try-catch на случай вывести текстом глюки.

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

Где-то в классе каталога в фазе подготовки данных (модели) профтыкаем


$news = new CSearchNews();
$news->query($item);


И теперь когда этот $news окажется в конкатенации рендера каталога, то, если там есть что показать - $news покажет через свой __toString(), а если нечего - покажет пусто.

$item = это небольшой массив который делается по запросу к классу отвечающему за урлы. Мы же должны из example.com/news/article_foo_about_bar_and_some_baz получить соответствующие данные из дерева сайта. Получаем и кладем в $item. Имя сугубо условное.

ORM писать с нуля топикстартер явно не потянет.

http://rude-php.com/rude-php.zip (сама либа с ORM)

http://rude-php.com/rude-orm.pdf (документация к ORM, первые 4 страницы - скучная теория, дальше по теме)

Линки выше - компактный фреймворк (не, серьёзно, действительно небольшой), который писался под нужды продакшена с джумлой 2000-х годов. Необходимо было перевести всё это мракобесие на новые рельсы, потому как звать $database по global уже утомляло.

Рекомендую в первую очередь для тех, кто до сих пор пишет классы для работы с БД на mysql_* либе или же вовсе не в курсе как можно юзать СУБД с комфортом.

Sly32
На сайте с 29.03.2012
Offline
303
#25

proksey-net, Попробовал ваш вариант - требует доработки.


<?php foreach ($result as $res): ?>

На эту строку дает ошибку. Я так понимаю, сначала нужно объявить переменную класса, а какую?

K
На сайте с 03.06.2015
Offline
45
#26

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

---------- Добавлено 09.06.2015 в 05:38 ----------

Применительно к автозагрузке классов последовательность


$news_class = 'style-class';
$news = new News($mysqli);
$result = $news->get(5);
include 'template.php';

может быть и такой


$news_class = 'style-class';
$limit = 5;
$result = include('model/news.php');
include 'template.php';

или еще явнее, такой


$news_class = 'style-class';
$limit = 5;
$result = array();
include 'model/news.php';
include 'template.php';

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

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

Таким образом контроллер или любая другая функция связывает именно ту модель и то представление которое диктуется логикой текущего контекста, или скажем параметров из адреса, того самого Action.

Про n:M отношения слышали? Ну вот такие контроллеры и реализуют отношение многие ко многим.

---------- Добавлено 09.06.2015 в 05:52 ----------

Тем не менее нация не запрещает написать такой примерно метод в класс Новостей


protected function render_short_list(){
$html=array();
foreach($this->get_list(5) as $row)
$html[]='<h1>'.$this->render_link($row).'</h1><h3>'.$row['sub_title'].'</h3>';
return $html;
}

чтобы в любом месте любого представления вставить


<div class="news-short-list"><?php echo join($news->render_short_list());?></div>

то есть вызвав загрузку данных на этапе рендера и из самого рендера.

Sly32
На сайте с 29.03.2012
Offline
303
#27

kostyanet, Столько пробелов в голове, что временами хочется все бросить... Понимаю процентов 30, не более. Но пытаюсь продраться )))

В template должен быть шаблон вывода? А для класса - news.php ?

VHS
На сайте с 28.09.2007
Offline
142
VHS
#28
Sly32:
kostyanet, Столько пробелов в голове, что временами хочется все бросить... Понимаю процентов 30, не более. Но пытаюсь продраться )))

В template должен быть шаблон вывода? А для класса - news.php ?

Не переживай. Я пишу на php лет 15, а и то через слово понимаю его ))) Догоняю по кускам кода и интуитивно ) Это просто манера изложения.

K
На сайте с 03.06.2015
Offline
45
#29

Это паттерн MVC гадит. Он устроен не в пространстве, а во времени. Я сам тыкался по мануалам когда пытался разобраться с чем едят. Они едят их с картинками типа вот сюда стрелка, и отсюда стрелка и между еще стрелка...

Так вот, я понял и вам расскажу.

M - модель. Это фаза моделирования какой-то сущности. Например сущности "газетная статья". Вы же видели статьи, у вас есть метафора, ее надо реализовать, значит собрать свойства статьи, собрать их в кучу, затем заполнить значениями.

Например статья как модель это: текст заголовка, имя автора, дата выхода, текст подзаголовка, параграфы текста статьи, клише картинок.

Обтекание картинок текстом, цвет плашек, интерлиньяж, кернинг, трекинг, кегль, буквица, лигатуры - НЕ входят в модель. Потому что они входят в

V - представление - фазу рендера.

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

C - контроллер - фазогенератор.

Который технически просто функция или метод или вообще команда где угодно в любом месте. Отношение n:M в реляционных базах это стандартное отношение для задач типа сколько у клиента заказов.

Клиентов - много? Много. Заказов много? - Много. Как теперь связать таблицу Клиенты с таблицей Заказы так, чтобы сохранить предикат баз данных - факт хранится в одном месте? Нужна связующая таблица, Заказы_Клиентов. В которой будет 3 поля: Собственный_ИД, Клиент_ИД и Заказ_ИД.

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

Так вот граница фаз моделирования и рендера проходит по контроллеру.

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

Технически и модель и представление могут быть просто файлами как в примере выше. Их загружают, они получают тот же scope, метафора инклюлды - это копипаста. Инклюда может возвращать значения, это очень приятная фича, хотя кажется бессмысленной.

---------- Добавлено 11.06.2015 в 09:26 ----------

Почему MVC а не MCV? На этот контроллер много нареканий. Вы легко заметите как легко можно туда напихать запчастей от модели и от представления, ну, типа, а чо, ну все сразу предусмотрел и вперде. В итоге у вас жыыырный контроллер и полудохлые ни на что не годные модели. Это верный призрак плохого полиморфизма.

Дело в том что кроме кустарного производства моделей и штукатурки, в котором мы с вами находимся, существует квази- или полностью индустриальные производства. И вам приходится приделывать карбюратор от Жигулей к Запору. Где лучше всего сделать переходник? КОнечно в контроллере. Так они и жыреют.

---------- Добавлено 11.06.2015 в 09:40 ----------

Теперь вы легко увидите пресловутый MVC во всем с чем сталкивались и не задумывались. Например <div class="foo-bar">Лорем ипсум долор си амет...</div> - это контроллер, который соединяет данные и рендер. Самым же вопиющим примером паттерна отделения мух от котлет признан XML. Настолько вопиющим, что осилить его могут только мощные заводы по производству софтверных сущностей.

---------- Добавлено 11.06.2015 в 09:50 ----------

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

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

1 23

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий