Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

PHP OOP Question

Name: Anonymous 2010-01-05 23:16

* For the record, I agree that PHP isn't the best. Sucks, even.

I have an OOP (object-oriented problem) and I'm wondering if either:
a) there's a solution
b) I'm worrying about nothing

I'm working on a ticketing system with MySQL. I have a child table that is one-to-one that represents ticket categories. I use it to resolve ticket category ids into English names.

I'm using my own sorta-ORM approach as I don't want to use a library. For Ticket objects, it made more sense to me to use a prepared PDO statement and execute it every time I instantiate, since it's lazy and the number of Tickets that will need to be instantiated changes depending on the page. Here's the class:

class TicketORM extends TicketBase
{
    private static $stmt_select;
   
    function __construct($id)
    {
        if(!isset(self::$stmt_select)) {
            $dbh = $this->getConnection();
            try {
                self::$stmt_select = $dbh->prepare(
                    'SELECT
                       ...
                    FROM
                        tickets
                        AS t
                    LEFT JOIN
                        ticket_categories
                        AS tc
                        ON t.category_id = tc.id
                    WHERE
                        t.id = ?');
                //...
            }
            catch (PDOException $e) {
                //...
            }
        }
       
        self::$stmt_select->execute( array($id) );
        $result = self::$stmt_select->fetch();
       
        $this->id = $id
        $this->created = strtotime($result['created']);
        //...
    }
    //...
}


However, with the simple category name resolution table, this approach seems like a lot of unnecessary overhead, when I could get all that shit with a simple SELECT * FROM ticket_categories.

So what's the problem?

Well, I want to take advantage of Type Hinting when I need to insert. I use a different class for creating new tickets:

class Ticket extends TicketBase
{
    private static $stmt_insert;
   
