Reputation: 17049
There is an object, which can be initialized by id or by name.
How it should be handled?
class user
{
function __construct($id_or_name)
{
if ( is_numeric($id_or_name) )
{
$this->id = $id_or_name;
$this->populate_by_id($this->id)
}
else
{
$this->name = $id_or_name;
$this->populate_by_name($this->name)
}
}
...
}
$user1 = new user('Max');
$user2 = new user(123);
Is it ok for general practice?
Upvotes: 1
Views: 121
Reputation: 316989
What you describe could roughly be an ActiveRecord, but ActiveRecord has a couple of drawbacks and isnt a too clean pattern. If you dont know the pattern and its implications, dont use it. Have a look at DataMapper or Repository patterns instead.
Here is an easy example implementation:
class Users
{
protected $users = array();
protected $userTableDataGateway;
protected $userFactory;
public function __construct($userTableDataGateway, $userFactory)
{
$this->userTableDataGateway = $userTableDataGateway;
$this->userFactory = $userFactory;
}
public function findById($id)
{
if(false === isset($this->users[$id])) {
$userData = $this->userTableDataGateway->findById($id);
$this->users[$id] = $this->userFactory->createById($id, $userData);
}
return $this->users[$id];
}
…
}
Now instead of doing things like
$jane = new User(123);
$john = new User('john');
and having the User class fetch the data, you create the Users collection once in your bootstrap:
$users = new Users(
new UserTableDataGateway(
new DbAdapter('localhost', 'user', 'pass', 'tableName');
),
new UserFactory
);
and whenever you need to load a user from your database you simply do
$jane = $users->findById(123);
$john = $users->findByName('john');
This has the added benefit that your classes are much more dedicated in their responsibilites. This will lead to more maintainable, testable and reusable code. See SOLID for details.
As for your specific piece of code: avoid doing work in the constructor. Dont mix Business Logic with Query or Creation Logic (unless it's an ActiveRecord). Dont combine arguments. Use two arguments or make two methods instead.
Upvotes: 0
Reputation: 26941
IMHO, it's terrible. Introuce two static "fabric methods", one receive string
, other - integer
. And construct your object differently:
class user
{
//you might want make it private
function __construct($id_or_name)
{
//common logic
}
static function construct_by_name($name){
$result = new self();
$result->name = $name; //note you are in the same class, so you may directly assign private variables
$result ->populate_by_name($result ->name);
return $result;
}
static function construct_by_id($id){
$result = new self();
$result->id= $id; //note you are in the same class, so you may directly assign private variables
$result ->populate_by_id($result ->id);
return $result;
}
}
Upvotes: 2
Reputation: 14941
I expect the part of the code to know wether to load by name or id, and not let my constructor handle this.
$oUser = new User();
$oUser->loadByName($sName);
$oAnotherUser = new User();
$oAnotherUser->loadById($iId);
Upvotes: 0
Reputation: 151594
So a user can't be named 123? Do you catch that in your registration form? ;-) Since it's not clear, as an objective reader of that code, to see what the constructor does, I would change it.
Why don't you use a basic constructor which does less, and call the appropriate method (either retreive_by_id()
or retreive_by_name()
to retreive the user?
Upvotes: 0
Reputation: 11301
It's OK, but I'd say this makes for a more clearer interface:
class user {
public function __construct( $id ) {
$this->load( $id );
}
public function load( $id ) {
$this->populate_by_id( $id )
}
public function loadByName( $name ) {
$this->populate_by_name( $name )
}
}
$user1 = new user();
$user1->loadByName('Max');
$user2 = new user(123);
With this approach, you also have don't have the (theoratical) downside that you can't have numeric usernames.
Upvotes: 0
Reputation: 1813
I think that is fine. There is nothing wrong about how you have accomplished this. You can avoid using an extra variable and write the following:
$this->populate_by_id($id_or_name)
instead of the following two lines:
$this->id = $id_or_name;
$this->populate_by_id($this->id)
Upvotes: 0