如何通过不同的属性初始化对象?

时间:2011-09-01 07:18:21

标签: php oop

有一个对象,可以通过id或名称初始化。

应如何处理?

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);

一般练习可以吗?

6 个答案:

答案 0 :(得分:2)

恕我直言,这太可怕了。引入两个静态“结构方法”,一个接收string,另一个接收 - integer。并以不同方式构建您的对象:

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;
    }
}    

答案 1 :(得分:0)

我认为这很好。你是如何做到这一点没有错。 您可以避免使用额外的变量并编写以下内容:

$this->populate_by_id($id_or_name)

而不是以下两行:

$this->id = $id_or_name;
$this->populate_by_id($this->id)

答案 2 :(得分:0)

没关系,但我会说这会让界面更加清晰:

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);

使用这种方法,你也没有(理论上的)缺点,你不能拥有数字用户名。

答案 3 :(得分:0)

所以用户不能命名为123?你在注册表中看到了吗? ;-)由于不清楚,作为该代码的客观读者,看看构造函数的作用,我会改变它。

为什么不使用效果较差的基本构造函数,并调用适当的方法(retreive_by_id()retreive_by_name()来检索用户?

答案 4 :(得分:0)

我希望代码的一部分知道是按名称还是id加载,而不是让我的构造函数处理它。

$oUser = new User();
$oUser->loadByName($sName);


$oAnotherUser = new User();
$oAnotherUser->loadById($iId);

答案 5 :(得分:0)

你描述的内容可能大致是ActiveRecord,但ActiveRecord有一些缺点,并不是一个太干净的模式。如果您不知道模式及其含义,请不要使用它。请改为查看DataMapperRepository模式。

以下是一个简单的示例实现:

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];
    }
    …
}

现在不要做像

这样的事情
$jane = new User(123);
$john = new User('john');

让User类获取数据,在bootstrap中创建一次Users集合:

$users = new Users(
    new UserTableDataGateway(
        new DbAdapter('localhost', 'user', 'pass', 'tableName');
    ),
    new UserFactory
);

无论何时需要从数据库加载用户,只需执行

即可
$jane = $users->findById(123);
$john = $users->findByName('john');

这样做的另一个好处是,您的课程更专注于他们的责任。这将导致更易于维护,可测试和可重用的代码。有关详细信息,请参阅SOLID

至于您的特定代码:avoid doing work in the constructor。不要将业务逻辑与查询或创建逻辑混合(除非它是ActiveRecord)。不要结合论点。使用两个参数或改为使用两种方法。