7

On Class A I have this:

protected function createTempTable()
{
    $qry = '
        CREATE TABLE  `'.$this->temp_table.'` (
         `style` VARCHAR( 255 ) NOT NULL ,
         `description` VARCHAR( 255 ) NOT NULL ,
         `metal` VARCHAR( 255 ) NOT NULL ,
         `available` VARCHAR( 255 ) NOT NULL ,
         `center_stone` VARCHAR( 255 ) NOT NULL ,
         `total_weight` VARCHAR( 255 ) NOT NULL ,
         `price` DECIMAL( 10, 2 ) NOT NULL ,
        PRIMARY KEY (  `style` )
        ) ENGINE = MYISAM ;
    ';
    
    $pdo = PDOManager::getConnection();
        
    $sth = $pdo->query($qry);
}

Class B extends class A and has this:

protected function createTempTable()
{
    $qry = '
        CREATE TABLE  `'.$this->temp_table.'` (
         `style` VARCHAR( 255 ) NOT NULL ,
         `syn10` DECIMAL( 10, 2 ) NOT NULL ,
         `gen10` DECIMAL( 10, 2 ) NOT NULL ,
         `syn14` DECIMAL( 10, 2 ) NOT NULL ,
         `gen14` DECIMAL( 10, 2 ) NOT NULL ,
        PRIMARY KEY (  `style` )
        ) ENGINE = MYISAM ;
    ';
    
    $pdo = PDOManager::getConnection();
        
    $sth = $pdo->query($qry);
}

ClassB does not actually call createTempTable it lets it's super class ClassA call it.

So in theory when I create a new ClassB class, it's super class calls createTempTable() which should use ClassB's override version of the function. However it does not, it still uses ClassA's version. I confirmed this by doing a SHOW CREATE TABLE from inside ClassB. I expected to have a syn10 column instead I had a description column.

Why is this?

edit:

Here is the code from class A that calls the createTempTable function:

public function processPriceSheet ($file, $test = false)
{
    if(!file_exists($file))
    {
        die('The file "'.$file.'" does not exist.');    
    }
    $fp = fopen($file,'r');
    
    $this->createTempTable();
    
    while (!feof($fp)) 
    {   
        $row = fgetcsv($fp);
        $this->processLine($row);
    }
    fclose($fp);
    
    $products_updates = $this->massUpdate();
    
    $this->findMissingFromDB();
    $this->findMissingFromCSV();
    
    return $products_updates;
}

Here is how ClassA starts out:

class AdvancedCsvFeed
{

    protected $vendor_prefix;
    protected $style_column;
    protected $price_column;
    protected $price_multiplier;
    protected $instock_column;
    
    protected $temp_table = 'csv_tmp';
    
    public function __construct($price_column, $style_column, $vendor_prefix = '', $price_multiplier = 1, $instock_column = 0)
    {
        $this->vendor_prefix = $vendor_prefix;
        $this->price_column = $price_column;
        $this->style_column = $style_column;
        $this->price_multiplier = $price_multiplier;
        $this->instock_column = $instock_column;
    }

... other functions

This is how classB starts out:

class MothersRingsAdvancedCsvFeed extends AdvancedCsvFeed
{
    private $syn10_price_column;
    private $gen10_price_column;
    private $syn14_price_column;
    private $gen14_price_column;
    
    public function __construct($syn10_price_column, $gen10_price_column, $syn14_price_column, $gen14_price_column, $style_column, $price_multiplier = 3)
    {
        $this->syn10_price_column = $syn10_price_column;
        $this->gen10_price_column = $gen10_price_column;
        $this->syn14_price_column = $syn14_price_column;
        $this->gen14_price_column = $gen14_price_column;
        $this->style_column = $style_column;
        $this->price_multiplier = $price_multiplier;
    }

... other functions

And this is how classB is initiated:

$s = new MothersRingsAdvancedCsvFeed(2,3,4,5,1);
echo $s->processPriceSheet('mothers_rings.csv');
Community
  • 1
  • 1
JD Isaacks
  • 56,088
  • 93
  • 276
  • 422
  • 2
    I don't know if there's a way around it, but I'm not surprised. The superclass shouldn't know anything about its children / their implementations of class methods. – Sam Dufel Jan 20 '11 at 19:14
  • @Sam Dufel, thats right, but from the way I understand OOP, the super class still doesn't. If I initiate a ClassA then it knows of no ClassB. However when I initiate a ClassB, any references to any members should first reference the overridden members defined in ClassB and only then fall back on members in ClassA if they are not overridden in classB. Otherwise what is the point of overriding anything? – JD Isaacks Jan 20 '11 at 19:23
  • So us the class definitions. The way you have it posted it will override the method... – ircmaxell Jan 20 '11 at 19:28
  • Hmm, I should have read your code more carefully - that first comment was based on what you said at the bottom. Never mind. – Sam Dufel Jan 20 '11 at 19:40
  • 1
    Add some debugging hooks to try to see which is being ran. You may be calling class A's `createTempTable` method from somewhere else. Add some backtraces and die() statements, or better yet use XDebug to trace the calls to try to see where the error is coming from – ircmaxell Jan 20 '11 at 19:56

1 Answers1

6

EDIT: I notice that the second class doesn't change the value for $temp_table. You may have a collision here: is it possible that some other AdvancedCsvFeed is creating the MySQL table csv_tmp first, and the call to $s->processPriceSheet fails to create the table because it already exists? Try having the constructor for MothersRingsAdvancedCsvFeed set

$this->temp_table = 'mothers_rings_csv_tmp';

ORIGINAL:

There must be something else at play here. Consider the following code:

<?php

class TestOne {
  public function foo() {
    echo "TestOne's foo.";
  }
  public function bar() {
    $this->foo();
    echo " TestOne's bar.";
  }
}
class testTwo extends TestOne {
  public function foo() {
    echo "TestTwo's foo.";
  }
}

$one = new TestOne();
$two = new TestTwo();

$one->foo();
$two->foo();

$one->bar();
$two->bar();

When I run the above, I get the output:

TestOne's foo.TestTwo's foo.TestOne's foo. TestOne's bar.TestTwo's foo. TestOne's bar.

So, there must be something else affecting your code. Can you share a bit more of the code, specifically what calls createTempTable()?

Josh
  • 10,961
  • 11
  • 65
  • 108
  • @Josh, ok well at least I know it is *supposed* to be doing what I am expecting, your example proves that. if I figure out whats going on I'll post an answer here. Thanks. – JD Isaacks Jan 20 '11 at 19:55
  • 1
    @Josh I do not understand why this made a difference but I added `protected $temp_table = 'mr_csv_tmp';` to class B definition and it fixed the issue. – JD Isaacks Jan 20 '11 at 20:00
  • I'm glad I could help. I'm guessing that somewhere, somehow, you're creating the `csv_tmp` table earlier. (Or maybe not deleting it?) – Josh Jan 20 '11 at 20:23
  • 1
    @Josh, your right, I wasn't deleting it. So the function WAS getting overridden but the MySQL table was already created and NOT getting overridden. Now it makes sense to me. Thanks. – JD Isaacks Jan 20 '11 at 20:39