0

I apologize in advance for this being a bit convoluted. If it were less so, I might not be considering the question. I am working with a platform that allows for extending certain core classes but not others but due to the sequence of events I'm not sure if I can apply the change from the extending class without obliterating the entire parent method (which I want to avoid). Here is a dumbed down version of the chain of classes involved:

Main View Class (extendable):

<?php

class ViewData {

    function display($main_data, $sub_id) {

        echo $main_data;

        $sub_data = new ViewSubData($sub_id);
        $sub_data->display();
    }
}

Secondary View Class (called from main class above):

<?php

class ViewSubData {

    function ViewSubData($id) {
        $this->subdata = new SubData($id);
    }

    function display() {
        print_r($this->subdata['data']);
    }

}

Data fetcher for secondary view class:

<?php

class SubData {

    function SubData($id) {

        include("path/to/{$id}.php");   
        $this = $data_array["$id"]; 

    }
}

Simplified data fetched, as an included array:

<?php

$data_array['xyz']['data']['fred'] = 'flintstone';
$data_array['xyz']['data']['barney'] = 'rubble';
$data_array['xyz']['data']['captain'] = 'caveman';

My extension of the main class (the first above) with pseudo-code of what it would accomplish:

<?php

class MyViewData extends ViewData {

    function display($main_data, $sub_id) {

        // unset(ViewSubData::subdata['data']['fred']);
        parent::display($main_data, $sub_id)

    }
}

I have read through the docs on late static binding but it's still really unclear when it works and when it doesn't and, in this case, if it can statically bind multiple-depths from a single point. If this isn't what late static binding is intended for, is there some equivalent way to call the data fetcher statically from the extended MyViewData::display method so that when the parent calls it non-statically it will already have the modified array and output (or in this case, not output) the modified array member?

Anthony
  • 36,459
  • 25
  • 97
  • 163
  • 1
    With so many levels of coupling going on *inside* the `display()` method, it's virtually impossible to extend it sanely; you *could* create data files based on other ids with certain values removed, but that's hardly a substitute of good old refactoring :) – Ja͢ck Dec 26 '13 at 05:21
  • @Jack - Thank you! If refactoring was an option, I would already be knee deep in it. But I just wanted to confirm that there was not a "sane" approach using static binding before assuming there was no other elegant option beside blaming the code I can't change (an attitude that I think contributes heavily to poor design, ie "I don't get this and I'm not aware of a way to make this work, so it must be the code's fault. This justifies me breaking it further!" Thanks again. – Anthony Dec 26 '13 at 23:01

1 Answers1

0

I don't see late static bindings used anywhere in here, I think you might misunderstand their purpose a little.

Anyway, your proposition is not going to work, since unset() in such solution is going to be called before any instance is actually constructed. It would be possible only if $subdata was declared as a static property, but then the whole design wouldn't make much sense.

You can explicitly overload the code instead of trying to use parent code to fill your specific need. Instead of doing something like

class MyViewData extends ViewData
{
    function display($main_data, $sub_id)
    {
        // unset(ViewSubData::subdata['data']['fred']);
        parent::display($main_data, $sub_id)
    }
}

you could do something like

class MyViewData extends ViewData
{
    function display($main_data, $sub_id)
    {
        echo $main_data;
        $sub_data = new ViewSubData($sub_id);
        //unset($sub_data->subdata['data']['fred']);
        //^ this is going to work since ViewSubData has filled its members in constructor
        $sub_data->display();
    }
}

Now you don't have to worry about whether unset() will work or not and neither will anyone else that later has to deal with this code later.

As a side node, setting $this to anything looks like asking for trouble and the whole design looks like it's going to give a lot of headache later. Have you considered another approach? You could be using json_encode instead of include $x and bind its results to some specific member, instead of $this.

rr-
  • 14,303
  • 6
  • 45
  • 67
  • Overwriting the entire method is what I'm trying to avoid. Since any of the downstream methods can change, overwriting can result in errors or loss of functionality ( such as parent class calling some other logic before subview ). Again, this is a mock up of the code I have no control over. I know that none of the properties are declared static, so I was curious if that was the value of late static binding, especially since the class that finally holds the array grabs it in the instantiation , – Anthony Dec 23 '13 at 22:18
  • You can always split `MyViewData::display` into smaller methods, one that is responsible for constructing `ViewSubData`, one that is responsible for doing whatever processing is necessary (this is the one you'd want to overload), and one that finally calls `display` on it. As for late static binding - generally it refers to parent class getting access to children-specific properties and methods, without knowing them beforehand. It doesn't work outside parent-child relationship. – rr- Dec 23 '13 at 22:21