Основная структура PHP OOP
Я просто отправляю этот вопрос, чтобы некоторые из вас могли правильно указать мне. Я медленно прогрелюсь до ООП, начинаю понимать концепцию. Я хочу создать хорошее твердое ядро или основу для использования в качестве CMS-сервера. Он также будет использовать MVC. Я использовал http://gilbitron.github.com/PIP/ в качестве базы MVC.
То, что я не могу понять, следующее:
Скажем, на странице проекта в бэкэнд у меня есть 2 раздела: htmltext и проекты, и я должен иметь возможность редактировать их оба. Ури будет примерно таким:
//domain/backend/projects (метод будет индексом и покажет 2 раздела)
Когда я нажимаю на проекты, как это следует обрабатывать?
//domain/backend/projects/projects/or
// домен/Серверные/проекты/список/
Еще один шаг: проект будет содержать некоторые изображения или галерею:
// домен/бэкенд/проекты/редактировать/5/галерея/2
Мой вопрос здесь, во-первых: будет ли это хорошим способом пойти и еще более важно, как это будет реализовано в ООП
главный контроллер проектов:
class projects {
function index(){
// view index
}
function edit{
$project = new Project();
$projectdata = $project->load(5);
}
}
Один контроллер проекта
class project {
function __construct(){
$this->projectmodel = $this->loadModel('project_model'); // prepare the model to be used
}
function load($id){
$this->projectmodel->loadproject($id);
}
}
модель проекта
class project_model extends model { //extends for DB access and such
function __construct(){
// do stuff
}
function loadproject($id){
return $this->db->query("SELECT * FROM projects where id=" . $id . " LIMIT 1");
}
}
Теперь мой вопрос. Если в этом проекте есть изображения, где я должен загрузить класс изображений для их обработки? Должен ли я загрузить его в project_model, например $this- > images = new Images(); и имеют функцию внутри модели
function loadimages($id){
$this->images->load($id);
}
а затем изображения будут выглядеть примерно так:
class image extends model { //extends for DB access and such
function __construct(){
}
function load($id){
return $this->db->query("SELECT * FROM project_images where id=" . $id . " LIMIT 1");
}
}
Кажется, что контроллеры и модели путаются таким образом. Но логичным способом проект является контейнером, который содержит projectinfo, который может представлять собой текст, изображения и, возможно, видео. Как я тоже собираюсь установить это логически.
Ответы
Ответ 1
Оригинальный вопрос
Первая часть, о URL-адресах, называется: Routing или Dispatching. Существует неплохая статья об этом в связи с Symfony 2.x, но идея, стоящая за ней, важна. Кроме того, вы можете посмотреть, как реализуют другие среды.
Что касается ваших исходных примеров URL, галереи будут храниться в БД. Не так ли? И они будут иметь уникальный идентификатор. Что делает это, /backend/projects/edit/5/gallery/2
совершенно бессмысленным. Вместо этого ваш URL должен выглядеть больше:
/backend/gallery/5/edit // edit gallery with ID 5
/backend/project/3 // view project with ID 3
/backend/galleries/project/4 // list galleries filtered by project with ID 4
URL должен содержать только информацию, которая вам нужна действительно.
Это также указывает на 3 контроллера:
- Управление отдельными галереями
- управление отдельными проектами
- со списками галерей
И пример URL-адресов будет иметь аналогичный шаблон:
/backend(/:controller(/:id|:page)(/:action(/:parameter)))
Если часть /backend
обязательна, но controller
является необязательной. Если контроллер найден, то id
(или страница, когда вы работаете со списками) и action
является необязательным. Если действие найдено, дополнительный parameter
является необязательным. Эта структура позволит вам заниматься большинством ваших маршрутов, если они написаны как регулярные выражения.
ООП вне классов
Прежде чем приступать к использованию или написанию своего рода фреймворка PHP, вы должны научиться писать правильный объектно-ориентированный код. И это не значит "умеет писать класс". Это означает, что вы должны действительно понимать, что такое объектно-ориентированное программирование, на каких принципах оно основано, на каких распространенных ошибках люди делают и каковы наиболее распространенные заблуждения. Вот несколько лекций, которые помогут вам в этом:
Это должно дать вам некоторое представление о предмете.. да, его много. Но подозреваю, что вы предпочтете видео по книгам. В противном случае некоторые материалы для чтения:
Вы заметите, что многие материалы являются языковыми-агностиками. Это потому, что теория для объектно-ориентированных языков на основе классов одинакова.
P.S.
Будьте осторожны с ключевым словом extends
в вашем коде. Это означает, что -. Это нормально, если class Oak extends Tree
, потому что все дубы - это деревья. Но если у вас class User extends Database
, кто-то может обидеться. На самом деле существует принцип ООП, который говорит об этом: Принцип подстановки Лискова.. также есть очень краткое объяснение
Ответ 2
Если у этого проекта есть изображения, где я должен загрузить класс изображения для их обработки? Должен ли я загрузить его в project_model, например $this- > images = new Images(); и имеют функцию внутри модели
Да. Целью модели является инкапсуляция бизнес-логики, так что вам нужно только один раз написать алгоритмы и поделиться ими несколько раз. Что бы я сделал, если бы я был вами, это добавить метод getImages()
к модели проекта, поскольку изображения являются прямым атрибутом проекта, что делает его таким, чтобы каждый проект знал, как получить его собственные изображения.
В коде отсутствует несколько ключевых концепций по сравнению с ORMS, с которыми я работал (классы гидратации и одноранговой сети), поэтому я попытаюсь придерживаться вашего кода. Вы можете получить изображения через объект "Проект", а затем ссылаться на изображения с помощью вида 1 из 2 способов:
// Controller
$this->project = new Project();
$this->projectImages = $project->getImages(); // Implemenation #2
// View
// Implemenation #1 (reference to object initialized in controller)
<?php foreach ($project->getImages() as $image): ?>
<img src="<?php echo $image['path'] ?>" />
<?php endforeach ?>
// Implemenation #2 (reference to separate variable initialized in controller)
<?php foreach ($projectImages as $image): ?>
<img src="<?php echo $image['path'] ?>" />
<?php endforeach ?>
Выше только демонстративное, но должно дать вам представление. Я бы посоветовал вам взглянуть на Doctrine. Это проверенная и стабильная ORM, которая обеспечивает большую часть того, что вы пытаетесь написать, плюс добавляет недостающие компоненты, о которых я упоминал ранее; гидратация, объектные отношения и классы таблиц, а также многие другие функции, такие как вложенные наборы.
Ответ 3
(так как вопрос был достаточно продолжительным сам по себе, я не хотел его расширять, поэтому я добавил это как ответ)
projects.php
этот контроллер расширяет контроллер проекта. основная задача состоит в том, чтобы обрабатывать несколько getAllProjects(), используя свою собственную модель, а затем передать ее на контроллер проекта getProject()
class Projects extends Project{
public function __construct()
{
parent::__construct();
$this->projects_model = new Projects_model();
}
public function getAllProjects()
{
$res = $this->projects_model->getAllProjects();
if($res) foreach($res as $v) $projects[] = $this->getProject($v);
return $projects;
}
}
project.php
project_model делает не что иное, как получение проектных данных и связанных с ними данных, таких как изображения
class Project{
public function __construct()
{
$this->project_model = new Project_model;
$this->images = new Images();
}
public function getProject($data=NULL)
{
if($data==NULL) $data = $this->project_model->loadProject($data['id']);
$images = $this->project_model->loadProjectImages($data['id']);
return array('project_id' => $data, 'project' => $data, 'images' => $images);
}
public function getProjectByID($id)
{
$data = $this->project_model->loadProject($id);
return getProject($data);
}
}
Поверхность этого подхода, я могу использовать класс проекта на своем собственном, и он будет работать. Я могу инкапсулировать его в проекты, и он также может быть использован.
Является ли это хорошим (и правильным) подходом к работе? Или было бы лучше объединить все это в один контроллер и один класс модели?