views:

582

answers:

6

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.

A: 

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

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

alex
+4  A: 

There is a difference.

$this refers to an instance of an object.

parent and self are used to call methods statically.

This page explains it in better detail than I've time to write at the moment. The first example in particular should help to highlight some of the differences. 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.

http://uk2.php.net/manual/en/language.oop5.basic.php

benlumley
Thank you for replying. The documentation link is very helpful. I was unable to come up with the right words to find it, otherwise.
superjadex12
+1  A: 

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 depreciated 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(){}
}
Thank your for taking the time to explain this. It is very helpful. I understand now what you mean by "Static functions are per class not per object". I will read the documentation supplied by benlumley, but I am still puzzled by the fact that my code still works: I have appended some example code to my question, please take a look. Thanks again.
superjadex12
A: 

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

A: 

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

A: 

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

Extrakun