    function __construct($subject, TicketCategory $category, Client $client)
    {  
        $dbh = $this->getConnection();
        self::$stmt_insert = $dbh->prepare(/* ... */);
        $this->category =  //?!?!?!?
        //...
    }
    //...
}


I want to make sure that the value passed as $category is valid, in the most straightforward, db efficient, and Don't Repeat Yourself way I can.

What would you do, /prog/? Aside from reading SICP, of course.

(In my next post, I'll describe what I have at the moment, and some ideas.)

Name: Anonymous 2010-01-05 23:36

This is far too much like my day job. Sorry, I have zero interest in solving this problem. At least it's one of the more on-topic threads here though.

Name: OP 2010-01-05 23:40

Oh, I forgot to mention. The problem I'm running into with simply making a TicketCategory class right now is that I'm not sure how to go about filling it in with the right data. My goal is to make sure that $category is valid. So if TicketCategory is a class that can be instantiated by the user, then it needs to have guaranteed valid information (i.e. not provided by the user, but from the db directly).


Here's what I've already written to deal with the problem, a static class called TicketCategories.

// I'm not even sure that I agree with this implementation.
class TicketCategories extends DBO
{
    private static $_byId = array();
    private static $_byName = array(); // faster than using array funcs every getName()
   
    private static function _init()
    {
        try {
            $dbh = $this->getConnection();
            self::$_byId = $dbh->query('SELECT id, name FROM ticket_categories')
                           ->fetch(PDO::FETCH_KEY_PAIR);
            self::$_byName = array_flip(self::$_byId);
        } catch(PDOException $e) {
            die($e->getMessage());
        }
    }
    private static function _get($array, $search)
    {
        if(empty($array)) {
            self::_init();
        }
       
        if(@isset($array[$search])) {
            return $array[$search];
        } else {
            throw new OutOfBoundsException('TicketCategory '.$search.' does not exist.');
            return FALSE;
        }
    }
   
    static function getNameFromId($name)
    {
        return self::_get(self::$_byName, $name);
    }
    static function getIdFromName($id)
    {
        return self::_get(self::$_byId, $id);
    }
    static function getIterator()
    {
        return ArrayIterator(self::$_byId);
    }
}


So, the user would use TicketCategories to resolve names and ids.

It doesn't solve my PHP Type Hinting problem, but I could use it to assert the $category being passed. That said, it seems a little redundant if I expect the user of this class to have already called TicketCategories::getIdFromName('General') or by iterating using TicketCategories::getIterator() to get a proper $id in the first place.

I could write that TicketCategory class and pass it new TicketCategory instances, and keep static array that holds on to all the possibilities so that I'm not repeating myself. But that doesn't solve the problem of the user being able to instantiate TicketCategory.

There's also the option of keeping static ticket category definitions in the Ticket class. Maybe with something like setCategory() and const definitions or something. (But I'm hesitant to start writing consts by hand, since that's what the table is for in the first place.)

Basically, I'm looking for something similar to a C enum, but not if it's going to be way more overhead than necessary since I'm working with a db and I'm in PHP. I could use an enum in the MySQL table, but those make me uncomfortable here, because they seem less extensible in the event that we need to add another category of ticket.

I looked into some clever PHP Reflection classes, but for a simple problem, it seems like a ridiculous solution.

Aaaaand that's where I am at now, which brings me to my point about being concerned over nothing. Should I just make a TicketCategory class that anyone can instantiate because it doesn't matter since they probably wouldn't anyway? Or should I get over the redundancy and use TicketCategories::getNameById($category) to check in the constructor?*

______________

I am aware that the third possibility is that I should kill myself for being so anal about a dumb problem, in PHP no less. It's just that other people will be using this code, and I care about my fellow programmers.

Name: Anonymous 2010-01-05 23:52

>>2
I understand completely. This is for my day job too. Unfortunately, no one there is available for help on this at the moment due to holiday.

And besides, /prog/ is more expert than us anyway.

Name: Anonymous 2010-01-06 5:36

one of the more on-topic threads here though.
HAHAHAHGETOUT

Name: Anonymous 2010-01-06 11:55

>>5
<meta name="description" content="/prog/ is 4chan's BBS for computer programming."/>
<meta name="keywords" content="bbs,computers,software,programming,
php,perl,html,sql,python,ruby"/>

Name: Anonymous 2010-01-06 15:12

>>6
Based on the fact that it doesn't mention Lisp or Haskell, this "keywords" thing is clearly of no use to anyone!

Name: Anonymous 2010-01-06 15:14

>>5
GET OUT MY LAMBDA KNIGHTS NAO

Name: Anonymous 2010-01-06 15:27

>>8
Lain.

Name: Anonymous 2010-01-06 16:00

>>7
that is because on uni kids and uni profs use haskall and lisp.

the other 99.999% of the world has no time to deal with cute academic curiosities

Name: Anonymous 2010-01-06 16:09

>>10
Right, keep telling yourself that.

Name: sage 2010-01-06 16:14

>>11
I'm sorry that the truth hurts so much, bro.

Name: Anonymous 2010-01-06 16:22

DON'T HELP HIM!

Name: Anonymous 2010-01-06 16:23

>>12
I realise this is a troll, but haven't we had the ``Real World Lisp'' thread several times already?

Name: Anonymous 2010-01-06 17:27

>>14
I don't know that there are any threads about it specifically, but the question comes up fairly often.  It's always the same: the sane people say that LISP and HASKAL are ok for solving well-defined math problems, but not for writing applications, and therefore useless to the working programmer.  Then you say But it's been used to solve these math problems!!, and we're like ``Well, duh.''.  And that's pretty much it.

Name: Anonymous 2010-01-06 17:35

>>15
I don't believe that any of the previous examples were about math problems. Off the top of my head, Square Enix used Scheme for scripting a graphics engine they wrote, and ITA uses Common Lisp for Airline Software. NASA used Lisp, at least at the JPL, and you can have your pick of many more.

Name: OP 2010-01-06 22:52

OP here. Just wanted to say that I ended up completely refactoring this such that I now have only one Ticket class. TicketORM, TicketCategory, and TicketBase are completely gone.

And after I posted this I realized that it wasn't a go-to-/prog/ kind of problem, but by then, unfortunately, it was too late. Sorry!

Name: Anonymous 2010-01-07 0:52

>>17
You can apologize by casting nukeandpave.scm on this thread, along with your job

Name: Anonymous 2010-01-07 1:18

>>17
Hi, been a long time lurker on this board.. but I feel I have to speak out at this moment.
 
Never on The 4Chan Programming board have I seen someone be so horrible and with no provocation, utterly appalling.
 
That was uncalled for and just plain rude.

Name: Anonymous 2010-01-07 1:21

>>16
Naughty Dog uses a derivative of TinyScheme for a scripting engine.

Name: Anonymous 2010-01-07 1:36

>>20
They did, though I couldn't say for sure if they still do.

Name: Anonymous 2010-01-07 2:05

>>21
I have Something Gregory's textbook on game engine design - it's still currently in the Uncharted codebase.

Name: Anonymous 2010-01-07 5:11

Name: Anonymous 2010-01-07 8:07

>>2,4
Enjoy your job.

Name: Anonymous 2010-12-06 9:05

Back to /b/, ``GNAA Faggot''

Name: Anonymous 2010-12-25 17:48

Don't change these.
Name: Email:
Entire Thread Thread List