[RESOLVED] OOP & Dependencies
Results 1 to 9 of 9

Thread: [RESOLVED] OOP & Dependencies

  1. #1
    Beware: Crazy Scientist leatherback's Avatar
    Join Date
    Mar 2002
    Location
    Small border town between Netherlands and Germany
    Posts
    5,395

    resolved [RESOLVED] OOP & Dependencies

    I have only recently restarted programming moving from PHP4.* into 5.* and with this started working on OOP so please be gentle

    I am trying to get my head around separating classes and making sure code becomes independent.

    So, when I have a class institute that gets information from a database, I would have to inject institute with an instance of the database class, right?:

    e.g.

    PHP Code:
    $dbh = new database();
    $a = new institute();

    $a->SetDBI($dbh); 
    In database class, I have a method pulling one record from the database, and is fed with the table table, the ID-coloum and the actual ID of the record to be pulled.

    Now, say I want one method in Institute that gets one institute. To me it would make sense to then use the database class method getone():

    PHP Code:
    public function GetInstitute()
        {
        
    $record $this->dbi->GetOneRecord('table''coloum'$this->id);
        } 
    Is this the right way of going about it? It feel that I am still building dependencies between classes this way?
    It feels that GetInstitute should not know anything about the database it is using. However, at some point a class has to know something about the outside world? Or would one create a class that gives the name of the sortcolom for specific tables, and table names to specific classes?

    How is this done in practice? I find a lot of theory, and some CI classes; which feel like way to complex. Is there a middle ground for small, one-coder projects?

    Kind-a stuck on the best approach
    Php 4.* to 5.*. A small step for programmers. But a leap for me!

  2. #2
    High Energy Magic Dept. NogDog's Avatar
    Join Date
    Aug 2006
    Location
    Ankh-Morpork
    Posts
    13,943
    I would probably make the database object a parameter of Institute::__construct(). That way (a) you have to pass it in or you get an exception, and (b) it becomes part of the Institute class's prototype, making the dependency immediately clear to anyone trying to use it. Also, you can use type-hinting to make it explicit what's expected:
    PHP Code:
    class Institute
    {
      private 
    $dbi;
      public function 
    __construct(PDO $pdo// change type-hint if not PDO
      
    {
        
    $this->dbi $pdo;
      }

    PHP Code:
    $dbh = new Database();
    $inst = new Institute($dbh); 
    Please give us a simple answer, so that we don't have to think, because if we think, we might find answers that don't fit the way we want the world to be." ~ from Nation, by Terry Pratchett

    "But the main reason that any programmer learning any new language thinks the new language is SO much better than the old one is because he’s a better programmer now!" ~ http://www.oreillynet.com/ruby/blog/...ck_to_p_1.html


    eBookworm.us

  3. #3
    Beware: Crazy Scientist leatherback's Avatar
    Join Date
    Mar 2002
    Location
    Small border town between Netherlands and Germany
    Posts
    5,395
    Hi,

    thx for that. Will try.

    How about this:

    PHP Code:
    $record $this->dbi->GetOneRecord('table''coloum'$this->id); 
    Would it be better to define a class say, DatabaseArchitecture that can: getTableName("Institutes"), GetAllColumNames($table), GetColumNames($NeededColumsArray, $table), GetIDColum($table) or would that make the application needlesly complex?
    Php 4.* to 5.*. A small step for programmers. But a leap for me!

  4. #4
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,885
    As well as NogDog's observations; (c) It ensures that if you have an Institute object then it is a functioning Institute object, with one less step to take before it can be used (a step which might be missed by accident, leading to an error much later on).
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

  5. #5
    Beware: Crazy Scientist leatherback's Avatar
    Join Date
    Mar 2002
    Location
    Small border town between Netherlands and Germany
    Posts
    5,395
    Thx Weedpacket.

    Any thoughts on the second part? How to deal with table information?
    Php 4.* to 5.*. A small step for programmers. But a leap for me!

  6. #6
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    Quote Originally Posted by leatherback View Post
    Is this the right way of going about it? It feel that I am still building dependencies between classes this way?
    It feels that GetInstitute should not know anything about the database it is using. However, at some point a class has to know something about the outside world? Or would one create a class that gives the name of the sortcolom for specific tables, and table names to specific classes?
    Classes only need to know enough about the "outside world" to interact with it. An API: a set of methods that do things and are intended to be used to interact with other objects.

    You're right that getInstitute shouldn't know anything about the database - things like the table name or column name should not be there.

    All that getInstitute needs to know is:
    • there is a method called GetOneRecord.
    • the GetOneRecord method needs a record id.
    • the GetOneRecord method returns a record that matches the given id.


    It doesn't matter at all how GetOneRecord gets the record. Could be from a database, could be hard-coded in the method definition. Could be made up on the fly. As long as getInstitute know how to use the method, how it works is not important.

    edit

    PHP Code:
    <?php

    class institute{

        public function 
    __constructrecordStorage $storage ){
            
    $this->storage $storage;
            
    $this->id 1;
        }

        public function 
    getInstitute(){
            
    $record $this->storage->GetOneRecord$this->id );
            
    //  . . . 
        
    }
    }

    // (for example)
    class recordStorage extends PDO{

        
    //  . . .

        
    public function GetOneRecord$id ){
            
    $result $this->query"SELECT ... WHERE `id`=$id", );
            
    //  . . .
        
    }
    }
    To clarify, GetOneRecord does not return a PDO result set. It returns a regular PHP data structure (perhaps an object or associate array) that getInstitute can use right away, without having to do any processing or having to worry about how it is/was stored in the DB.

    If you later find you need to change the query, you can, as long as you don't change what arguments GetOneRecord needs or what values it returns. You could even substitute a different recordStorage class that doesn't use a database at all.
    Last edited by traq; 12-04-2013 at 05:40 PM.

  7. #7
    Beware: Crazy Scientist leatherback's Avatar
    Join Date
    Mar 2002
    Location
    Small border town between Netherlands and Germany
    Posts
    5,395
    So, if I get this right, if I want to avoid all database interaction, I need to define classes that can take the right table to use (sloppy coding below; I just typed this straight into the phpb editor to verify my understanding of the logic):

    PHP Code:
    class institute{

        public function 
    __constructrecordStorage $storage ){
            
    $this->storage $storage;
            
    $this->id 1;
        }

        public function 
    getInstitute(){
            
    $this->storage->setDataSource("Institute");
            
    $this->storage->SelectByIdField();
            
    $record $this->storage->GetOneRecord$this->id );
            
    //  . . . 
        
    }
    }

    // (for example)
    class recordStorage extends PDO{

        public function 
    setDataSource($Table)
          {
          
    $this->_currenttable GetTableName($Table);
          }

        public function 
    SelectByIdField()
         {
          
    $this->_wherefield=($this->GetIdColum($this->_currenttable));
          }

        public function 
    GetOneRecord$id ){
            
    $result $this->query"
                       SELECT 
    $this->ColumNames($this->_currenttable, 'ForQuery') 
                        FROM  
    $this->_currenttable 
                       WHERE 
    $this->_wherefield =$id"limit);  // naturally, with proper pdo coding
            //  . . .
        
    }

    Php 4.* to 5.*. A small step for programmers. But a leap for me!

  8. #8
    Senior Member traq's Avatar
    Join Date
    Jun 2011
    Location
    so.Cal
    Posts
    949
    I think you're understanding the basic idea.

    Two paths:

    1) IF you intend to have only one recordStorage class to serve all other classes, then your setDataSource method makes sense. Ideally, however, it would not require the DB table name (as implied here)—instead, just specify the "record type." That way, you can make changes to the DB structure whenever needed, accommodate records that might require more than one DB table to store, and so forth. The recordStorage class should be responsible for deciding what the table name is, based on the type of record requested.

    Another suggestion would be to pass the record type at the same time as you pass the id:
    PHP Code:
    $record $this->storage->GetOneRecord'Institute',); 
    The way you have it now, there's a risk of forgetting to call setDataSource before a subsequent call, which would result in the wrong record (and wrong record type) being returned.

    2) If NOT, then the "data source" can be implicit. This is the approach I take. I have a base storage class that accesses the database, and I extend that base class for each record type I have. I might end up with something like:
    PHP Code:
    class storage extends MySQLi{
        
    /* basic database access methods */
    }

    class 
    instituteStorage extends storage{
        
    /* methods for accessing institute records */
    }

    class 
    customerStorage extends storage{
        
    /* methods for accessing customer records */
    }

    //  and so forth 
    Grouping all record storage methods into one class makes more sense at first, but from a practical standpoint, you're going to end up with a BIG class very quickly. Big classes are hard to maintain and easy to be confused by. A single class might work "just fine" for tiny-to-small projects, but separating it all into several smaller classes is definitely the way to go with medium-to-large projects.
    Last edited by traq; 12-05-2013 at 07:48 PM.

  9. #9
    Beware: Crazy Scientist leatherback's Avatar
    Join Date
    Mar 2002
    Location
    Small border town between Netherlands and Germany
    Posts
    5,395
    Super. That gets me going for now. Will open another thread in case I run into specific problems.
    Php 4.* to 5.*. A small step for programmers. But a leap for me!

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Posting Permissions

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