0

I'm converting an old plugin from PHP5 -> PHP8 and I came across this check, which caused an error when executing:

Notice: Accessing static property PropertySearch::$listing_details_template_name as non static

I found online that this can be fixed, by using self instead of $this to access a static member. However, when I pass self to the is_page Wordpress function, it returns false, where-as when I pass $this, it returns true.

From what I can tell, both of these contain the exact same string value.

  • self::$listing_details_template_name
  • $this->listing_details_template_name

One thing I noticed while debugging, is that upon entering the is_page function, the $page variable is NULL when using $this->listing_details_template_name.

When entering the is_page function with self::$listing_details_template_name, the $page variable contains the name of the template.

Here's a quick demo of what I'm talking about.

Ultimately, I'm trying to find out why this is happening, and how I can pass the static member to is_page to get the expected result of true.

global $wp_query;

    if (is_page(self::$listing_details_template_name)) {
        echo nl2br ("[DEBUG] - self2 = " . self::$listing_details_template_name . " \r\n");
    }

    if (is_page($this->listing_details_template_name)) {
        echo nl2br ("[DEBUG] - this2 = " . self::$listing_details_template_name . " \r\n");
    }

===

For the time being, I've added this to the class-wp-query.php file of WordPress.

    if ($page = 'property-search-single-property-details-template.php') {
        $page = NULL;
    }

However, this is just a bandaid so I can continue debugging. I would love a solution that does NOT involve me modifying the core WordPress files. Or at the very least, some further understanding of why this is happening.

===

    class PropertySearch {

    private static $listing_details_template_name;

    public function __construct() {

        if (self::IsSingleProperty()) {
            self::$listing_details_template_name = 'property-search-single-property-details-template.php';
        } else {
            self::$listing_details_template_name = 'property-search-details-template.php';
        }

    public function PropertySearchListingDetails() {
        global $wp_query;

        if (is_page(self::$listing_details_template_name)) {
            if (!empty($wp_query->query_vars['building'])) {
                return json_decode((string) $this->SyndicationAPI->getDetails($wp_query->query_vars['building']), null, 512, JSON_THROW_ON_ERROR);
            } else {
                return json_decode((string) $this->SyndicationAPI->getDetails(SINGLE_PROPERTY_ID), null, 512, JSON_THROW_ON_ERROR);
                //return 'No listing found';
            }
        } else {
        }
    }

}
5
  • 1
    How is the listing_details_template_name property declared on the class, and how is its value set? Where and how is the class instantiated? Nov 14 at 4:56
  • I added a code block which "I think" answers your questions. I actually ended up "circumventing" this issue, by simply inverting the is_page() function with ! is_page() (not shown in the code example). It "works" but I would still like to know why there is a differnet result when passing $this and or self.
    – level42
    Nov 14 at 14:04
  • 1
    your inversion isn't what solved the problem, rather you accidentally fixed the issue by using self::$ instead of $this->
    – Tom J Nowell
    Nov 14 at 15:51
  • The original code I inherited had $listing_details_template_name declared as static, and was passing $this to the is_page() function. Since I'm converting this code to PHP8, and am rather inexperienced with PHP, I assumed this was at least somewhat a correct method (at least back in PHP5ish when this code was written). I found online that I should be using self instead, hence this question. I'm still not 100% sure I understand why there are differnet output results from is_page() (per the video clip), but I'm getting the expected results now from the inversion which I made.
    – level42
    Nov 15 at 16:32
  • Your answer absolutely helps me to understand the difference between self and $this, by the way. I guess the is_page() function just handles static members and objects differently in PHP8, thus the differentiated results? I'm also guessing that this was not the case in older versions of PHP, which is why the code was originally written with an object identifier $this instead.
    – level42
    Nov 15 at 16:35

1 Answer 1

2

You've shared that this is how the member variable is defined:

class PropertySearch {
    private static $listing_details_template_name;

This means it is a private static variable and can be accessed using static accessor such as self::$listing_details_template_name or PropertySearch::$listing_details_template_name.

Additionally, you've declared that it's a private member variable, so it can only be referred to from within the same class via self::.

Why not $this?

$this would be innapropriate because $this refers to a specific object, not a class, and static member variables do not belong to objects, they belong to the definition of a class, specifically PropertySearch.

Remember, PropertySearch is not an object, it's a class, a class is a definition that's used to create instances of objects. I may be human but it would be a mistake to say human::$name = 'Tom'; because that's saying that all humans are named Tom, not just me specifically.

Likewise $this->listing_details_template_name heavily implies that different PropertySearch objects can have different listing detail templates, and that it's a dynamic changing value, not a static value shared by all objects that use that class.

That is why you get this message:

Notice: Accessing static property PropertySearch::$listing_details_template_name as non static

Ironically, if you changed it to be a dynamic member variable it would work with $this and it would no longer be appropriate to use self.

Methods

Instead of directly accessing it why not use a method? Then you can add filtering and other logic.

TLDR

  • static member variables are on classes
  • dynamic member variables are on objects
  • Use $this->variablename or $object->variablename for dynamic member variables
  • Use self::$variablename or ClassName::$variablename for static member variables
  • Consider using a method as an alternative option
2
  • 1
    Hey Tom! I really appreciate the breakdown here, and it helps to explain a lot! I'm not a PHP developer, and before this project have never really worked with PHP code prior too, so it's all brand new to me. You explanation helped immensely here and was clear and concise as possible. As per the use of a method instead, I'm not sure how this would work, or apply, nor do I think it's necessary in the scope of the project I'm working on, but it's something I will look into after this project has been completed. Thank you again for taking the time to break things down and explain them to me!
    – level42
    Nov 15 at 16:26
  • 1
    re: using a method, it would let you move the logic out of the constructor allowing more flexibility, you could then do something like $template = self::get_listing_details_template();. Also note that PHP isn't the only language that supports static stuff
    – Tom J Nowell
    Nov 15 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.