2
\$\begingroup\$

I'm using PDO, but I want to create my own class for more convenient work with the database.

My main idea in example with comments:

<?php

/**
 * User entity. I want to save it into database.
 *  @Table(name="my_table")
 */
class User {

    /**
     * Special phpDoc values indicates that this variable should be stored into database.
     *  @Column(type="integer", autoincrement=true)
     */
    private $id;

    /**
     *  @Column(type="string", length=32)
     */
    private $name;
    /**
     *  @Column(type="string", length=64)
     */
    private $password;

    /**
     *  @Column(type="string", length=256)
     */
    private $email;

    public function __construct($id = NULL) {
        if($id) {
            // Load user data from DB
        }
        // If `id` not provided — we are creating new empty user, no need to load something
    }

    public function __set($var, $value) {
        return (isset($this->$var)) ? $this->$var = $value : FALSE;
    }

    public function __get($var) {
        return (isset($this->$var)) ? $this->$var : NULL;
    }
}

// --------------------------------------------------
//  Somewhere...
// --------------------------------------------------
$dataMgr = new DataManager(); // My class that will read object properties and store them in MySQL

// --------------------------------------------------
//  Create new user
// --------------------------------------------------
$user = new User(); // Empty user

/*
 *  Set user data
 */
//$user->id = 1; // Autoincrement value
$user->name     = 'TestUser';
$user->password = 'verystrongpassword';
$user->email    = '[email protected]';

/*
 * Read $user object properties and perform MySQL query if phpdoc block with special values found.
 * INSERT query will be performed, because `id` field == NULL
 */
$dataMgr->save($user);

// --------------------------------------------------
// Update existing user
// --------------------------------------------------
$user = new User(50);
$user->password = 'newstrongpassword';

$dataMgr->save($user); // `id` in object != NULL, so perform UPDATE query

I know that there are good ORM frameworks, but they're very powerful and I don't need to use all their functions. Also I want to use my own mechanism in my own system.

What are the disadvantages? Perhaps I missed something, and my idea is not optimal, is it good practice? And what about Reflection performance?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Code critique

You indicate that the constructor will be responsible for fetching and hydrating the Entity's values. I know this is tempting. Don't do it. You already have something named DataManager. Shouldn't it handle fetching and hydrating the Entity?

In your magic get/set, you should add some code to handle the cases where a concrete getter/setter exists. Inevitably, you will end up needing special logic or transformations done to data going in our out of the object. Allowing getters and setters to be added later without having to change calling code will make life easier.

Your __set method does not need to return a value.

One example where I think you already need a setter is for the password property. I posted an example about this previously.

/*
 * @param string $clearPassword
 */
public function setPassword($clearPassword)
{
    $this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
    $this->password = crypt($clearPassword, $this->salt);
}

Me trying to talk you out of writing your own ORM

"I want to create my own class for more convenient work with the database...I don't need to use all their functions"

This indicates that you may not fully understand how to use other ORM tools. Implementing your own ORM is a massive undertaking. What are you ultimately trying to achieve? Write an application? Write an ORM library? Go down this path if you feel you must but, your time is probably better spent learning how to use of the existing tools.

You think you don't need all their (other ORM tools) functions but you eventually will as your application grows and matures. Here is a small list of things that you will eventually need but don't yet realize it:

  • Associations - How will you map Entity associations?
  • Transactions - How will you deal with transactions?
  • Custom SQL - Where would you keep any custom sql?
  • Database Migrations - After your app is in production, how will you manage schema changes?

Your Entity class annotations look similar to that of Doctrine's. It uses proxies and cached code to get around the performance issues related to reflection.

Since you seem to favor the Repository Pattern, why not simply use Doctrine?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.