2

I am building an user class that manage the creation, deletion and modification of a generic user. My class should be used in this way:

# creation
user::create($username, $password, $email); // Does not need of $id

# modification
$u = new user($id);
$u->edit('password', $new_password);

# deletion
$u->delete();

Basically the class contain a static method create() that obliviously does not require the used id as argument. After the creation you can gather user infos and manage the user creating an instance of the class user and set as argument the $id of the user. Is that a good design or should i create something like:

# creation
$users = new genericUserMethod();
$users->create($username, $password, $email);

# modification
$u = new specificUser($id);
$u->edit('password', $new_password);

# deletion
$u->delete();

...Creating 2 different classes. Or is there any other way?

Shoe
  • 70,092
  • 30
  • 150
  • 251

3 Answers3

4

two popular ways to handle this are Active Record and Data mapper. Doctrine 1 used Active record pattern and Doctrine 2 uses Data Mapper. In short:
- with active record you have class that handles both data and persistence
- with Data Mapper you have data class and class that handles persistence

Also there is Data Access Object pattern which can go on top of either of mentioned above.

Your first example looks like active record pattern with unreasonable static shorthand for building record object (why not have multiple constructors or optional id - null for new, integer for existing).

Second example looks like DAO on top of active record and looks more usual.

Community
  • 1
  • 1
3

This could be an approach:

class User {
    private $id;
    private $name;
    //more fields here

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

    protected function load_user_data() {
        //select from DB where id = $this->id and populate fields
    }

    public function save() {
        //if $this->id is null insert the user details in DB and populate $this->id with new user's id
        //else update DB with field (optionally check what has changed and update only if necessary)
    }

    public function delete() {
        //delete user if $this->id is not null
    }

    //fields getters and setters here as needed

}

Usage sample:

$mary = new User(); //fresh new user
echo $mary->getId(); //returns null as this user is not inserted.
$mary->setName('mary');
$mary->save(); //insert user with name mary in the DB
echo $mary->getId(); // returns an id as this user is now inserted

$john = new User(2); // we assume there was a user john in DB with id = 2
echo $john->getName(); //echoes 'john' if this was his name in DB

You can even define static methods in the class like getActiveUsers() that returns an array with the active users for example...

Note: This is intended for quite simple needs, in case you require to do dome complex things I would recommend you to use an ORM library as pointed @What is the question

ircmaxell
  • 155,647
  • 33
  • 256
  • 309
maid450
  • 7,338
  • 3
  • 33
  • 32
  • I like that too, and it's what I've done in the past. Perhaps add a bit of usage (creating new users, loading old ones, deleting, etditing, etc)... Other than that, +1 – ircmaxell Jan 07 '11 at 13:54
  • 1
    Using the constructor to implicitly load the object from the database is no 'good design'. You wan't to have the possibility to indicate that the given $id is not present in the database. Also the constructor should only serve the purpose of creating new valid instances of a Class. -1 – mschneider Jan 07 '11 at 14:02
  • @mschneider you are right, constructor could also be set as protected and make 2 static methods "create" and "load" for example which internally calls the constructor... but this was intended just as a simple skeletton... – maid450 Jan 07 '11 at 14:06
  • @mschneider in what way using constructor to load the data is bad design? what did i oversleep in university?:) –  Jan 07 '11 at 14:12
  • This thing of save() and stuff really inspired me. – Shoe Jan 07 '11 at 14:12
  • 1
    @Charlie: This is called the *Active record pattern*. Look it up. – netcoder Jan 07 '11 at 14:16
  • @What is the Question You shouldn't include any functionality except for the bare minimum in your constructors. Otherwise your Modularization will suffer. Also constructors shouldn't be treated as regular methods as their capability to respond invalid/exceptional or even just rare parameters is limited as you can not return null and in some languages not even safely throw exceptions.If you follow the Active Record Pattern you would use User::find_by_id($id) to call the constructor and load the data from the database, given the parameter $id is valid. Otherwise you would return null. – mschneider Jan 07 '11 at 14:47
2

The first one. Maybe you should look at ActiveRecord/ActiveModel for some further inspirations.

mschneider
  • 716
  • 4
  • 9