3

It seems all my classes I create are filled with methods that contain MySql queries. I decided to take a shot at decoupling. Below I have my base class Customer, and my repository class CustomerRepository that's passed to the constructor if needed. The methods are basic, the save method in customer calls the create method in CustomerRepository for example. The customer class is now a little more readable but at what cost? I coded an entire other class just to do the MySql query that I could have put in the create method in the Customer class to begin with. I'm struggling to find a real world example of decoupling that will work in this scenario as it pertains to a work project. The examples I've found such as here, Proper Repository Pattern Design in PHP? (although fantastic), seem to be overly complex. My question(s) is: am I decoupling correctly? and is decoupling even necessary when the real world requires quick and somewhat dirty code to achieve the business goal as quickly as possible?

<?php

/*
 CRUD
 create, read, update, delete
*/

class Customer {

    public $CustomerRepository;

    public $id;
    public $first_name;
    public $last_name
    public $email;
    public $phone;

    public function __construct( CustomerRepository $CustomerRepository = null ) {
        if( !is_null( $CustomerRepository ) {
            $this->CustomerRepository = $CustomerRepository;
        }
    }

    public function save() {

        return $this->CustomerRepository->create( 
            $this->first_name, 
            $this->last_name, 
            $this->email, 
            $this->phone 
        );

    }

    public function find() {

        return $this->CustomerRepository->read( $this->id );

    }

    public function edit() {

        return $this->CustomerRepository->update( 
            $this->first_name, 
            $this->last_name, 
            $this->email, 
            $this->phone,
            $this->id
        );

    }

    public function remove() {

        return $this->CustomerRepostitory->delete( $this->id );

    }

    public function populate( $id ) {

        $customer = $this->find( $id );
        $this->id         = $customer['id'];
        $this->first_name = $customer['first_name'];
        $this->last_name  = $customer['last_name'];
        $this->email      = $customer['email'];
        $this->phone      = $customer['phone'];

    }

}

class CustomerRepository {

    private $Database;

    public function __construct() {
        if( is_null( $this->Database ) {
            $this->Database = new Database();
        }
    }

    public function create( $first_name, $last_name, $email, $phone ) {

        $this->Database->query( 'INSERT INTO customers( first_name, last_name, email, phone ) 
            VALUES( :first_name, :last_name, :email, :phone )' );
        $this->Database->bind( ':first_name', $first_name );
        $this->Database->bind( ':last_name', $last_name );
        $this->Database->bind( ':email', $email );
        $this->Database->bind( ':phone', $phone );

        return $this->Database->getLastID();
    }

    public function read( $id ) {

        $this->Database->query( 'SELECT * FROM customers WHERE id = :id LIMIT 1' );
        $this->Database->bind( ':id', $id ):

        return $this->Database->single();

    }

    public function update( $first_name, $last_name, $email, $phone, $id ) {

        $this->Database->query( 'UPDATE customer SET 
            first_name = :first_name,
            last_name  = :last_name,
            email      = :email,
            phone      = :phone WHERE id = :id' );
        $this->Database->bind( ':first_name', $first_name );
        $this->Database->bind( ':last_name', $last_name );
        $this->Database->bind( ':email', $email );
        $this->Database->bind( ':phone', $phone );
        $this->Database->bind( ':id', $id );

        return $this->Database->execute();
    }

    public function delete( $id ) {

        $this->Database->query( 'DELETE FROM customers WHERE id = :id LIMIT 1' );
        $this->Database->bind( ':id', $id ):

        return $this->Database->execute();

    }

}
Community
  • 1
  • 1
Naterade
  • 2,399
  • 8
  • 31
  • 51
  • 2
    have a look at ORMs, e.g. Active Record, Data Mapper, and frameworks that use them. If you want to exercise in designing your own ORM, there is nothing wrong with it, just an extra work. – vitr Jan 22 '16 at 02:20
  • I have checked those out. I've also used Doctrine, which was neat, but they all still seem to go back to the same issue, overkill. – Naterade Jan 22 '16 at 03:02
  • @Naterade Doctrine is powerful and flexible and might have a high learning curve. I suggest you try something like this: [SpotORM](http://phpdatamapper.com/) — there is nothing overkill about it. – Michael Jan 22 '16 at 03:57
  • _well, yes, it's overkill in a same way as using OOP for showing a simple list of customers. Just get your sql results, implode with
    and print away)_
    – vitr Jan 22 '16 at 04:06
  • @vitr I never said anything about showing a simple list of customers. It a simplified example of a more complex class that runs a complex eCommerce subscription engine. The point was to get basic decoupling advice to work into a larger system. No need to italicize your comments and be sarcastic, nobody attacking your ego. – Naterade Jan 22 '16 at 04:17
  • @Naterade, good, you accept the complexity in your systems, then ORM is the way to go, as everybody suggests here, peace – vitr Jan 22 '16 at 04:29

1 Answers1

1

As everyone already suggested here you need to implement ORM. See this question to choose: Good PHP ORM Library?

If you still don't want to use ORM you will need to implement the same thing by itself, this will take more time than using ready-to-go ORM. You could implement Unit of work (http://martinfowler.com/eaaCatalog/unitOfWork.html ) and Repository (http://martinfowler.com/eaaCatalog/repository.html) patterns to build you own ORM.

Community
  • 1
  • 1
Dzianis Yafimau
  • 1,725
  • 1
  • 23
  • 33