Using $this, self::, parent:: for code readability

2019-03-15 15:00发布

问题:

I would like to know if it is acceptable/preferred to use self::method() and parent::method() when working in php classes.

You can use $this->method() but $this-> can also refer to a class variable, a parent class variable, or a method from the parent class. There is no ambiguity in self::

Is self:: depreciated and/or are there any caveats or cons to using this style?

I understand that self:: and parent:: refer to a static instance of the class, but in kohana, unless you specifically define a method as static, there does not seem to be a difference.

Thanks.

Added an example: Assuming this application stores forums from multiple websites...

class Forum_Controller extends Controller {

    function __construct()
    {
        parent::__construct();
    }

    function index()
    {
        echo self::categories();
    }

/*
 * get a list of categories from a specific site.
 */
    private function categories()
    {
        $db = new Database;
        $categories = $db->query("
            SELECT * FROM
            forum_categories
            WHERE fk_site = '$this->site_id'
        ");
        $view = new View('categories_view');
        $view->categories = $categories;
        return $view;
    }

}

This examples works in kohana with error reporting set to: error_reporting(E_ALL & ~E_STRICT);

$this->site_id is defined in the main Controller_Core class (a library in kohana).

As far as I know, $this is not supposed to be available since I am calling self::categories() in a static manner, but it is only when i define categories() as static that it throws an error.

But as I said I much rather prefer using self:: because from a readability perspective, I know exactly where this function should be, rather than using $this which causes ambiguity, to me that is.

回答1:

Controllers are not static in Kohana, although they can contain static member variables / methods or constants.

self:: is a shorthand way of writing ClassName:: i.e

class Animal
{
    public static $arms = 0;
}

class Dog extends Animal
{
    public static $leg = 0;
    const NAME = 'dog';

    public static function bark()
    {
        echo 'Woof';
    }
}

To call static functions or get constants from a class we use the scope resolution operator ::. Static functions are per class not per object. Saying :: refers to static instances of a class is wrong, it is just a way to access the static methods - there isn't an object instance that has these methods.

so:

Dog::bark(),
Dog::$leg, 
Dog::NAME, 

we can also use

Animal::$arms

Inside the class Dog we can use self:: and parent:: so that we do not need to type the full class name (as it could be very long!)

In answer to your question though: No - self:: is not deprecated and no it is not bad practice to use it. The reason it is not used in kohana core is for a very different reason.... (transparent class extensions with eval read below for more info...).

p.s calling non-static methods statically is wrong and shouldn't be allowed- if you set error_reporting(E_ALL | E_STRICT) (like you should during development) you will see an error being raised.

Basically what happens is:

Core has a file called:

class Controller_Core { 
    public function someMethod(){}
}

You create:

// We can use someMethod of Controller_Core
Index_Controller extends Controller {}

This is really extending Controller_Core UNLESS you have created MY_Controller.php which would be class Controller extends Controller_Core.

//MY_Controller.php
class Controller extends Controller_Core
{
      // overloads Controller_Core::someMethod without us having to change the core file
      public function someMethod(){}
}


回答2:

There is a difference.

$this refers to an instance of an object.

parent and self are used to call methods statically.

This page of PHP's manual explains it in better detail than I have time to write at the moment. The first example in particular should help to highlight some of the differences. I encourage you to copy paste the first example and mess about with it, as I think its an important concept to get in your mind if you don't already know the difference.



回答3:

I think self:: is used generally for static functions and properties.

I use Kohana, and perhaps the controllers are made static.



回答4:

I couldn't add a comment (apparently i do not have the required rep!)

class Forum_Controller extends Controller {

public function __construct()
{
    parent::__construct();
}

public function index()
{
    echo self::categories();
}

/*
 * get a list of categories from a specific site.
 */
private static function categories()
{
    $db = new Database;

    // You cannot use $this in a static function, because static functions are per class 
    // and not per object it doesnt know what $this is :)   (make private static $site_id and use self::$site_id) if this is what you want

    $categories = $db->query("
            SELECT * FROM
            forum_categories
            WHERE fk_site = '$this->site_id'
    ");
    $view = new View('categories_view');
    $view->categories = $categories;
    return $view;
}

}

Like i said, you should use error_reporting(E_ALL | E_STRICT); (change it in the kohana file )

calling private function categories() statically works due to a bug in PHP, you shouldn't be able to do it :)



回答5:

I strictly use self:: only for static variables and static member function



回答6:

another thing to note by the way is that this isn't very good MVC design to be making static controller functions that return lists of categories.

Controllers are for dealing with requests, Models are for dealing with data (which is what this is) and Views are for display.

make a model!

class Category_Model extends Model
{
      public function categories($site_id)
      {
            $categories = $this->db->from('forum_categories')->where('fk_site',$site_id)->get();

                return new View('categories_view', array('categories' => $categories)); 
      }
}

...

$cat = new Category_Model;

echo $cat->categories(1);