views:

19

answers:

1

I am brushing up on my non-framework Object Oriented PHP and decided to do a test. Unfortunately, while I understand the concept of calling methods from a class, this particular test is slightly more complicated and I don't know what the terminology is for this particular type of situation is.

Test

Create a PHP class that parses (unknown number of) text files in a folder and allows to extract the total value of amount field from the file and get filenames of parsed files.

File Format:

The files are plain text csv files. Let's assume that the files contain a list of payments changed in the last N days. There are 2 different types of line:

  • Card payment collected - type = 1, date, order id, amount
  • Card payment rejected - type = 2, date, order id, reason, amount

Example file:

1,20090313,542,11.99
1,20090313,543,9.99
2,20090312,500,some reason, 2.99

Usage Example:

The usage could be something like this:

$parser = new Parser(...);
$files = $parser->getFiles();

foreach ($files as $file) {
    $filename = $file->getFileName();
    $amount_collected = $file->getTotalAmount(...); 
    $amount_rejected = $file->getTotalAmount(...);
}

My question is:

How can you do $file->method() when the class is called parser? I'm guessing you return an object from the getFiles method in the parser class, but how can you run methods with the returned object?

I attempted to Google this, but as I don't know the terminology for this situation I didn't find anything.

Any help is much appreciated, even if it's just what the terminology for this situation is.

+1  A: 

The returned object could be of class ParserFile with getFileName and getTotalAmount methods. This approach would be quite close to the Factory pattern, although it would be a good idea to make the getFiles method static, callable without the parser class itself.

class ParserFile {
    public function getFilename() { /* whatever */ }
    public function getTotalAmount() { /* whatever */ }
}

class Parser {
    public static function getFiles() {
        // loop through the available files
        // and store them in some $arr
        $arr[] = new ParserFile('filename1.txt');
        $arr[] = new ParserFile('filename2.txt');

        return $arr;
    }
}

$files = Parser::getFiles();
foreach ($files as $file) {
    $filename = $file->getFilename();
    $amount_collected = $file->getTotalAmount();
    $amount_rejected = $file->getTotalAmount();
}

Although I'm pretty sure this is not the best design. Another approach would be:

$parser = new Parser();
$files = $parser->getFiles();
foreach ($files as $file) {
    $filename = $parser->getFilename($file);
    $amount_collected = $parser->getTotalAmount($file);
    $amount_rejected = $parser->getTotalAmount($file);
}

So you'll get the array of files into your $files but when you want to parse these files you'll ask $parser to do it for you by passing the current $file to its methods.

There's no 100% correct solution I guess, just use what's best for you. If you then encounter problems, profile, benchmark and refactor.

Hope that helped. Cheers :)

P.S. Hope this isn't homework :D

kovshenin
It's not homework, but it's not something I want the complete answer to as I wanted to understand how/why you'd do what you've done in the first option which, bizarrely, isn't explained in the book. I agree that the second option is more sensible approach and was what I originally went with before noticing it wasn't still the parser class in the usage example.
PaulSkinner
I was kidding about homework Paul, although scanning your post diagonally did remind me of Google Code Jam (http://code.google.com/codejam) hehe. Glad to have helped! Cheers ~
kovshenin