2

I have a hierarchy of classes representing html elements. Some of them may not be compatible with some browser versions. The HTML5 canvas, for exemple, is not compatible with Internet Explorer before version 9.

I would like, for each type of element, to be able to know if they are or not supported by the calling browser.

abstract class AbstractView // Base class, doesn't represent anything.
{
    // ...

    // By default, an element will be considered compatible with any version of ny browser.
    protected static $FirstCompatibleVersions = array(
        'Firefox' => 0,
        'Chrome' => 0,
        'Internet Explorer' => 0);

    protected static function SetFirstCompatibleVersion($browser, $version)
    {
        static::$FirstCompatibleVersions[$browser] = $version;
    }

    protected static function IsSupportedByBrowser()
    {
        $browser = // ... Assumed to be the calling browser name.
        $version = // ... Assumed to be the calling browser version.
        return static::$FirstCompatibleVersions[$browser] <= $version;
    }
}

class CanvasView extends AbstractView // Displays a canvas. Not compatible with IE < 9.
{
    // ...
}

CanvasView::SetFirstCompatibleVersion('Internet Explorer', 9);

class FormView extends AbstractView // Displays a form. Assumed compatible with anything.
{
    // ...
}

// Nothing to do form FormView.

echo FormView::IsSupportedByBrowser(); // Should print 1 (true) (on firefox 12) but does not.

My problem is that, when i execute :

CanvasView::SetFirstCompatibleVersion('Internet Explorer', 9);

This will not only set CanvasView::$FirstCompatibleVersion['Internet Explorer'], but it will also set this value for all other classes, just like this array was common to all of the classes, making all my elements incompatible with IE < 9.

What can i do to prevent this ?

Thanks for taking the time to read.

-Virus

Virus721
  • 83
  • 5
  • Forgot to mentation that, if i redeclare the $FirstCompatibleVersions array in each of the sub classes, it works fine. – Virus721 Jun 01 '12 at 09:48

2 Answers2

1

Inside the static method you can use get_called_class() (PHP 5.3+) to know which class it's being called on.

FormView::SetFirstCompatibleVersion()

The get_called_class() would return 'FormView'. This is how you can distinguish between your subclasses.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • I tried to : "$class = get_called_class(); ... $class::..." instead of "static::...", but it seems to have the same behaviour. Thanks anyway – Virus721 Jun 01 '12 at 11:43
  • @Virus721 I thihk he suggested to store in the FirstCompatibleVersions array the name of the class: `static::$FirstCompatibleVersions[get_called_class()][$browser] = $version;`. Then you can use `return static::$FirstCompatibleVersions[get_called_class()][$browser] <= $version;`. You'll need also to assign a default value for each class. – meze Jun 01 '12 at 11:54
  • @virus721 the difference is that with get_called_class() you get a string with which you can differentiate between subclasses. Basically what meze explained. – Ja͢ck Jun 01 '12 at 12:21
  • It seems to work, thanks a lot guys. Though it can not be "inherited". If i say that CanvasView is not compatible with IE < 9, I would have liked that any class extending CanvasView would automatically considered as incompatible with IE < 9 too. But that should be good enough like this. Thanks again, cya ! – Virus721 Jun 01 '12 at 12:53
  • @virus721 if this was helpful and your rep has reached 15 consider to upvote :) – Ja͢ck Jun 01 '12 at 13:03
  • I don't have 15 yet, sorry :D – Virus721 Jun 01 '12 at 13:09
0

You can't prevent this. All children of AbstractView shares the class static variables. You can use objects instead or set their compatibility in a static variable in each class instead of using SetFirstCompatibleVersion.

meze
  • 14,975
  • 4
  • 47
  • 52
  • That's what i've been thinking about, but since i have many elements (over 100), i'll have to add a protected static array on each. And if someone ever creates a new element, he will maybe forget to create this array, and so the objet will share the parent'class array (if i understood well). Thanks for your answer ! – Virus721 Jun 01 '12 at 11:13
  • @Virus721 you still have to call SetFirstCompatibleVersion over 100 times,don't you? And someone can forget to call it too... – meze Jun 01 '12 at 11:23
  • Not exactly, i want to have to call it only when an element has compatibility issues with the calling browser. Most of the html 4 elements won't have to use this function, but some html 5 elements will have to do it for some browsers. But i will still need to give to of my element its own array, or else it will use the parent's class array, am i right ? – Virus721 Jun 01 '12 at 11:26
  • @Virus721 i was talking of `class CanvasView extends AbstractView { protected function getFirstCompatibleVersions() { return array('Internet Explorer' => 9); } }` – meze Jun 01 '12 at 11:57
  • Do you mean that i should put a getFirstCompatibleVersion static function (that would return an array like you did) in my base class, and override it in classes that have compatibility issues ? – Virus721 Jun 01 '12 at 12:21