PHP面向对象核心框架



我刚刚发布了这个问题,所以你们中的一些人可能会向我指出正确的方向。我正在慢慢地适应OOP,开始理解这个概念。我想做一个好的坚实的核心或基础,用作CMS后端。它还将使用MVC。我一直在使用http://gilbitron.github.com/PIP/作为MVC基础。

我想不通的是:

比方说,在后台的项目页面上,我有两个部分:htmltext和projects,我应该能够编辑它们。uri应该是这样的://域/后端/项目(方法将是索引并显示2个部分)

当我点击项目时,应该如何处理?//域/后端/项目/项目/或//域/后端/项目/列表/

更进一步,一个项目将保存一些图像或图库://域/后端/项目/编辑/5/库/2

我的问题是,首先:这是一个好的方法吗?更重要的是,如何在OOP 中实现这一点

主要项目控制者:

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");
    }
}

现在是我的问题。如果这个项目有图像,我应该在哪里加载图像类来处理这些图像?我应该像$this->images=new images()那样在project_model中加载它吗;并且在模型内部具有功能

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");
    }
}

控制器和模型似乎以这种方式混淆了。然而,从逻辑上讲,项目是一个容纳项目信息的容器,可以是文本、图像,也可以是视频。我该如何从逻辑上设置它呢。

原始问题

关于URL的第一部分叫做:路由或调度。关于它与Symfony 2.x的关系,有一篇很好的文章,但它背后的想法才是最重要的。此外,您还可以看看其他框架是如何实现它的

至于您的原始URL示例,库将存储在DB中。不是吗?它们将有一个唯一的ID。这使得/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个控制器:

  1. 单通道管理
  2. 单一项目管理
  3. 处理画廊列表

示例URL的模式与此类似:

/backend(/:controller(/:id|:page)(/:action(/:parameter)))

其中/backend部分是强制性的,但controller是可选的。若找到了控制器,则id(或页面,当您处理列表时)和action是可选的。如果找到操作,则额外的parameter是可选的。如果将此结构写成正则表达式,则可以处理大多数路由。

OOP超越类

在开始使用或编写某种PHP框架之前,您应该学习如何编写正确的面向对象代码。这并不意味着"知道如何写一堂课"。的意思是,你必须真正理解什么是面向对象编程,它基于什么原则,人们会犯什么常见错误,以及最普遍的误解是什么。以下是一些可能对你有所帮助的讲座:

  • 遗传,多态性,&测试
  • 高级OO模式(幻灯片)
  • 单元测试
  • 敏捷设计原理
  • 全球状态与辛格尔顿
  • 不要找东西
  • 超越框架(幻灯片)
  • 灵活性和质量(幻灯片)
  • Clean Code I:参数
  • Clean Code III:函数

这应该会让你对这个主题有一些了解。。是的,很多。但我怀疑你会更喜欢视频而不是书。否则,一些阅读材料:

  • PHP面向对象解决方案
  • 设计模式说明
  • 企业应用程序体系结构的模式

你会注意到很多材料都是语言不可知论者。这是因为基于类的面向对象语言的理论是一样的。

P.S

小心代码中的extends关键字。意思是"是一个"。如果class Oak extends Tree,那也没关系,因为所有的橡树都是树。但如果你有class User extends Database,有人可能会被冒犯。实际上有一个OOP原理在谈论它:利斯科夫替代原理。。还有一个非常简短的解释

如果这个项目有图像,我应该在哪里加载图像类来处理这些图像?我应该像$this->images=new images()那样在project_model中加载它吗;并且在模型内部具有功能

是的。该模型的目标是封装业务逻辑,这样您只需要编写一次算法,并多次共享它们。如果我是你,我会做的是在项目模型中添加一个getImages()方法,因为图像是项目的直接属性,这样每个项目都知道如何检索自己的图像。

与我使用过的ORMS(水合和peer/table)类相比,您的代码缺少了一些关键概念,所以我将尝试使用您的代码。您可以通过Project对象检索图像,然后通过以下两种方式之一的视图引用图像:

// 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,提供了您试图编写的大部分内容,此外,它还添加了我前面提到的缺失组件;水合、对象关系和表类,以及许多其他功能,如嵌套集。

(由于问题本身就足够长,我不想扩展它,所以我添加了它作为答案)

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只不过是获取projectdata和图像等相关数据

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);
}   
}

这种方法的好处是,我可以单独使用项目类,它会起作用。我可以将它封装在项目中,也可以使用它。

这是一种好的(也是正确的)做事方法吗?或者把这些放在一个控制器和一个模型类中会更好吗?

最新更新