2

I have been programming PHP for 7 years now- really enjoy the OOP approach with MVC and Zend Studio autocompletion.

Though it's not as complex as Visual Studio you can usually get around any autocompletion mistakes by making hints as this for example:

/* @var $this Model_User */

My question is - how exactly can you trick Zend Studio when extending other classes - without creating all the methods again and commenting them all over.

For example:

class LivingPerson extends DeadPerson {
    // This class is just to demonstrate 
}

class DeadPerson {

    public $name;
    public $lastname;

    /**
     * Get the most popular DOH' out there
     * @param string|NULL $param
     * @return DeadPerson
     */
    public static function GetDead($param=NULL) {
        $caller = get_called_class();
        $person = new $caller();
        $person->name = 'Michael';
        $person->lastname = 'Jackson';
        return $person;
    }
}

Now - if I do:

var $person = DeadPerson::GetDead(); 

Zend Studio will now reconize the object that where returned as "DeadPerson", which is true... But, if I call it from the class which i'm extending from, it obviously still think it's a "DeadPerson" object even though it's actually now a "LivingPerson" object as i've used the get_called_class() to create a new instance of the LivingPerson class.

The only way I can think of getting around this issue is by doing something like:

class LivingPerson extends DeadPerson {
    // This class is just to demonstrate 
    
    /**
     * Get the most popular DOH' out there
     * @param string|NULL $param
     * @return LivingPerson
     */
    public static function GetDead($param=NULL) {
        return parent::GetDead($param);
    }
}

But it's kinda stupid as I then need to maintain params on both the DeadPerson and LivingPerson class. And the autocomplete is really essential when programming large corporate websites - where programmeres come an go...


1 Thanks for the reply - I didn't get a chance to try it out - but I can see that i made some mistakes in the example.

I might be missing the point, because I really can't understand why it should be bad abstraction. :)

The thing is, that the second class is an abstract class. And if i call self - i will get an instance of the B class, which might not have the method's i need (as theire on class A).

Example:

interface Model_Interface {
    public function setData($data);
}

abstract class Model implements Model_Interface
{
    protected $data;

    // I do some mysql magic
    public static function FetchSingle($sql,$args=NULL) {
        $args=func_get_args();
        
        // DO mysql query etc. etc.
        
        $caller=get_called_class(); // This will make new instance of Shopping_User class instead of Model_User
        $class=new $caller();
        $caller->setData($sql->UserID);
        
    }
    
    public function setData($data) {
        $this->data = (object)$data;
    }
    
    public function __get($name) {
        return (isset($this->data->$name)) ? $this->data->$name : NULL;
    }
}

abstract class Model_User extends Model{

    /**
    /* Get user by user id.
    /* @param $userId
    /* @return Model_User
     **/
    public static function GetById($userId) {
        return self::FetchSingle('SELECT * FROM `User` WHERE `UserID` = %s', $userId);
    }
    
    public function getUrl() {
        return '/what/ever/';
    }
    
    public function getName() {
        return $this->name;
    }
}

class Shopping_User extends Model_User {
    public function getCart() {
        return 'shopping card stuff';
    }
}

Haven't tested the above- but it should give you an idea of what i'm trying to accomplish.

See.. it the same class as the Shopping user have the same properties as the "normal" user. But the IDE cannot reconize the new class

Simon

Community
  • 1
  • 1
Simon Sessingø
  • 335
  • 2
  • 10
  • Try to replace `$caller = get_called_class(); $person = new $caller();` with `$person = new static;`. Just a guess. – Valera Leontyev Dec 15 '12 at 19:47
  • Well the problem is not, that i'm not getting the correct object back. In fact i'm getting LivingPerson. The problem is, that Zend Studio still thinks, that the GetDead() return's a DeadPerson object as it can't figure out, that DeadPerson have been extended and because of get_called_class returns new instance of LivingPerson. – Simon Sessingø Dec 15 '12 at 21:07

1 Answers1

0

Your example code does not work.

First of all, calling B::GetDead() won't call DeadPerson::GetDead(). Assigning this in a statement var $person = B::GetDead() sounds completely backward, as this is the old PHP 4 syntax for public properties, and additionally it does not work: You cannot assign default values that need to execute code.

Second: A class that is able to instantiate copies of itself is weird. Unless you want to implement a Singleton, which should be avoided at all cost. Calling static methods on the class which name you already know sounds like bad abstraction.

So you might think you only suffer from bad autocomplete support from your IDE, but in reality you suffer from bad code abstraction that does not separate concerns properly enough.

Your example doesn't show enough of your real problem, but if you head over to Codereview, your code problem might get solved.

Sven
  • 69,403
  • 10
  • 107
  • 109
  • Oh sorry - i'm kinda new to stockoverflow, but the above reply was actually a comment to your reply :) – Simon Sessingø Dec 15 '12 at 20:59
  • DeadPerson::GetDead() - is not a property. It is a method. It returns an instance of the class, with all it's properties. I think it's perfectly valid. See in other programming languages calling "self" from a class that is being extended will get you the name of the child class (in this case; LivingPerson). But PHP can't seem to figure this out by itself, so that's why the get_called_class() is handy. – Simon Sessingø Dec 15 '12 at 21:03
  • I see what you are trying, but you shouldn't do it. Don't use static methods. Separate database stuff from your models. And first of all: Improve your question by editing it. If that doesn't work, start a new question and link it here. – Sven Dec 15 '12 at 21:56