SitePoint Sponsor

User Tag List

Results 1 to 6 of 6

Thread: Data Mapper

  1. #1
    SitePoint Wizard
    Join Date
    Oct 2001
    Posts
    2,686
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Data Mapper

    Hi,
    I'm working with the Modified Preorder Tree Traversal method and have a question/problem with the data mapper.

    My problem lies with the TreeTraversal:display() method. As you can see I access the resultset directly ($row['rgt'] and $row['title']) that has come from the data mapper. From what I have understood that is not the correct way to do it, even if it works.
    Should I populate the list in the Data Mapper?
    I'm looking for suggestions on how to not access the data using the db colum names.

    If I haven't described the problem properly, hopefully the code will help:
    File: category.php
    PHP Code:
    require_once LIB 'TreeTraversal.class.php';
    require_once 
    LIB 'TreeTraversalMapper.class.php';
     
    $tree =& new TreeTraversal(new TreeTraversalMapper($db));
    $tree->display() 
    File: TreeTraversal.class.php
    PHP Code:
    class TreeTraversal {

        var 
    $mapper;

        function 
    TreeTraversal($mapper) {
            
    $this->mapper =& $mapper;
        }

        function 
    display() {
            
    $right = array();

            
    $it =& $this->mapper->getTree();
            for (
    $it->reset(); $it->isValid(); $it->next()) {
                
    $row $it->getCurrent();
            
                if(
    count($right) > 0) {
                    
    // On next line I access $row['rgt']
                    
    while($right[count($right)-1] < $row['rgt']) {
                        
    array_pop($right);
                    }
                }
                
    // On next line I access $row['title']
                
    echo "\n<br />" str_repeat("&gt; &nbsp;"count($right)) . $row['title']; 

                
    $right[] = $row['rgt']; 
            }
        }

    File: TreeTraversalMapper.class.php
    PHP Code:
    require_once ECLIPSE_ROOT 'QueryIterator.php';

    class 
    TreeTraversalMapper {
        
        var 
    $db;
        
        function 
    TreeTraversalMapper($db) {
            
    $this->db =& $db;
        }
        
        
    // Public    
        
    function getTree($rootid=1) {
            
    $row $this->getLftRgt($rootid);
            
            
    $sql 'SELECT title, lft, rgt 
                      FROM category 
                     WHERE lft 
                   BETWEEN ' 
    $row['lft'] . 
                       AND ' 
    $row['rgt'] . 
                  ORDER BY lft ASC'
    ;
            
            return new 
    QueryIterator($this->db->query($sql));
        }

        
    // Private
        
    function getLftRgt($rootid) {
            
    $sql "SELECT lft, rgt 
                      FROM category 
                     WHERE id = 
    $rootid";
            
    $result =& $this->db->query($sql);
            return 
    $result->getRow(0);
        }

    As you can see I use the Eclipse library.

    Any suggestions are greatly appreciated.

    -Helge

  2. #2
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by Helge
    Should I populate the list in the Data Mapper?
    What are your worries here? The only problem I can see is if you change a column name in the database, then you have to change it again in all the display classes that use it. If it's an in-house project then this may be less hassle than the extra mapping code to isolate it. You would probably get away with aliases in the SQL queries for a while anyway without changing any code, at least for reporting.

    The fun begins with updates. Once you have coded stuff into your web pages/controllers/displays you will have fixed your schema unless you add some isolation. I cannot remember how Eclipse treats updates. All you probably need is for updates to also go through the mapper. That way the mapper can keep all of the renaming information, which is probably a simple hash.

    So as preparation I would make the mapper the central point for all DB work for that type of data. That way you won't have to change any client code later. You have probably done this aready, so you might already be safe. Then implement the rest when you need it.

    You're call .

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  3. #3
    SitePoint Addict
    Join Date
    May 2003
    Location
    Calgary, Alberta, Canada
    Posts
    275
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey,

    Im one of those people who hate to see column names in the code like that. Ive been burned before so I usually try to avoid that kind of thing now. That being said its not really that bad .

    This may give you some ideas:
    PHP Code:
    class TreeTraversal {
        var 
    $tree;
        function 
    TreeTraversal($tree) {
            
    $this->tree =& $tree;
        }
        function 
    display() {
            
    $right = array();
            for (
    $this->tree->reset(); $this->tree->isValid(); $this->tree->next()) {
                
    $category $this->tree->getCurrent();        
                if(
    count($right) > 0) {
                    while(
    $right[count($right)-1] < $category->getRight()) {
                        
    array_pop($right);
                    }
                }
                echo 
    "\n<br />" str_repeat("&gt; &nbsp;"count($right)) . $category->getTitle();
                
    $right[] = $category->getRight();
            }
        }

    class 
    CategoryMapper {
        var 
    $db;
        function 
    TreeTraversalMapper($db) {$this->db =& $db;}
        function 
    getTree($id=1) {
            
    $category $this->findLftRgtById($id);
            
    $sql 'SELECT title, lft, rgt
                      FROM category
                     WHERE lft
                   BETWEEN ' 
    $category->getLeft() . '
                       AND ' 
    $category->getRight() . '
                  ORDER BY lft ASC'
    ;
            
    $recordSet $this->db->query($sql);
            
    $queryIterator = new QueryIterator($recordSet);
            return new 
    DomainObjectIterator($this$queryIterator);
        }
        function 
    findLftRgtById($id) {
            
    $sql "SELECT lft, rgt
                      FROM category
                     WHERE id = " 
    . (int)$id;
            
    $recordSet =& $this->db->query($sql);
            return 
    $this->load($recordSet->getRow(0));
        }
        function 
    load($row) {
            
    $result = new Category();
            
    $result->setTitle($row['title']);
            
    $result->setLeft($row['lft']);
            
    $result->setRight($row['rgt']);
            return 
    $result;
        }
    }
    class 
    Category {
        var 
    $title;
        var 
    $right;
        var 
    $left;
        
    //getters
        //settters
    }
    class 
    DomainObjectIterator {
        function 
    DomainObjectIterator($mapper$queryIterator) {
            
    $this->queryIterator $queryIterator;
            
    $this->mapper $mapper;
        }
        function 
    reset() {
            return 
    $this->queryIterator->reset();
        }
        function 
    isValid() {
            return 
    $this->queryIterator->isValid();
        }
        function 
    next() {
            return 
    $this->queryIterator->next();
        }
        function 
    getCurrent() {
            return 
    $this->mapper->load($this->queryIterator->getCurrent());
        }


  4. #4
    SitePoint Wizard
    Join Date
    Oct 2001
    Posts
    2,686
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you both Marcus and Brenden!

    Quote Originally Posted by lastcraft
    What are your worries here?
    I was under the impression that I should not access the those directly. But I see I got this wrong.
    Quote Originally Posted by lastcraft
    So as preparation I would make the mapper the central point for all DB work for that type of data. That way you won't have to change any client code later. You have probably done this aready, so you might already be safe.
    Yes I have done so. Good to know I'm on the right track.

    I've pretty much used what Brenden suggested and it's working.
    Thank you both again!

  5. #5
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by Helge
    I was under the impression that I should not access the those directly. But I see I got this wrong.Yes I have done so. Good to know I'm on the right track.
    You are absolutely right to be suspicious, and I think you're instincts are quite correct. If you were shipping it as a library I think a developer would be non-plussed to find that they cannot map from one naming scheme to another, as that is a possible scenario. If you have complete control over the database though, the extra purity may not be worth the extra investment. It's a difficult decision.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  6. #6
    SitePoint Wizard
    Join Date
    Oct 2001
    Posts
    2,686
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's only me that will ever use this so I have complete control, but I went with "total separation" cause it will be a good practise as I'm starting to do some coding again and I see I've a lot to catch up on.


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
  •