简体   繁体   English

PHP项目结构

[英]PHP project structure

I have a project I created using structural programming that I want to refactor as a object oriented project in the most "bestpractices" way. 我有一个我使用结构编程创建的项目,我希望以最“最佳实践”的方式将其重构为面向对象的项目。 I will probably be the only one using this project, it's not actually meant for others. 我可能是唯一一个使用这个项目的人,它实际上并不适合其他人。 But I might show it to others as example of excellence ;) 但我可能会把它作为卓越的例子展示给别人;)

My questions are pretty general, but I hope this is OK. 我的问题非常普遍,但我希望这没关系。

I'm thinking about having it split in three ways; 我想把它分成三种方式; backend (the main class), frontend (get and posts check, call class functionality), visual (using Twig templating). 后端(主类),前端(获取和发布检查,调用类功能),可视化(使用Twig模板)。 My project will be using an external intgration for IPS forum software (the user sessions will be kept there). 我的项目将使用IPS论坛软件的外部集成(用户会话将保留在那里)。 See below for my code idea how to structure this. 请参阅下面的代码,了解如何构建此代码。

My questions: 我的问题:

  1. Is my general structure ok with the class separated from "frontend" like this? 我的一般结构是否可以将这个类与“frontend”分开?
  2. Is my idea of having the member lookup/handling from IPS outside of class ok, as I later can switch to some other member functionality in frontend without messing with backend? 我的想法是在类之外让IPS成员查找/处理ok,因为我以后可以切换到前端的其他一些成员功能而不会弄乱后端吗? Just put the member object into class from wherever, making sure what class use is always set at least. 只需将成员对象从任何地方放入类中,确保始终至少设置类使用。
  3. Should I send the member data as parameter to class (construct), or keep it like now and set a public class var from frontend? 我应该将成员数据作为参数发送到类(构造),还是像现在一样保留它并从前端设置公共类var?
  4. Should my class throw exceptions on errors or return true/false and setting an error message? 我的类应该在错误上抛出异常还是返回true / false并设置错误消息?
  5. Should the frontend also be a class? 前端是否也应该是一个班级? Extend the main class? 扩展主类?
  6. Setting error messages in __construct like this is ok, or should that be done somewhere else? 像这样在__construct中设置错误消息是可以的,还是应该在其他地方完成?
  7. Should the MyProject class be split into multiple classes? MyProject类应该分成多个类吗? The current project in structural code is 10000 lines, the new class may be about half since I'm taking out a lot of visual rendering stuff. 结构代码中的当前项目是10000行,新类可能是大约一半,因为我正在取出大量的视觉渲染内容。 Maybe classes for MyProjectDisplayData and MyProjectCreateData and such? 也许MyProjectDisplayData和MyProjectCreateData的类等等?
  8. If answer to 7 is yes, should I have one core class for messages, db and general functionality, which the other specific classes "extends"? 如果对7的回答是肯定的,我应该为消息,数据库和一般功能设置一个核心类,其他特定类“扩展”吗?
  9. Is there something else one might want to do different? 是否有其他人可能想要做的不同?

myproject_class.php: myproject_class.php:

namespace MySpace;

use \PDO;
use \PDOException;
use \Exception;

class MyProject {

    public $projectdata;
    public $errormessages;
    public $ips_member;

    function __construct () {
        //set up vars for error messages
        $this->errormessages["database_queryfailed"] = "Query failed";
        $this->errormessages["general_missingdata"] = "Missing data";
        $this->errormessages["handling_something"] = "Some error";
    }

    public function displaySomeData ( $id ) {
        if ($id == ""){
            throw new Exception($this->$errormessages["general_missingdata"]);
        }

        try{
            $sql = "GET SOME DATA FROM DB";
            //PDO execute
        }catch (PDOException $e) {
            throw new Exception($this->$errormessages["database_queryfailed"] . " SQL: " . $sql);
        }

        $this->projectdata = array();
        $this->projectdata["one"] = "cool";
        $this->projectdata["two"] = "verycool";

        if ($someerror){
            throw new Exception($this->$errormessages["handling_something"]);
        }
    }

    public function createSomeData(){
        try{
            $sql = "INSERT SOME DATA IN DB";
            //PDO execute
        }catch (PDOException $e) {
            throw new Exception($this->$errormessages["database_queryfailed"] . " SQL: " . $sql);
        }
    }
}

Frontend index.php: 前端index.php:

require_once 'vendor/autoload.php';
require_once 'myproject_class.php';
require 'forum/init.php';

//forum initialize
\IPS\Session\Front::i();
$ips_member = \IPS\Member::loggedIn();

//load class
try {
    $myproj = new MySpace\MyProject();
    $myproj->ips_member = $ips_member;
} catch (Exception $e) {
    die($e->getMessage()); //not die, but handle in some way
}

//check get or post var to decide what to do
if ($_GET["dowhat"] == "display"){
    try {
        $myproj->displaySomeData($_GET["id"]);
    } catch (Exception $e) {
        die($e->getMessage()); //not die, but handle in some way
    }
}

//twig rendering
$loader = new Twig_Loader_Filesystem('template');
$twig = new Twig_Environment($loader);
$template = $twig->load('myproject.html');

echo $template->render(array('projectdata' => $myproj->projectdata, 'member' => $ips_member));

Thank you for your help! 谢谢您的帮助!

If your codebase is about 10k lines, there is no way you can stuff that in two or three classes (well, apparently you can, but it's a terrible idea). 如果你的代码库大约是10k行,你就无法在两三个类中填充(好吧,显然你可以,但这是一个糟糕的主意)。

First of all, you should extract your HTML in templates. 首先,您应该在模板中提取HTML。 Twig is a nice choice and should serve you well. Twig是一个不错的选择,应该很好。 But next step would probably be introduction of routing logic, that would let you automate the choosing of which template to render. 但下一步可能是引入路由逻辑,这将允许您自动选择要呈现的模板。

Regarding your general understanding of OOP, I would recommend you watch this and this lecture. 关于你对OOP的一般理解,我建议你观看这个讲座。 Because I am getting a feeling, that you do not really understand OOP paradigm as a whole. 因为我感觉到,你并没有真正理解OOP范式。

And don't abuse extends keywords. 并且不要滥用extends关键字。 There is this old quote in OOP: "You should favour composition over inheritance" . 在OOP中有这句老话: “你应该赞成作文而不是继承” And that sums it up quite well. 这总结得很好。

Regarding error handling, I wrote about it just few days ago, so I will just be lazy and direct you to an older post , that covered briefly the common approaches and touched upon some of the drawback in each. 关于错误处理,我几天前写过这篇文章,所以我只是懒惰并指导你找一篇较旧的帖子 ,简要介绍了常见的方法并触及了每个方面的一些缺点。

And finally, for dealing with DB: each class, that requires access to DB, should have an instance of PDO (or MySQLi) be passed in it's constructor. 最后,为了处理DB:每个需要访问DB的类,都应该在它的构造函数中传递PDO(或MySQLi)的实例。 If you have more than one such class, reading this post might help with sharing that connection instance. 如果您有多个这样的类,阅读这篇文章可能有助于共享该连接实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM