views:

142

answers:

2

Hello,

I'm very new to PHP and OOP in general. I'm using codeigniter for a framework, and am currently attempting to build a class 'BuildLinks' that will redirect the user to the correct link based on what URL they landed on.

The controller passes the right variables to the class, while the function build_afflink() selects what class to call next based on the var1

The controller:

    function out($var1, $var2)
{
    // redirect to link after parsing data
    $debug='1';
    $params = array('var1'=>$var1, 'var2'=>$var2);
    $this->load->library('BuildLinks', $params);
    if ($debug=='0'){
        $redirect = $this->buildlinks->build_afflink();
        redirect($redirect, 'location', 301);
    }
    else {
        var_dump($this->buildlinks->build_afflink());
    }

}

The class BuildLinks is a work in progress... but it is extended by all of the other sites I need to support.

BuildLinks class:

    class BuildLinks
{
    public $var1;
    public $var2;
    public $link;
    function __construct($params)
    {
        //populate up inititial variables from $params array (passed from controller)
        $this->var1 = (string)$params['var1'];
        $this->var2 = (string)$params['var2'];
        echo __class__ . ' loaded....' . 'var1: '.$this->var1 . '    var2: ' .$this->var2. '<br/>';

    }
    public function get_var1()
    {
        return $this->var1;
    }

    public function set_var1($var1)
    {
        $this->var1 = $var1;
    }

    public function get_var2()
    {
        return $this->var2;
    }

    public function set_var2($var2)
    {
        $this->var2 = $var2;
    }


    function build_thelink()
    {
        switch ($this->var1) {
            case 'amazon':
                //echo 'Amazon is our vendor.<br>';
                $newobj = new Amazon;
// Amazon subclass returns the correct affiliate link

                return $newobj->affiliate_link();
                break;
            case 'ebay':
                $newobj = new Ebay;
         //ebay subclass however, cannot access the public var var1, it returns a null value for $this->var1
                return $newobj->affiliate_link();
                break;
        }

    }
}

Essentially, when I make a new Ebay object, it can't access any of the public variables from the parent class BuildLinks. What am I doing wrong?

In this example, I have it construct the initial variables and echo back out some information for debugging.

EDIT: If I change the __construct to read:

    function __construct($params)
    {
        //populate up inititial variables from $params array (passed from controller)
        $this->var1 = (string)$params['var1'];
        $this->var2 = (string)$params['var2'];
        echo __class__ . ' loaded....' . 'var1: '.$this->var1. '    var2: ' .$this->var2 . '<br/>';
        var_dump(get_class_vars(get_class($this)));
}

Then I get this as an output:

    BuildLinks loaded....var1: ebay var2: somedata

array
  'var1' => null
  'var2' => null
  'link' => null

The following works fine:

$newobj = new Amazon;
return $newobj->affiliate_link();

This does not, but the classes are almost identical...

$newobj = new Ebay;
return $newobj->affiliate_link();

Here is the ebay class:

  class Ebay extends BuildLinks
{
    private $res;
    //TODO: language/multiple site support
    //public $locale;
    function __construct()
    {
        //echo __class__ . ' loaded....' . 'vendor: '.$this->vendor . '    isbn: ' .$this->isbn . '<br/>';               
    }

    function add_to_cart_button($isbn, $locale)
    {
    }
    function affiliate_link()
    {
        $this->get_info();
        return $this->link;
    }
    // Load $this->api_call() and return Amazon SimpleXML response object, load variables
    function get_info()
    {
        $apicall = $this->api_call();
        //build variables
       foreach ($apicall->searchResult->item as $item) {
        $this->link = (string )$item->viewItemURL;
        }
    }

    // Generate API call and return simplexml object $res
    function api_call()
    {
        //build $apicall here
        $res = simplexml_load_file($apicall);

        // Check to see if the request was successful, else print an error
        if ($res->ack == "Success") {
            $this->res = $res;
            return $res;
        } else {
            echo 'api_call() unsuccessful';
        }
    }
}
A: 

Ebay::get_info() does this

foreach ($apicall->searchResult->item as $item) {
  $this->link = (string )$item->viewItemURL;
}

If $apicall->searchResult->item happens to have several elements, last of which is empty, you'll get only that last empty element.

That's a wild guess though.

[added]

You're overwriting a constructor in Ebay, so if you want BuildLinks' class constructor to be called, you need to do this explicitly.

Mchl
When the ebay class is loaded by the BuildLinks::build_thelink(), I set up the constructor of Ebay to echo $this->var1 and $this->var2. Both of these are empty -- so its a problem before it even gets to Ebay::get_info()
onlinemarketresults
Does your constructor call parent class' constructor?
Mchl
If set the constructor to call parent::__construct();, the $params array that I pass from controller to parent is not available for referencing. What's weird is that the Amazon class is able to access the var1 and var2 for some reason. This runs fine in Amazon::api_call() -- $res = $pas->item_search('$this->var2', array('ResponseGroup' => 'Large'));
onlinemarketresults
Oh I see what you are saying. How can I pass the variables from the CI controller into my class constructor so that they are constructed/available for every subclass?
onlinemarketresults
Probably rethinking your class dependencies. If the parent class can not be used in same context as extending class, it's a violation of http://en.wikipedia.org/wiki/Liskov_substitution_principle
Mchl
A: 

This part of the ebay class doesn't make too much sense to me:

function api_call()
    {
        //build $apicall here
        $res = simplexml_load_file($apicall);

        // Check to see if the request was successful, else print an error
        if ($res->ack == "Success") {
            $this->res = $res;
            return $res;
        } else {
            echo 'api_call() unsuccessful';
        }
    }

simplexml_load_file($apicall); specifically isn't loading anything. Where's $apicall? If you debug that, does it echo "api_call() unsuccessful"?

Because if that's unsuccessful then Ebay::link won't be set and as a result return $newobj->affiliate_link(); wouldn't end up returning anything.

for clarification, $apicall should be set to a file path before calling simplexml_load_file($apicall);

Tim
I didn't include the whole function here -- in my function, the $apicall variable is constructed before simplexml_load_file($apicall); is called. The api call works just fine, but I had to hardcode in a string where I'd like $this->var2 to be. That's the problem here -- the subclass Ebay can't reference any of the vars set by the parent class
onlinemarketresults
look at Mchl's constructor suggestion. Also, I have noticed that sometimes if you explicitly make a member/method public that it implicitly makes it static as well. Any chance that can access them with $BuildLinks::var2 (that's kind of a wild guess, though...).
Tim
Thanks for your suggestion, but I haven't fixed the problem yet :/
onlinemarketresults
unfortunately I am out of ideas :/ I hope you have better help...
Tim