122

I have the following php. However when I see the index.php I get the following error message.

Strict standards: Non-static method Page::getInstanceByName() should not be called statically in /var/www/webworks/index.php on line 12

I am hoping someone can tell me how to fix the problem.

index.php

// { common variables and functions
include_once('ww.incs/common.php');
$page=isset($_REQUEST['page'])?$_REQUEST['page']:'';
$id=isset($_REQUEST['id'])?(int)$_REQUEST['id']:0;
...

// { get current page id
if(!$id){
    if($page){ // load by name
        $r=Page::getInstanceByName($page);
        if($r && isset($r->id))$id=$r->id;
    }
    if(!$id){ // else load by special
        $special=1;
        if(!$page){
            $r=Page::getInstanceBySpecial($special);
            if($r && isset($r->id))$id=$r->id;
        }
    }
}

// { load page data
if($id){
    $PAGEDATA=(isset($r) && $r)?$r : Page::getInstance($id);
}
else{
    echo '404 thing goes here';
    exit;
}
...
...

ww.incs/common.php

<?php
require dirname(__FILE__).'/basics.php';
...
...

ww.incs/basics.php

session_start();
if(!function_exists('__autoload')){
    function __autoload($name) {
        require $name . '.php';
    }
}
...
...

Page.php

class Page{
    static $instances             = array();
    static $instancesByName     = array();
    static $instancesBySpecial   = array();
    function __construct($v,$byField=0,$fromRow=0,$pvq=0){
        # byField: 0=ID; 1=Name; 3=special
        if (!$byField && is_numeric($v)){ // by ID
            $r=$fromRow?$fromRow:($v?dbRow("select * from pages where id=$v limit 1"):array());
        }
        else if ($byField == 1){ // by name
            $name=strtolower(str_replace('-','_',$v));
            $fname='page_by_name_'.md5($name);
            $r=dbRow("select * from pages where name like '".addslashes($name)."' limit 1");
        }
        else if ($byField == 3 && is_numeric($v)){ // by special
            $fname='page_by_special_'.$v;
            $r=dbRow("select * from pages where special&$v limit 1");
        }
        else return false;
        if(!count($r || !is_array($r)))return false;
        if(!isset($r['id']))$r['id']=0;
        if(!isset($r['type']))$r['type']=0;
        if(!isset($r['special']))$r['special']=0;
        if(!isset($r['name']))$r['name']='NO NAME SUPPLIED';
        foreach ($r as $k=>$v) $this->{$k}=$v;
        $this->urlname=$r['name'];
        $this->dbVals=$r;
        self::$instances[$this->id] =& $this;
        self::$instancesByName[preg_replace('/[^a-z0-9]/','-',strtolower($this->urlname))] =& $this;
        self::$instancesBySpecial[$this->special] =& $this;
        if(!$this->vars)$this->vars='{}';
        $this->vars=json_decode($this->vars);
    }
    function getInstance($id=0,$fromRow=false,$pvq=false){
        if (!is_numeric($id)) return false;
        if (!@array_key_exists($id,self::$instances)) self::$instances[$id]=new Page($id,0,$fromRow,$pvq);
        return self::$instances[$id];
    }
    function getInstanceByName($name=''){
        $name=strtolower($name);
        $nameIndex=preg_replace('#[^a-z0-9/]#','-',$name);
        if(@array_key_exists($nameIndex,self::$instancesByName))return self::$instancesByName[$nameIndex];
        self::$instancesByName[$nameIndex]=new Page($name,1);
        return self::$instancesByName[$nameIndex];
    }
    function getInstanceBySpecial($sp=0){
        if (!is_numeric($sp)) return false;
        if (!@array_key_exists($sp,$instancesBySpecial)) $instancesBySpecial[$sp]=new Page($sp,3);
        return $instancesBySpecial[$sp];
    }
H. Pauwelyn
  • 13,575
  • 26
  • 81
  • 144
shin
  • 31,901
  • 69
  • 184
  • 271
  • 17
    Hmm, could it be that you're calling a method statically, and that method isn't defined as static? You know, pretty much exactly what the error says, on the line number it says... – Harold1983- Jan 13 '11 at 19:48

7 Answers7

197

Your methods are missing the static keyword. Change

function getInstanceByName($name=''){

to

public static function getInstanceByName($name=''){

if you want to call them statically.

Note that static methods (and Singletons) are death to testability.

Also note that you are doing way too much work in the constructor, especially all that querying shouldn't be in there. All your constructor is supposed to do is set the object into a valid state. If you have to have data from outside the class to do that consider injecting it instead of pulling it. Also note that constructors cannot return anything. They will always return void so all these return false statements do nothing but end the construction.

Kelderic
  • 6,502
  • 8
  • 46
  • 85
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 2
    The codes are from this book...https://www.packtpub.com/cms-design-using-php-and-jquery/book. I think you should write a book, Gordon. :-) – shin Jan 13 '11 at 20:00
  • 6
    @shin Nah, I'd only repeat what others have said better than me before. But that's some really bad code for a book that was released Dec 2010. Do they give any reason for omitting any visibility keywords or not following PEAR coding convention? Let's hope the jQuery and general CMS architecture is more solid. – Gordon Jan 13 '11 at 20:26
  • 17
    @dzona that would be ignoring the problems with the code, not fixing it. – Gordon Dec 04 '13 at 06:10
  • 1
    Important NOTE: the `public` keyword is used only in function/variable declarations from within a class. See http://stackoverflow.com/questions/13341378/php-parse-error-syntax-error-unexpected-t-public – cssyphus Feb 06 '15 at 18:17
  • 1
    @Gordon, just curious -- why do you advocate changing the offending method to `static`, instead of (re)writing the code to use `$p = new Page(); $p->getInstanceByName();`? – Dennis Jul 13 '16 at 18:35
  • 1
    @Dennis I am not advocating it. Using static us the correct and immediate explanation to the question at hand. But it should be clear from the second half the answer that I am not advocating it at all. – Gordon Jul 13 '16 at 18:50
  • 1
    @Gordon, thanks, I meant that I see the `static` answer as accepted & most upvoted answer. Even though you warn about using static as a death to testability, it tells me that people consume this answer and move on, most likely using `static` to fix their issue. To me I don't see why it is necessarily (the only) correct or immediate solution. When I first encountered the error myself, I changed my code to instantiate the class. After receiving same error in another place, I've decided to take a look at which method is "better". Judging by upvotes, I presume that `static` fix is preferred. – Dennis Jul 13 '16 at 19:58
  • 1
    What if we don't have control on class? I mean I am using the method of third-party class. So I can't make the method static. – Bunty Nov 06 '17 at 06:26
  • 1
    @Bunty Dont call it statically then? – Gordon Nov 06 '17 at 06:46
  • 1
    @Gordon Any other option, I can do for that? – Bunty Nov 06 '17 at 06:55
  • 1
    @Bunty without further context as to why you cannot call it non-statically, the answer is no. it makes no sense. If the third party method is not static, dont call it as if it was static. You have control over how you call the method, dont you? – Gordon Nov 06 '17 at 07:29
25

I think this may answer your question.

Non-static method ..... should not be called statically

If the method is not static you need to initialize it like so:

$var = new ClassName();
$var->method();

Or, in PHP 5.4+, you can use this syntax:

(new ClassName)->method();
Pea
  • 431
  • 7
  • 9
1

If scope resolution :: had to be used outside the class then the respective function or variable should be declared as static

class Foo { 
        //Static variable 
        public static $static_var = 'static variable'; 
        //Static function 
        static function staticValue() { return 'static function'; } 

        //function 
        function Value() { return 'Object'; } 
} 



 echo Foo::$static_var . "<br/>"; echo Foo::staticValue(). "<br/>"; $foo = new Foo(); echo $foo->Value();
B001ᛦ
  • 2,036
  • 6
  • 23
  • 31
1

Try this:

$r = Page()->getInstanceByName($page);

It worked for me in a similar case.

Nissa
  • 4,636
  • 8
  • 29
  • 37
1

use className->function(); instead className::function() ;

ulas korpe
  • 39
  • 2
-1

return false is usually meant to terminate the object creation with a failure. It is as simple as that.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Tomas
  • 7
  • 2
-2

Instead of using the instance with the scope resolution operator :: because it wasn't defined like static function.

$r=Page::getInstanceByName($page);

change it to :

$r=Page->getInstanceByName($page);

And it will work like a charm.

Rashwan L
  • 38,237
  • 7
  • 103
  • 107
Lorand
  • 57
  • 1
  • 4