简体   繁体   中英

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). My project will be using an external intgration for IPS forum software (the user sessions will be kept there). 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?
  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? 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?
  4. Should my class throw exceptions on errors or return true/false and setting an error message?
  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?
  7. Should the MyProject class be split into multiple classes? 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. Maybe classes for MyProjectDisplayData and MyProjectCreateData and such?
  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"?
  9. Is there something else one might want to do different?

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:

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).

First of all, you should extract your HTML in templates. Twig is a nice choice and should serve you well. 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. Because I am getting a feeling, that you do not really understand OOP paradigm as a whole.

And don't abuse extends keywords. There is this old quote in OOP: "You should favour composition over inheritance" . 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. If you have more than one such class, reading this post might help with sharing that connection instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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