简体   繁体   中英

PHP OOP Class vs Functions vs Static Functions efficiency

Sorry if I am not using the best jargon, but I have run into an issue I want to solve early before I write too much code. Which of these options below is "better"? And is there a better way of doing this? Someone mentioned to me abstracting my code but another class seems to be the last thing I need. Also I feel like there's something I can do by potentially making my "get" function seen below into a public static function so that I can use it differently. (its not static right now)

Here is my situation:

  • I have 2 (relevant to this question) classes, DB (database) and Page (for getting my content to display on my website)
  • the DB class has a query method that prepares and execute my queries
  • the DB class also has methods for inserting, getting, deleting things from the database.
  • I now feel that I may not even need my page class because right on the webpage I can just use those DB methods to call my content. (I store all images, content, page title, description in mysql). Is this not a legitimate way to do this? Won't I need to create a new object each time? such as:

     $pg_ID = 2; $title = new DB($pgID); $title->get('pages', $pgID, $lang); // 3 tables to pull from for each page $images = new DB($pgID); $images->get('images', $pgID, $lang); $structure = new DB($pgID); // I need these tables mostly because my site is in two languages $images->get('pages_list', $pgID); 

I do not like this potential solution just because to me its counter intuitive. Why should I have to create new objects just to reuse a function? However, what I do right now is something I feel is going to get me some hate mail.

    $page = new Page();
    $page->find('pages', $pgID, $lang);
    $page->lookup($pgID);
    $page->retrieve('images', $pgID, $lang);

These are 3 separate functions in my Page class that perform very similar things. Find gets my pages content out of the database and returns it as an object. Lookup does basically the same thing but only needs to pass one variable because its only to do with the html structure of each page regardless of which language is being accessed. retrieve gets all images from a table that get shown in a slider with different language descriptions. But as you can see, all three functions do basically the same thing! They query the database. Thanks for the help with this I am literally just getting into this OOP and its driving me insane. Stack has been very helpful and I think I just didn't know how to search for this to find the answer. Feel free to point me to other questions/answers that I may have missed. It was hard for me to think of the keywords to search for.

I don't want to get into the weeds on a SPECIFIC implementation for you situation, rather I am going to offer some generic guidance.

First off, you shouldn't have to create a separate database object (dbo) for title, images, or structure. Chances are the DSN used for each dbo you are initializing are the exact same, so I would create a singleton dbo which can be shared across multiple objects. For reference take a look at Doctrine's connection manager .

Secondly, I think your objectification could be implemented better. Following most ORMS implementation, you have a Record class and a Table class. The Record class is a specific instance of a Record in your schema, whereas the Table class executes queries against your store which may result in multiple records. These results are then hydrated into an array (of records).

So what I would suggest is something like this (code has not been tested and some of it has been stubbed for brevity):

class PageTable
{
    public static function getById($id)
    {
        // Validate id, if invalid throw exception

        $dbo = Database::getConnection();

        $stmt = $dbo->prepare('SELECT * FROM page WHERE id = :id');

        $stmt->bindParam(array('id' => $id));

        $stmt->execute();

        $result = $stmt->fetch();

        $page = new Page;

        // Hydration
        $page->setId($result['id']);
        $page->setImages($result['images']);

        return $page;
    }
}

class Page
{
    protected $id;

    protected $title;

    public function setId($id){}

    public function getId(){}
}

Hopefully this separation of Record and methods affecting a single, or multiple records makes sense. You should take a look at a DBAL, like Doctrine .

we may create other classes indeed, but efficiently so. Maybe we can render DB a public state function. I like the idea of creating a database object, pass it as parameter to an other object, which could then format data with the link he just received:

$pg_ID = 2;
$db = new DB($pg_id);
$page = new Page($db,$pg_ID);
 // make sure you assign the parameters a private properties in `Page()` ctor.

then, from inside your function, you can call images, titles and structures at will from $this

$title = $this->DB->get('pages', $this->pgID, $lang);
$images = $this->DB->get('images', $this->pgID, $lang);
$structure = $this->DB->get('pages_list', $this->pgID);

and you can those other method as well

$page->find('pages', $this->pgID, $lang);
$page->lookup($this->pgID);
$page->retrieve('images', $this->pgID, $lang);

Now we do not need to create a new object each time we want information from the database.

Now...

the way I access member functions here $this->pgID is better used by defining a getter: $this->pgID() . I like my getter to have the same name as the property. This might not be a very good idea though.

private function pgID() {
  return $this->pgID;
}

As for abstract classes..

I did in fact come very lately into thinking abstract classes were quite cool indeed. I've some problem with wording it, having a constant constructor with custom mandatory functions and possible different implementation of classes seems awesome:

abstract class Page {
  function __construct($db,$pgID,$lang,$params='') {
    $this->db = $db;
    $this->pgID = $pgID;
    $this->lang = $lang;
    $this->init($params);
  }
  function pgID() {
   return $this->pgID;
  }
  function lang() {
   return $this->lang;
  }
  abstract function init();
  abstract function retrieve();
}

class Structure extends Page {
  function init($params) {
    // some specific to Structure foo here
  }
  function retrieve($what='pages_list') {
    return $this->db->get($what,$this->pgID,$this->lang);
  }
}

class Image extends Page {
  function init($params) {
    // some specific to Image foo here
  }
  function retrieve($what='images') {
    $images = $this->db->get($what,$this->pgID,$this->lang);
    // plus some foo to resize each images
    return $images;
  }
}

ok, hope you're still there! Now we have a Structure and Image class with requisites constructor arguments, generic functions and a custom retrieve function. We could use them that way:

$db = new DB(2);
$template = new Structure($db,2,'fr');
$template->retrieve();

$slideshow = new Image($db,4,'en');
$slideshow->retrieve();

I do hope you do not have to create a new instance of DB if you use a different page id :-)

jokes appart this helps me using classes in a better structured way, as I might have many different classes to represent different parts of a site, but when called from an index all of them will have the same function names, like retrieve() or print() , list() ...

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