SitePoint Sponsor

User Tag List

Page 2 of 3 FirstFirst 123 LastLast
Results 26 to 50 of 51
  1. #26
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    GoF (Group of Four)
    Mandatory error reporting: It's Gang of Four.

    Nice idea, Herr Dr. Will contribute some later too.

  2. #27
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Opps, yer your right it's Gang of Four... Did I post that?? ... I can't belive that, how embarrassing

    And I and other would indeed welcome your contributions, so please do.

  3. #28
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Having seen you around here for long and always valueing your contributions I too could not believe you posted that.

    Back on topic now, though.

  4. #29
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Perhaps the next great patterns book will come from the Gaggle of Four
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  5. #30
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice one, Jason.

    I cannot believe I haven't read GoF yet..only PoEAA. But just got an email from Amazon that GoF has been shipped. Should be here soonish.

  6. #31
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    *sigh*

  7. #32
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    Ireland
    Posts
    349
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It would be good if a sub-forum could be requested on this forum, where we could have each PHP Pattern in their own threads. That way discussions could continue within the forum and everything would be well organised and not all muddled up: and it would be easy to link to if questions came up during forum conversations.

    Just an idea.

  8. #33
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @Ryan: Top notch idea.

  9. #34
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is a Dynamic Proxy implementation for PHP5 (could also be the basis for a Decorator, since the two patterns are structually identical):

    PHP Code:
    class GenericProxy {
        protected 
    $subject;
        public function 
    __construct($subject) {
            
    $this->subject $subject;
        }
        public function 
    __call($method$args) {
            return 
    call_user_func_array(
                array(
    $this->subject$method),
                
    $args);
        }


    Edit:

    Had a request for usage

    Say you have a class:
    PHP Code:
    class SomeClass {
      public function 
    __construct() {}
      public function 
    someMethodOne() {}
      public function 
    someMethodTwo() {}
      
    //...
      
    public function someMethodTwenty() {}

    which you want to Proxy/Decorate. Most of the methods you want to pass through, but someMethodTwo() you want to do something with. You could then do:
    PHP Code:
    class SomeClassProxy extends GenericProxy {
      public function 
    someMethodTwo($foo) {
        return 
    strtoupper($this->subject->someMethodTwo($foo));
      }

    Then you can do:
    PHP Code:
    $foo = new SomeClassProxy(new SomeClass);
    $foo->someMethodTwenty(); 
    and the call will automatically be proxied to the SomeClass instantance stored in SomeClassProxy::$subject.

    A more typical example for a Proxy class might be to have some kind of an access control object as part of the Proxy construction. You could then write a Model class without worrying about whether a user is authorized to do any of the actions the Model provides. Whenever you use the Model, you could then use it through a Proxy object which would automatically check if the user is authorized before providing access to the proxied Model class.

    HTH
    Last edited by sweatje; Apr 16, 2005 at 12:24.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  10. #35
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Pattern: Active Record

    If the classes of your domain model and the structures of your sql tables match closely (which they often do), then you can take that to your advantage. An Active Record is an object - a part of the domain model - that is responsible for itself whether it is inserted into the db, deleted or updated. So unlike you have a central DataMapper approach for inserting/updating and deleting data, you can save some code, when you do it with the Active Record.

    An ActiveRecord is typicially responsible for the following:
    * Construct an instance of the Active REcord class from a SQL result set row
    * Construct a new instance for later insertion into the table
    * Either static finder methods or centralized Finder classes are used for fetching SQL result set..the Active Record is mostly used only for modifying data. Whatever way you take, the fetching mechanisms should return ActiveRecord objects.
    * Update the Database and insert into it the data from the Active Record (every attribute becomes one column in the SQL row)
    * Get and set the fields

    I think this pattern is pretty straight-forward. I can write some example code, though, if requested.

  11. #36
    SitePoint Evangelist Ian R. Gordon's Avatar
    Join Date
    Feb 2004
    Location
    New York
    Posts
    474
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Write some sample code please.
    Ian Gordon
    CSS / XHTML / PHP Programmer
    http://www.iangordon.us

  12. #37
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Active Record
    -------------

    PHP Code:
    //...
    $person = new PersonObj;
    $person -> id 1;
    $person -> firstname 'Dr';
    $person -> lastname 'Livingston';
    $person -> insert();
    //...
    class PersonObj {
    private 
    $db;

    public 
    $id;
    public 
    $firstname;
    public 
    $lastname;

    public function 
    __construct() {
    try {
    $this -> db MySqlDatabase::getInstance();
    } catch( 
    SqlException $e ) {
    die( 
    $e -> getMessage() );
    }
    }

    public function 
    insert() {
    $stmt $this -> db -> createStatment'insert into persons set id = ?, firstname = ?, lastname = ?' );
    $stmt -> setInteger1$this -> id );
    $stmt -> setParameter2$this -> firstname );
    $stmt -> setParameter3$this -> lastname );
    $rslt $stmt -> execute();
    //... validation etc
    }

    public function 
    update() { }
    public function 
    delete() { }


  13. #38
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is a unit test case for an ActiveRecord representing bookmarks. You should be able to see usage from the test, and build you own implementation if you wanted

    It uses ADOdb as a database access layer, and DB::conn() is a static function to return an ADOdb connection.

    PHP Code:
    define('BOOKMARK_TABLE_DDL', <<<EOS
    CREATE TABLE `bookmark` (
        `id` INT NOT NULL AUTO_INCREMENT ,
        `url` VARCHAR( 255 ) NOT NULL ,
        `name` VARCHAR( 255 ) NOT NULL ,
        `description` MEDIUMTEXT,
        `tag` VARCHAR( 50 ) ,
        `created` DATETIME NOT NULL ,
        `updated` DATETIME NOT NULL ,
    PRIMARY KEY ( `id` )
    )
    EOS
    );

    Mock::generate('ADOConnection');

    class 
    ActiveRecordTestCase extends UnitTestCase {
        protected 
    $conn;
        function 
    __construct($name='') {
            
    $this->UnitTestCase($name);
            
    $this->conn DB::conn();
        }
        
        
    // no test interference
        
    function setup() {
            
    $this->conn->execute('drop table bookmark');
            
    $this->conn->execute(BOOKMARK_TABLE_DDL);
        }
        
        function 
    testSetupLeavesTableEmptyWithCorrectStructure() {
            
    $rs $this->conn->execute('select * from bookmark');
            
    $this->assertIsA($rs'ADORecordSet');
            
    $this->assertEqual(0,$rs->recordCount());
            foreach(array(
                
    'id',
                
    'url',
                
    'name',
                
    'description',
                
    'tag',
                
    'created',
                
    'updated') as $i => $name) {
                
    $this->assertEqual($name$rs->fetchField($i)->name);
            }
        }
        function 
    testNew() {
            
    $link = new Bookmark;
            
            
    $link->url 'http://simpletest.org/';
            
    $link->name 'SimpleTest';
            
    $link->description 'SimpleTest project homepage';
            
    $link->tag 'testing';
            
            
    $link->save();
            
    $this->assertEqual(1$link->getId());
            
            
    // fetch the table as an array of hashes
            
    $rs $this->conn->getAll('select * from bookmark');
            
    $this->assertEqual(1count($rs), 'returned 1 row');
            foreach(array(
    'url''name''description''tag') as $key) {
                
    $this->assertEqual($link->$key$rs[0][$key]);
            }
        }
        function 
    testAdd() {
            
    $this->add('http://php.net''PHP''PHP Language Homepage''php');
            
    $this->add('http://phparch.com''php|architect''php|arch site''php');
            
    $rs $this->conn->execute('select * from bookmark');
            
    $this->assertEqual(2,$rs->recordCount());
            
    $this->assertEqual(2,$this->conn->Insert_ID());
        }
        
        function 
    testDbFailure() {
            
    $conn = new MockADOConnection($this);
            
    $conn->expectOnce('execute', array('*','*'));
            
    $conn->setReturnValue('execute',false);
            
    $conn->expectOnce('errorMsg');
            
    $conn->setReturnValue('errorMsg''The database has exploded!!!!');
            
            
    $link = new Bookmark(1,$conn);
            
    $this->assertErrorPattern('/exploded/i');
            
            
    $conn->tally();
        }

        function 
    testAddReturnsBookmark() {
            
    $link $this->add(
                
    'http://blog.casey-sweat.us/',
                
    'My Blog',
                
    'Where I write about stuff',
                
    'php');
            
    $this->assertIsA($link'Bookmark');
            
    $this->assertWantedPattern('/sweat/i'$link->url);
            
    $this->assertEqual('My Blog'$link->name);
            
    $this->assertWantedPattern('/write/i'$link->description);
            
    $this->assertTrue((time()-strtotime($link->created))<2);
            
    $this->assertEqual($link->created$link->updated);
        }

        function 
    testGetId() {
            
    $this->add('http://php.net''PHP'
                
    'PHP Language Homepage''php');
            
    // second bookmark, id=2
            
    $link $this->add('http://phparch.com'
                
    'php|architect''php|arch site''php');
            
            
    $this->assertEqual(2$link->getId());
            
            
    //how would you check it by hand? do it in the test!
            
    $alt_test $this->conn->getOne(
                
    "select id from bookmark where url = 'http://phparch.com'");
            
    $this->assertEqual(2$alt_test);
            
    //alternatively
            
    $this->assertEqual($link->getId(), $alt_test);
        }
        
        function 
    testCreateById() {
            
    $link $this->add(
                
    'http://blog.casey-sweat.us/',
                
    'My Blog',
                
    'Where I write about stuff',
                
    'php');
            
    $this->assertEqual(1$link->getId());
            
            
    $link2 = new Bookmark(1);
            
    $this->assertIsA($link2'Bookmark');
            
    $this->assertEqual($link$link2);
        }

        function 
    testFindByUrl() {
            
    $this->add('http://blog.casey-sweat.us/''My Blog',
                
    'Where I write about stuff''php');
            
    $this->add('http://php.net''PHP'
                
    'PHP Language Homepage''php');
            
    $this->add('http://phparch.com''php|architect'
                
    'php|arch site''php');
                
            
    $result Bookmark::findByUrl('php');
            
            
    $this->assertIsA($result'array');
            
    $this->assertEqual(2count($result));
            
    $this->assertEqual(2$result[0]->getId());
            
    $this->assertEqual('php|architect'$result[1]->name);
        }


        function 
    testSave() {
            
    $link $this->add(
                
    'http://blog.casey-sweat.us/',
                
    'My Blog',
                
    'Where I write about stuff',
                
    'php');
            
    sleep(2);
            
    $link->description 'Where I write about PHP, Linux and other stuff';
            
    $link->save();
            
            
    $link2 Bookmark::findById($link->getId());
            
    $this->assertEqual($link->getId(), $link2->getId());
            
    $this->assertNotEqual($link2->created$link2->updated);
            
    $this->assertTrue(strtotime($link2->updated)>strtotime($link2->created));
            
    $this->assertEqual($link->updated$link2->updated);
        }
        
        function 
    add($url$name$description$tag) {
            
    $link = new Bookmark;
            
            
    $link->url $url;
            
    $link->name $name;
            
    $link->description $description;
            
    $link->tag $tag;
            
            
    $link->save();
            return 
    $link;
        }



  14. #39
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    96
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Any more patterns?

  15. #40
    SitePoint Evangelist Andrewaclt's Avatar
    Join Date
    Dec 2003
    Location
    Raleigh, NC
    Posts
    535
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Dunno if you noticed, but this thread is almost two years old

    Anyway, I've found http://www.phparch.com/shop_product.php?itemid=96 very good. If you want free examples, then maybe else can give you a link...

  16. #41
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > Any more patterns?

    No, this thread has fallen by the way side by the looks of things; At the time it was a good idea, as fewer people really knew enough about patterns, plus a couple of years ago there was little documentation in regards to PHP and patterns.

    That isn't the case today, where there are more plentiful resources; Did you have any particular patterns in mind that you wanted to know more about?

  17. #42
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    96
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank, I have a questions regarding Active Record & Table Data Gateway, So this is what I understand: the Active Record pattern deals with a single record in a table and the Table Data Gateway deals with multiple records. How can I use them together effectively? For example, A User class abstracts the user table and provides some domain logic. If I want to retrieve multiple records at a time, how can I get a multiple records of User object so that I can make use of the domain logic.
    Is this how it works?

    PHP Code:
    class User {
      public function 
    __construct($user_id) {
         
      }
    }

    class 
    UserGateway() {
      public function 
    findbylastname($lastname) {
         
    //sql to get all the user id
         
    while(looping the sql result) {
           
    $User[] = new User(id);
         }  
         return 
    $User;
      }


  18. #43
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by libranet View Post
    Thank, I have a questions regarding Active Record & Table Data Gateway, So this is what I understand: the Active Record pattern deals with a single record in a table and the Table Data Gateway deals with multiple records. How can I use them together effectively? For example, A User class abstracts the user table and provides some domain logic. If I want to retrieve multiple records at a time, how can I get a multiple records of User object so that I can make use of the domain logic.
    Is this how it works?
    You can have a domain object which essentially equates to a database row with both patterns, the key distinction is where the actual logic which accesses the database itself resides. In the ActiveRecord, this logic is contained in the row level object itself, whereas the TableDataGateway has the database logic and the can return collections of (or individual) domain objects, which still can have business logic, but would need to ask the TableDataGateway to persist any changes to themselves in the database.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  19. #44
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > but would need to ask the TableDataGateway to persist any changes to themselves in the
    > database.

    So, with the Active Record you would do this,

    PHP Code:
    // ...
    $record -> save(); 
    Whereas, with Jason's TableDataGateway (from my understanding of course) you would do this instead,

    PHP Code:
    // ...
    $gateway -> save$record ); 
    Where the Gateway in question would have the knowledge to know how to save the record for example. Is this what you had in mind yourself?

    Personally I would one or the other but not both at the same time, as I believe therefore if you used the Gateway option, the Active Record (from my viewpoint) would be bloated, having to carry around additional responsibilities, which would be taken care of anyways by the Gateway.

    But that's just my thoughts; Your milage may vary

  20. #45
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Dr. L is correct. One additional possibility is to have the model retain knowledge of it's gateway:

    PHP Code:
    class Model {
      protected 
    $gateway;
      function 
    __construct($gateway) {
        
    $this->gateway $gateway;
        
    //...
      
    }
      function 
    save() {
        
    $this->gateway->save($this);
      }
      
    //...

    the you can have the record level object have the API of the ActiveRecord, without the additional responsibilities of knowing how to interact with the database.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  21. #46
    SitePoint Evangelist jplush76's Avatar
    Join Date
    Nov 2003
    Location
    Los Angeles, CA
    Posts
    460
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    we gonna wiki this or what?
    My-Bic - Easiest AJAX/PHP Framework Around
    Now Debug PHP scripts with Firebug!

  22. #47
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    96
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, Jason & Dr. L

    Dr. L, take my User class as example again, if this class defines some business logic like: is_vip_user(), get_estimated_income(), wouldn't you want to reuse this code in the active record instead of redefining them in the gateway.

  23. #48
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jplush76 View Post
    we gonna wiki this or what?
    With http://www.phppatterns.com/ getting a bit long in the tooth, http://www.patternsforphp.com/wiki/Main_Page was another attempt to start up a pattern wiki. Looks like perhaps it may have stalled out last fall.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  24. #49
    SitePoint Evangelist jplush76's Avatar
    Join Date
    Nov 2003
    Location
    Los Angeles, CA
    Posts
    460
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    yea , none have been updated in quite a while.
    My-Bic - Easiest AJAX/PHP Framework Around
    Now Debug PHP scripts with Firebug!

  25. #50
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > wouldn't you want to reuse this code in the active record instead of redefining them in the
    > gateway.

    Yes. The logic in this case is in regards to that one row of data that is likely to be unique; The emphasis is with the data therefore and belongs with that row of data. From my point of view, this would be the case where you have that uniqueness so any behaviour you have acts on that row of data only.

    If there is common, shared values then it belongs elsewhere...


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •