Search code examples
phpstatic-methodsfactorypropelanti-patterns

Propel peer static classes: how to avoid to write duplicated code?


I have a few tables configured in Propel, with generated Peer static classes.

My problem is that I need to perform the same search operation on different but similar tables. Those tables have different Peer classes as it is how Propel works. This situation leads to duplicated code regarding to the queries that are performed on these tables.

I was wondering if there is some construct (avoiding the use of the function eval) that might help me in this case; I really would like to avoid writing duplicated code that performs the same exact calls on just different static Peer classes.

example code snippet from a (very long) method of a class I am writing:

$criteria = new Criteria();
$criteria->add(FoobarPeer::CONTRACTNR,$data['contractnr']);
$result = FoobarPeer::doSelect($criteria);
if(count($result) > 1){
  throw new FoobarException("status: more than one row with the specified contractnr.");
}
if(count($result) == 0){
  // no object with given contractnr. Create new one.
  $obj = $this->factory->createORM("foobar");
  $obj->setCreatedAt(time());
} else {
  // use and update existing object.
  $obj = $result[0];
}

As you can see I managed to write a factory method for the row object, but I could not find a way to do the same for static classes. In other words, I would like to have the access to the static classes dynamic and not in a way that is an ugly workaround.

Any ideas?

thanks :)


Solution

  • I'm not really sure I fully understand what you are asking, but here's a solution to what I think you are asking:

    function orm_for($type) {
        return strtolower($type);
    }
    
    function peer_for($type) {
        return ucfirst($type)."Peer";
    }
    
    function exception_for($type) {
        return ucfirst($type)."Exception";
    }
    
    function query($type, $data) {
        $peer = $peer_for($type);
        $exception = $exception_for($type);
        $obj = null;
        $criteria = new Criteria();
        $criteria->add($peer::CONTRACTNR, $data["contractnr"]);
        $result = $peer::doSelect($criteria);
        if(count($result) > 1) {
            throw new $exception("status: more than one row with the specified contractnr.");
        } else if(count($result) == 0) {
            $obj = $this->factory->createORM(orm_for($type));
            $obj->setCreatedAt(time());
        } else {
            $obj = $result[0];
        }
    }
    

    I think the code is self-explanatory. Let me know whether or not I interpreted your question correctly.

    A live example (just a POC) can be found here