Question

So basically I'm making a leap from procedural coding to OOP. I'm trying to implement the principles of OOP but I have a nagging feeling I'm actually just writing procedural style with Objects.

So say I have a list of pipes/chairs/printers/whatever, they are all all listed as products in my single table database. I need to build a webapp that displays the whole list and items depending on their type, emphasis is on 'correct' use of OOP and its paradigm.

Is there anything wrong about just doing it like:

     CLass Show
     {

      public function showALL(){
      $prep = "SELECT * FROM myProducts";
      $q = $this->db-> prepare($prep);     
      $q->execute();
      while ($row = $q->fetch()) 
          {
            echo "bla bla bla some arranged display".$row['something']       
          }
      }

and then simply

$sth = new show();
$sth->showAll();

I would also implement more specific display methods like:

showSpecificProduct($id)->($id would be passed trough $_GET when user say clicks on one of the links and we would have seperate product.php file that would basically just contain

include('show.class.php');
$sth = new show();
$sth->showSpecificProduct($id);

showSpecificProduct() would be doing both select query and outputing html for display.

So to cut it short, am I going about it allright or I'm just doing procedural coding with classes and objects. Also any ideas/hints etc. on resolving it if I'm doing it wrong?

Was it helpful?

Solution

As well as the model practices described by @Phil and @Drew, I would urge you to separate your business, data and view layers.

I've included a very simple version which will need to be expanded upon in your implementation, but the idea is to keep your Db selects separate from your output and almost "joining" the two together in the controller.

class ProductController
{
    public $view;

    public function __construct() {
        $this->view = new View;
    }

    public function indexAction() {
        $model = new DbProductRepository;
        $products = $model->fetchAll();

        $this->view->products = $products;
        $this->view->render('index', 'product');
    }
}

class View
{
    protected $_variables = array();        

    public function __get($name) {
        return isset($this->_variables['get']) ? $this->_variables['get'] : null;
    }

    public function __set($name, $value) {
        $this->_variables[$name] = $value;
    }

    public function render($action, $controller) {
        require_once '/path/to/views/' . $controller . '/' . $action . '.php';
    }
}

// in /path/to/views/product/index.php
foreach ($this->products as $product) {
    echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}

OTHER TIPS

A better fit would be to implement a repository pattern. An example interface might be

interface ProductRepository
{
    public function find($id);

    public function fetchAll();
}

You would then create a concrete implementation of this interface

class DbProductRepository implements ProductRepsoitory
{
    private $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function find($id)
    {
        // prepare execute SQL statement
        // Fetch result
        // return result
    }

    public function fetchAll()
    {
        // etc
    }
}

It's generally a bad idea to echo directly from a method or function. Have your methods return the appropriate objects / arrays / whatever and consume those results.

The scenario you are describing above seems like a good candidate for MVC.

In your case, I would create a class strictly for accessing the data (doing selects of product categories or specific products) and then have a different file (your view) take the output and display it.

It could look something like this:

class Product_Model {
    public function find($prodId) { ... }
    public function fetchAll($category = '') { ... }
    public function search($string) { ... }
}

Then somewhere else you can do:

$products = new Product_Model();
$list = $products->fetchAll(37); // get all from category 37

// in true MVC, you would have a view that you would assign the list to
// $view->list = $list;

foreach($ilst as $product) {
    echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}

The basic principle of MVC is that you have model classes that are simply objects representing data from some data source (e.g. database). You might have a mapper that maps data from the database to and from your data objects. The controller would then fetch the data from your model classes, and send the information to the view, where the actual presentation is handled. Having view logic (html/javascript) in controllers is not desirable, and interacting directly with your data from the controller is the same.

first, you will want to look into class autoloading. This way you do not have to include each class you use, you just use it and the autoloader will find the right file to include for you.

http://php.net/manual/en/language.oop5.autoload.php

each class should have a single responsibility. you wouldn't have a single class that connects to the database, and changes some user data. instead you would have a database class that you would pass into the user class, and the user class would use the database class to access the database. each function should also have a single responsibility. you should never have an urge to put an "and" in a function name.

You wouldn't want one object to be aware of the properties of another object. this would cause making changes in one class to force you to make changes in another and it eventually gets difficult to make changes. properties should be for internal use by the object.

before you start writing a class, you should first think about how you would want to be able to use it (see test driven development). How would you want the code to look while using it?

$user = new User($db_object);
$user->load($id);
$user->setName($new_name);
$user->save();

Now that you know how you want to be able to use it, it's much easier to code it the right way.

research agile principles when you get a chance.

One rule of thumb is that class names should usually be nouns, because OOP is about having software objects that correspond to real conceptual objects. Class member functions are usually the verbs, that is, the actions you can do with an object.

In your example, show is a strange class name. A more typical way to do it would be to have a class called something like ProductViewer with a member function called show() or list(). Also, you could use subclasses as a way to get specialized capabilities such as custom views for particular product types.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top