Я просто отправляю этот вопрос, чтобы некоторые из вас могли указать мне правильно. Я медленно прогрелюсь до ООП, начинаю понимать концепцию. Я хочу создать хорошее твердое ядро или основу для использования в качестве CMS-сервера. Он также будет использовать MVC. Я использую http://gilbitron.github.com/PIP/ как базу MVC.
То, что я не могу понять, следующее:
Скажем, на странице проекта в бэкэнд у меня есть 2 раздела: htmltext и проекты, и я должен иметь возможность редактировать их оба. Ури будет что-то вроде: // domain / backend / projects (метод будет индексом и покажет 2 раздела)
Когда я нажимаю на проекты, как это следует обрабатывать? // domain / backend / projects / projects / или // domain / backend / projects / list /
Еще один шаг: проект будет содержать некоторые изображения или галерею: // domain / backend / projects / edit / 5 / gallery / 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, который может представлять собой текст, изображения и, возможно, видео. Как я собираюсь установить это логически.
Первая часть, о 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, вы должны научиться писать правильный объектно-ориентированный код. И это не значит «умеет писать класс». Это означает , что вы должны действительно понимать, что такое объектно-ориентированное программирование, на каких принципах оно основано, на каких распространенных ошибках люди делают и каковы наиболее распространенные заблуждения. Вот несколько лекций, которые помогут вам в этом:
Это должно дать вам обзор темы. Да, ее много. Но подозреваю, что вы предпочтете видео по книгам. В противном случае некоторые материалы для чтения:
Вы заметите, что многие материалы являются языковыми-агностиками. Это потому, что теория для объектно-ориентированных языков на основе классов одинакова.
Будьте осторожны с extends
ключевого слова в вашем коде. Это означает, что « есть ». Это нормально, если class Oak extends Tree
, потому что все дубы – деревья. Но если у вас есть class User extends Database
, кто-то может обидеться. На самом деле есть принцип ООП, который говорит об этом: принцип замещения Лискова .. также есть очень короткое объяснение
Если в этом проекте есть изображения, где я должен загрузить класс изображений для их обработки? Должен ли я загрузить его в project_model, например $ this-> images = new Images (); и имеют функцию внутри модели
Да. Целью модели является инкапсуляция бизнес-логики, так что вам нужно только один раз написать алгоритмы и поделиться ими несколько раз. Что бы я сделал, если бы я был вами, это добавить метод getImages()
к модели Project, поскольку изображения являются прямым атрибутом проекта, что делает его таким, чтобы каждый проект знал, как получить собственные изображения.
В вашем коде отсутствует несколько ключевых концепций по сравнению с ORMS, с которыми я работал (классы гидратации и одноранговой сети), поэтому я попытаюсь придерживаться вашего кода. Вы можете извлекать изображения через объект Project, а затем ссылаться на изображения с помощью вида 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 ?>
Выше только демонстративное, но должно дать вам представление. Я бы посоветовал вам взглянуть на Доктрину . Это проверенная и стабильная ORM, которая обеспечивает большую часть того, что вы пытаетесь написать, плюс добавляет недостающие компоненты, о которых я упоминал ранее; гидратации, объектных отношений и табличных классов, а также многих других функций, таких как вложенные наборы.
(поскольку вопрос был достаточно продолжительным сам по себе, я не хотел его расширять, поэтому я добавил это как ответ)
project.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); } }
Поверхность этого подхода, я могу использовать класс проекта на своем собственном, и он будет работать. Я могу инкапсулировать его в проекты, и его также можно использовать.
Является ли это хорошим (и правильным) подходом к делу? Или было бы лучше собрать все это вместе в одном контроллере и одном классе модели?