OOP database tables <-> php interface (semi LONG)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • amygdala

    OOP database tables <-> php interface (semi LONG)

    Hi,

    I'm trying to grasp OOP to build an interface using class objects that lets
    me access database tables easily. You have probably seen this before, or
    maybe even built it yourself at some point in time. I have studied some
    examples I found on the internet, and am now trying to build my own from
    scratch.

    I have made a default table class (DB_Table), a default validation class
    (Validator) which is an object inside DB_Table and my final database tables
    each get a class: e.g. User, UserProfile, Country, etc that extend the
    DB_Table class.

    Its something along the lines of (incomplete code, just for demonstration
    purpose):

    <?php

    class DB_Table
    {
    public function __construct()
    {
    // intialize object
    // initialize (common) validator
    $this->validator = new Validator( $this );
    }

    public function loadData()
    {
    // get all data from record
    }

    public function saveData()
    {
    // save all data to record
    }

    public function __get( $field )
    {
    // get object property
    }

    public function __set( $field, $value )
    {
    // set object property
    }
    }

    class User extends DB_Table
    {
    public $dbt = DB_TABLE_USER;

    public $fields = array(
    'id' =NULL,
    'userType' =NULL,
    'username' =NULL,
    'password' =NULL,
    'email' =NULL,
    'active' =NULL,
    'timeCreated' =NULL,
    'timeActivated' =NULL,
    'timeUpdated' =NULL
    );

    public $fieldSpecs = array(
    'id' =array(
    'screenname' ='user id',
    'type' ='int',
    'autoinsert' =true,
    'autoincrement' =true,
    'static' =true
    ),
    'userType' =array(
    'type' ='tyniint',
    'nodisplay' =true
    ),
    'username' =array(
    'screenname' ='username',
    'type' ='string',
    'unique' =true,
    'required' =true,
    'static' =true,
    ),
    // etc...
    );
    }

    ?>

    It definately still needs a lot of tayloring for it to even work smoothly
    for straightforward DB tables. But besides that, a few future issues are
    bothering me already:

    For instance, take the class User: let's say somebody registers at my site.
    This person fills in the details. The Validator class checks each field
    seperately. No problem. A new User record is inserted in the database.

    But what now, if a user wants to login to the system after the user is
    registrated?
    I would create an instance of class User. Asign the credential values to the
    object. And let the Validator class do its work again.
    But, if a user logs in with incorrect credentials, I don't want to report
    back to the user whether he/she filled in an incorrect username or an
    incorrect password. No, I only want to report back that he/she has filled in
    wrong credentials.

    But the Validator class only checks each field seperately. In order to keep
    the Validator class as common as possible would you build a seperate Login
    class for instance? A class that has some custom validation methods? Or
    perhaps just insert custom validation methods in the User class? I myself
    just cannot seem to make up my mind in this case. Probably cause I'm still
    too inexperienced when it comes to OOP programming.

    A few other minor questions come to mind also:
    - My gut feeling tells me it is wise to make a reference to the Validator
    class inside DB_Table, e.g:
    $this->validator =& new Validator( $this );
    .... because it only creates a single instance of the object, right?

    - And why can't I refer to a private variable in DB_Table from an extended
    class (such as User)? I would asume, that this private variable, declared in
    the parent object, is now a private variable in User also, no?

    - And last but not least, is there a way for me to access let's say User
    properties from the Validator class without having to pass $this as an
    argument to:
    $this->validator = new Validator( $this );
    .... I know the following to be incorrect, but I was thinking of something
    like the keyword parent.

    I hope these questions and examples make sense to you and hopefully someone
    can shed a light on these issues. Thank you in advance for your time.

    Cheers


  • Toby A Inkster

    #2
    Re: OOP database tables &lt;-&gt; php interface (semi LONG)

    amygdala wrote:
    But the Validator class only checks each field seperately. In order to keep
    the Validator class as common as possible would you build a seperate Login
    class for instance? A class that has some custom validation methods? Or
    perhaps just insert custom validation methods in the User class?
    class User
    {
    public static logon ($username, $password)
    {
    // Example query. You will want to protect against SQL
    // injection here.
    $q = "SELECT blah
    FROM blah
    WHERE username=$usern ame
    AND password=$passw ord";
    $result = run_query($q);

    if (!$result)
    return NULL;

    $user = new User;
    $user->load_data(/* blah */);
    return $user;
    }
    }

    This is an example of a User "factory". See "factory design pattern" in the
    PHP manual. To use it:

    $logged_in_user = User::logon($_P OST['un'], $_POST['pw']);
    if (!$logged_in_us er)
    echo "Login failed.";

    --
    Toby A Inkster BSc (Hons) ARCS
    Contact Me ~ http://tobyinkster.co.uk/contact
    Geek of ~ HTML/SQL/Perl/PHP/Python*/Apache/Linux

    * = I'm getting there!

    Comment

    • amygdala

      #3
      Re: OOP database tables &lt;-&gt; php interface (semi LONG)


      "Toby A Inkster" <usenet200703@t obyinkster.co.u kschreef in bericht
      news:jd61f4-4kp.ln1@ophelia .g5n.co.uk...
      amygdala wrote:
      >
      >But the Validator class only checks each field seperately. In order to
      >keep
      >the Validator class as common as possible would you build a seperate
      >Login
      >class for instance? A class that has some custom validation methods? Or
      >perhaps just insert custom validation methods in the User class?
      >
      class User
      {
      public static logon ($username, $password)
      {
      // Example query. You will want to protect against SQL
      // injection here.
      $q = "SELECT blah
      FROM blah
      WHERE username=$usern ame
      AND password=$passw ord";
      $result = run_query($q);
      >
      if (!$result)
      return NULL;
      >
      $user = new User;
      $user->load_data(/* blah */);
      return $user;
      }
      }
      >
      This is an example of a User "factory". See "factory design pattern" in
      the
      PHP manual. To use it:
      >
      $logged_in_user = User::logon($_P OST['un'], $_POST['pw']);
      if (!$logged_in_us er)
      echo "Login failed.";
      >
      Thanks for the response and the pointer.

      I'm a little confused about the 'factory design pattern' though. Let me see
      if I understand this correctly. Does the factory design pattern in this case
      refer to the fact that you have different interfaces in one Class (in this
      case class User) to create the object, depending on the purpose it serves.

      So I could do a:

      $blank_user = new User();

      or I could do a

      $logged_in_user = User::logon($_P OST['un'], $_POST['pw']);

      which both return a User object?


      Comment

      • Toby A Inkster

        #4
        Re: OOP database tables &lt;-&gt; php interface (semi LONG)

        amygdala wrote:
        I'm a little confused about the 'factory design pattern' though. Let me see
        if I understand this correctly. Does the factory design pattern in this case
        refer to the fact that you have different interfaces in one Class (in this
        case class User) to create the object, depending on the purpose it serves.
        Yep, precisely. You create a static method to produce an object which
        would normally go further than the plain constructor function in terms of
        setting object properties.

        On some occasions you may even want to make the main constructor method
        for the class private instead of public to force all objects to be created
        via the factory.

        --
        Toby A Inkster BSc (Hons) ARCS
        Contact Me ~ http://tobyinkster.co.uk/contact
        Geek of ~ HTML/SQL/Perl/PHP/Python*/Apache/Linux

        * = I'm getting there!

        Comment

        • amygdala

          #5
          Re: OOP database tables &lt;-&gt; php interface (semi LONG)


          "Toby A Inkster" <usenet200703@t obyinkster.co.u kschreef in bericht
          news:rrr2f4-4kp.ln1@ophelia .g5n.co.uk...
          amygdala wrote:
          >
          >I'm a little confused about the 'factory design pattern' though. Let me
          >see
          >if I understand this correctly. Does the factory design pattern in this
          >case
          >refer to the fact that you have different interfaces in one Class (in
          >this
          >case class User) to create the object, depending on the purpose it
          >serves.
          >
          Yep, precisely. You create a static method to produce an object which
          would normally go further than the plain constructor function in terms of
          setting object properties.
          >
          On some occasions you may even want to make the main constructor method
          for the class private instead of public to force all objects to be created
          via the factory.
          >
          Nice one! That's excellent stuff.
          In the meantime I read a little further on the factory stuff, and indeed saw
          that you could make the constructor method private. Could you by any chance
          provide the simplest example of an occassion where making the constructor
          private makes sense? Cause I can't think of a valuable situation right now.
          But I'm interested in understanding where this would make sense. (That OOP
          stuff is pretty hard to grasp for me)

          Another thing I am trying to accomplish is the following: (still the same
          'framework')

          What would be ideal for me is if I had table classes derived from the
          'template' DB_Table that would only describe table fields and their
          properties. And for the most part let the parent DB_Table handle all the
          generic methods for tweaking fields. Except of course a function such as
          login, as discussed earlier.

          What would seem important here also, is to have as little public methods and
          properties as possible. So if you will, consider the following:

          class DB_table
          {
          protected static fields;
          protected static fieldSpecs;

          // some __constructor etc...

          public function getFieldSpecs( $f )
          {
          if( isset( self::fieldSpec s[ $f ] ) )
          {
          return self::fieldSpec s[ $f ];
          }
          else
          {
          return NULL;
          }
          }
          }

          class User extends DB_Table
          {
          protected static fieldSpecs = array(
          'id' =array(
          'article' ='a',
          'screenname' ='user id',
          'type' ='int',
          'autoinsert' =true,
          'autoincrement' =true,
          'static' =true
          ),
          etc...
          );
          }

          What I would like to happen is that when I do a:

          $u = new User();
          var_dump( $u->getFieldSpec s( 'id' ) );

          it would return the 'fieldSpecs' from the 'id' in User. But this doesn't
          seem to work.

          parent::$fieldS pecs = array( etc...

          doesn't seem to work either.

          Is there any way to get this working without having to declare fieldSpecs
          public and/or having to overload (I think it is what it's called) the
          'getFieldSpecs' function from within User?

          In other words, how can I overwrite the 'protected static fieldSpecs' of
          DB_Table from within User so that 'getFieldSpecs' in DB_Table returns its
          values? Or is this against OOP principles?


          Cheers.


          Comment

          • amygdala

            #6
            Re: OOP database tables &lt;-&gt; php interface (semi LONG)

            >
            class DB_table
            {
            protected static fields;
            protected static fieldSpecs;
            >
            // some __constructor etc...
            >
            public function getFieldSpecs( $f )
            {
            if( isset( self::fieldSpec s[ $f ] ) )
            {
            return self::fieldSpec s[ $f ];
            }
            else
            {
            return NULL;
            }
            }
            }
            >
            class User extends DB_Table
            {
            protected static fieldSpecs = array(
            'id' =array(
            'article' ='a',
            'screenname' ='user id',
            'type' ='int',
            'autoinsert' =true,
            'autoincrement' =true,
            'static' =true
            ),
            etc...
            );
            }
            >
            Oops; dollarsigns where needed of course. :-S


            Comment

            • Jerry Stuckle

              #7
              Re: OOP database tables &lt;-&gt; php interface (semi LONG)

              amygdala wrote:
              "Toby A Inkster" <usenet200703@t obyinkster.co.u kschreef in bericht
              news:rrr2f4-4kp.ln1@ophelia .g5n.co.uk...
              >amygdala wrote:
              >>
              >>I'm a little confused about the 'factory design pattern' though. Let me
              >>see
              >>if I understand this correctly. Does the factory design pattern in this
              >>case
              >>refer to the fact that you have different interfaces in one Class (in
              >>this
              >>case class User) to create the object, depending on the purpose it
              >>serves.
              >Yep, precisely. You create a static method to produce an object which
              >would normally go further than the plain constructor function in terms of
              >setting object properties.
              >>
              >On some occasions you may even want to make the main constructor method
              >for the class private instead of public to force all objects to be created
              >via the factory.
              >>
              >
              Nice one! That's excellent stuff.
              In the meantime I read a little further on the factory stuff, and indeed saw
              that you could make the constructor method private. Could you by any chance
              provide the simplest example of an occassion where making the constructor
              private makes sense? Cause I can't think of a valuable situation right now.
              But I'm interested in understanding where this would make sense. (That OOP
              stuff is pretty hard to grasp for me)
              >
              Another thing I am trying to accomplish is the following: (still the same
              'framework')
              >
              What would be ideal for me is if I had table classes derived from the
              'template' DB_Table that would only describe table fields and their
              properties. And for the most part let the parent DB_Table handle all the
              generic methods for tweaking fields. Except of course a function such as
              login, as discussed earlier.
              >
              What would seem important here also, is to have as little public methods and
              properties as possible. So if you will, consider the following:
              >
              class DB_table
              {
              protected static fields;
              protected static fieldSpecs;
              >
              // some __constructor etc...
              >
              public function getFieldSpecs( $f )
              {
              if( isset( self::fieldSpec s[ $f ] ) )
              {
              return self::fieldSpec s[ $f ];
              }
              else
              {
              return NULL;
              }
              }
              }
              >
              class User extends DB_Table
              {
              protected static fieldSpecs = array(
              'id' =array(
              'article' ='a',
              'screenname' ='user id',
              'type' ='int',
              'autoinsert' =true,
              'autoincrement' =true,
              'static' =true
              ),
              etc...
              );
              }
              >
              What I would like to happen is that when I do a:
              >
              $u = new User();
              var_dump( $u->getFieldSpec s( 'id' ) );
              >
              it would return the 'fieldSpecs' from the 'id' in User. But this doesn't
              seem to work.
              >
              parent::$fieldS pecs = array( etc...
              >
              doesn't seem to work either.
              >
              Is there any way to get this working without having to declare fieldSpecs
              public and/or having to overload (I think it is what it's called) the
              'getFieldSpecs' function from within User?
              >
              In other words, how can I overwrite the 'protected static fieldSpecs' of
              DB_Table from within User so that 'getFieldSpecs' in DB_Table returns its
              values? Or is this against OOP principles?
              >
              >
              Cheers.
              >
              >
              Definitely properties should be private. They're part of the
              implementation.

              However, I often have lots of public methods. For instance, I'll have a
              getXXX method to fetch 'xxx'. And I may have a setxxx method to set it,
              if that makes sense - the latter doing validation on the parameter
              passed, if necessary.

              So potentially in a table with 25 columns I can have 25 getXXX and 25
              setXXX methods (and 25 private variables, one for each column), database
              related methods, etc. This can easily come out to 60-70 public methods
              - and often I'll have some private ones, also.

              But don't try to put all of your variables in one 'fieldspec' array.
              While it will work, it will also be almost impossible to understand
              later and even worse to maintain.

              --
              =============== ===
              Remove the "x" from my email address
              Jerry Stuckle
              JDS Computer Training Corp.
              jstucklex@attgl obal.net
              =============== ===

              Comment

              • Jerry Stuckle

                #8
                Re: OOP database tables &lt;-&gt; php interface (semi LONG)

                amygdala wrote:
                "Toby A Inkster" <usenet200703@t obyinkster.co.u kschreef in bericht
                news:rrr2f4-4kp.ln1@ophelia .g5n.co.uk...
                >amygdala wrote:
                >>
                >>I'm a little confused about the 'factory design pattern' though. Let me
                >>see
                >>if I understand this correctly. Does the factory design pattern in this
                >>case
                >>refer to the fact that you have different interfaces in one Class (in
                >>this
                >>case class User) to create the object, depending on the purpose it
                >>serves.
                >Yep, precisely. You create a static method to produce an object which
                >would normally go further than the plain constructor function in terms of
                >setting object properties.
                >>
                >On some occasions you may even want to make the main constructor method
                >for the class private instead of public to force all objects to be created
                >via the factory.
                >>
                >
                Nice one! That's excellent stuff.
                In the meantime I read a little further on the factory stuff, and indeed saw
                that you could make the constructor method private. Could you by any chance
                provide the simplest example of an occassion where making the constructor
                private makes sense? Cause I can't think of a valuable situation right now.
                But I'm interested in understanding where this would make sense. (That OOP
                stuff is pretty hard to grasp for me)
                >
                Another thing I am trying to accomplish is the following: (still the same
                'framework')
                >
                What would be ideal for me is if I had table classes derived from the
                'template' DB_Table that would only describe table fields and their
                properties. And for the most part let the parent DB_Table handle all the
                generic methods for tweaking fields. Except of course a function such as
                login, as discussed earlier.
                >
                What would seem important here also, is to have as little public methods and
                properties as possible. So if you will, consider the following:
                >
                class DB_table
                {
                protected static fields;
                protected static fieldSpecs;
                >
                // some __constructor etc...
                >
                public function getFieldSpecs( $f )
                {
                if( isset( self::fieldSpec s[ $f ] ) )
                {
                return self::fieldSpec s[ $f ];
                }
                else
                {
                return NULL;
                }
                }
                }
                >
                class User extends DB_Table
                {
                protected static fieldSpecs = array(
                'id' =array(
                'article' ='a',
                'screenname' ='user id',
                'type' ='int',
                'autoinsert' =true,
                'autoincrement' =true,
                'static' =true
                ),
                etc...
                );
                }
                >
                What I would like to happen is that when I do a:
                >
                $u = new User();
                var_dump( $u->getFieldSpec s( 'id' ) );
                >
                it would return the 'fieldSpecs' from the 'id' in User. But this doesn't
                seem to work.
                >
                parent::$fieldS pecs = array( etc...
                >
                doesn't seem to work either.
                >
                Is there any way to get this working without having to declare fieldSpecs
                public and/or having to overload (I think it is what it's called) the
                'getFieldSpecs' function from within User?
                >
                In other words, how can I overwrite the 'protected static fieldSpecs' of
                DB_Table from within User so that 'getFieldSpecs' in DB_Table returns its
                values? Or is this against OOP principles?
                >
                >
                Cheers.
                >
                >
                One other thing - the class members shouldn't be static. Static members
                are shared by all objects of the class. So if you have two objects of
                this class and change it in one, both will change.

                Non-static data members are unique to each instantiation of the class.

                --
                =============== ===
                Remove the "x" from my email address
                Jerry Stuckle
                JDS Computer Training Corp.
                jstucklex@attgl obal.net
                =============== ===

                Comment

                • amygdala

                  #9
                  Re: OOP database tables &lt;-&gt; php interface (semi LONG)


                  "Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                  news:_L2dncAv8Z xOfIPbnZ2dnUVZ_ sOknZ2d@comcast .com...
                  amygdala wrote:
                  <snip>

                  Definitely properties should be private. They're part of the
                  implementation.
                  >
                  However, I often have lots of public methods. For instance, I'll have a
                  getXXX method to fetch 'xxx'. And I may have a setxxx method to set it,
                  if that makes sense - the latter doing validation on the parameter passed,
                  if necessary.
                  >
                  So potentially in a table with 25 columns I can have 25 getXXX and 25
                  setXXX methods (and 25 private variables, one for each column), database
                  related methods, etc. This can easily come out to 60-70 public methods -
                  and often I'll have some private ones, also.
                  Well, this is just exactly what I am trying to avoid. I have (unfinished)
                  __get and __set methods in the base class DB_Table that should take care of
                  this in one go.
                  But don't try to put all of your variables in one 'fieldspec' array. While
                  it will work, it will also be almost impossible to understand later and
                  even worse to maintain.
                  Hmm, you are no doubt much more experienced in this field, but my gutfeeling
                  says I have to disagree on this one. The whole point of creating this
                  framework for me is to avoid the cumbersome task of creating getter and
                  setter functions for each and every table field. Thus I'm declaring one
                  generic fieldSpecs array that provides properties for the fields so that the
                  generic getters and setters as well as the generic Validator will take care
                  of the rest. I don't see the fieldSpecs array becoming to difficult to
                  understand quickly for me in the future.

                  Still, this leaves me wondering: why doesn't a child class just simply
                  inherite the 'getFieldSpecs' function and let self::$fieldSpe cs refer to the
                  $fieldSpecs in the child class? Should this not be the basics of OOP? What
                  am I missing here? Or better yet: how can this be achieved?

                  Thanks for your time people. Much appreciated!


                  Comment

                  • amygdala

                    #10
                    Re: OOP database tables &lt;-&gt; php interface (semi LONG)


                    "Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                    news:_L2dncMv8Z yhf4PbnZ2dnUVZ_ sPinZ2d@comcast .com...
                    amygdala wrote:
                    <snip>
                    >
                    One other thing - the class members shouldn't be static. Static members
                    are shared by all objects of the class. So if you have two objects of
                    this class and change it in one, both will change.
                    >
                    Non-static data members are unique to each instantiation of the class.
                    Aaah yes of course. Silly me. Good point. I overlooked that one.

                    But would it be save to say that a derived class of DB_Table such as User
                    _could_ have a static $fields variable (for instance when I wont be
                    declaring it in the parent class first), since every User instance would
                    have the same table fields?

                    Thanks again Jerry et al.


                    Comment

                    • Jerry Stuckle

                      #11
                      Re: OOP database tables &lt;-&gt; php interface (semi LONG)

                      amygdala wrote:
                      "Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                      news:_L2dncAv8Z xOfIPbnZ2dnUVZ_ sOknZ2d@comcast .com...
                      >amygdala wrote:
                      >
                      <snip>
                      >
                      >
                      >Definitely properties should be private. They're part of the
                      >implementation .
                      >>
                      >However, I often have lots of public methods. For instance, I'll have a
                      >getXXX method to fetch 'xxx'. And I may have a setxxx method to set it,
                      >if that makes sense - the latter doing validation on the parameter passed,
                      >if necessary.
                      >>
                      >So potentially in a table with 25 columns I can have 25 getXXX and 25
                      >setXXX methods (and 25 private variables, one for each column), database
                      >related methods, etc. This can easily come out to 60-70 public methods -
                      >and often I'll have some private ones, also.
                      >
                      Well, this is just exactly what I am trying to avoid. I have (unfinished)
                      __get and __set methods in the base class DB_Table that should take care of
                      this in one go.
                      >
                      >But don't try to put all of your variables in one 'fieldspec' array. While
                      >it will work, it will also be almost impossible to understand later and
                      >even worse to maintain.
                      >
                      Hmm, you are no doubt much more experienced in this field, but my gutfeeling
                      says I have to disagree on this one. The whole point of creating this
                      framework for me is to avoid the cumbersome task of creating getter and
                      setter functions for each and every table field. Thus I'm declaring one
                      generic fieldSpecs array that provides properties for the fields so that the
                      generic getters and setters as well as the generic Validator will take care
                      of the rest. I don't see the fieldSpecs array becoming to difficult to
                      understand quickly for me in the future.
                      >
                      Still, this leaves me wondering: why doesn't a child class just simply
                      inherite the 'getFieldSpecs' function and let self::$fieldSpe cs refer to the
                      $fieldSpecs in the child class? Should this not be the basics of OOP? What
                      am I missing here? Or better yet: how can this be achieved?
                      >
                      Thanks for your time people. Much appreciated!
                      >
                      >
                      OK, now how are you going to validate the entry? For instance - if you
                      have a date field, ensure they put a date in there? Or an integer?

                      Classes also need to be responsible for their own variables. There
                      should be no way you can ever set an invalid value in any member.

                      So you might as well get used to writing the set and get functions.
                      They go pretty quickly (unless you have some extensive validation), and
                      in the long run it's a much better way to go.

                      I've been doing OO programming for almost 20 years now, and yes, I've
                      seen your way before. It ends up being cumbersome and highly prone to
                      errors. It also creates a maintenance nightmare. You *really* don't
                      want to go that route.

                      --
                      =============== ===
                      Remove the "x" from my email address
                      Jerry Stuckle
                      JDS Computer Training Corp.
                      jstucklex@attgl obal.net
                      =============== ===

                      Comment

                      • Jerry Stuckle

                        #12
                        Re: OOP database tables &lt;-&gt; php interface (semi LONG)

                        amygdala wrote:
                        "Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                        news:_L2dncMv8Z yhf4PbnZ2dnUVZ_ sPinZ2d@comcast .com...
                        >amygdala wrote:
                        >
                        <snip>
                        >
                        >One other thing - the class members shouldn't be static. Static members
                        >are shared by all objects of the class. So if you have two objects of
                        >this class and change it in one, both will change.
                        >>
                        >Non-static data members are unique to each instantiation of the class.
                        >
                        Aaah yes of course. Silly me. Good point. I overlooked that one.
                        >
                        But would it be save to say that a derived class of DB_Table such as User
                        _could_ have a static $fields variable (for instance when I wont be
                        declaring it in the parent class first), since every User instance would
                        have the same table fields?
                        >
                        Thanks again Jerry et al.
                        >
                        >
                        No, because I would never do it that way per my previous response.

                        --
                        =============== ===
                        Remove the "x" from my email address
                        Jerry Stuckle
                        JDS Computer Training Corp.
                        jstucklex@attgl obal.net
                        =============== ===

                        Comment

                        • amygdala

                          #13
                          Re: OOP database tables &lt;-&gt; php interface (semi LONG)


                          "Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                          news:UbydnbDR17 4eZYPbnZ2dnUVZ_ tOmnZ2d@comcast .com...
                          amygdala wrote:
                          >"Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                          >news:_L2dncAv8 ZxOfIPbnZ2dnUVZ _sOknZ2d@comcas t.com...
                          >>amygdala wrote:
                          >>
                          ><snip>
                          >>
                          >>
                          >>Definitely properties should be private. They're part of the
                          >>implementatio n.
                          >>>
                          >>However, I often have lots of public methods. For instance, I'll have a
                          >>getXXX method to fetch 'xxx'. And I may have a setxxx method to set it,
                          >>if that makes sense - the latter doing validation on the parameter
                          >>passed, if necessary.
                          >>>
                          >>So potentially in a table with 25 columns I can have 25 getXXX and 25
                          >>setXXX methods (and 25 private variables, one for each column), database
                          >>related methods, etc. This can easily come out to 60-70 public
                          >>methods - and often I'll have some private ones, also.
                          >>
                          >Well, this is just exactly what I am trying to avoid. I have (unfinished)
                          >__get and __set methods in the base class DB_Table that should take care
                          >of this in one go.
                          >>
                          >>But don't try to put all of your variables in one 'fieldspec' array.
                          >>While it will work, it will also be almost impossible to understand
                          >>later and even worse to maintain.
                          >>
                          >Hmm, you are no doubt much more experienced in this field, but my
                          >gutfeeling says I have to disagree on this one. The whole point of
                          >creating this framework for me is to avoid the cumbersome task of
                          >creating getter and setter functions for each and every table field. Thus
                          >I'm declaring one generic fieldSpecs array that provides properties for
                          >the fields so that the generic getters and setters as well as the generic
                          >Validator will take care of the rest. I don't see the fieldSpecs array
                          >becoming to difficult to understand quickly for me in the future.
                          >>
                          >Still, this leaves me wondering: why doesn't a child class just simply
                          >inherite the 'getFieldSpecs' function and let self::$fieldSpe cs refer to
                          >the $fieldSpecs in the child class? Should this not be the basics of OOP?
                          >What am I missing here? Or better yet: how can this be achieved?
                          >>
                          >Thanks for your time people. Much appreciated!
                          >
                          OK, now how are you going to validate the entry? For instance - if you
                          have a date field, ensure they put a date in there? Or an integer?
                          Well, I would use a generic Validator class for that. Something along the
                          lines of:

                          class Validator
                          {
                          public function validateField( $fieldName, $fieldValue, $fieldSpecs )
                          {
                          switch( $fieldSpec [ 'type' ] )
                          {
                          case 'boolean':
                          // validate boolean
                          break;
                          case 'string':
                          if( isset( $fieldSpec[ 'subtype' ] ) )
                          {
                          switch( $fieldSpec[ 'subtype' ] )
                          {
                          case 'email':
                          // validate email
                          break;
                          case 'url':
                          // validate url
                          break
                          etc.. etc...
                          }
                          }
                          case 'int':
                          etc.. etc...


                          For dates I _would_ probably use a custom setter which would convert three
                          form elements (dd, mm, yyyy) to a unix timestamp (I like those better then
                          SQL dates) first, but then I would validate its outcome with the generic
                          Validator also. I could even have some minimal and maximal date values in
                          $fieldSpecs to check that the date doesn't exceed a certain time span.

                          For integers I would define some minimal and maximal values in the
                          $fieldSpecs, and check it directly in the generic Validator. Use is_numeric
                          and the likes.
                          Classes also need to be responsible for their own variables. There should
                          be no way you can ever set an invalid value in any member.
                          Of course, I agree with you totally. But I don't see how my approach would
                          lead to this happening. I would validate each entry just like you do. But
                          with a generic __set instead of custom setters.
                          So you might as well get used to writing the set and get functions. They
                          go pretty quickly (unless you have some extensive validation), and in the
                          long run it's a much better way to go.
                          Maybe you're right. I might be stubborn here. ;-) And off course, I have
                          thought of the fact that exceptional situations _will_ occur. Probably more
                          often then I'm thinking off right now. But then that leads me to the
                          somewhat black and white conclusion stated under your following opinions:
                          I've been doing OO programming for almost 20 years now, and yes, I've seen
                          your way before. It ends up being cumbersome and highly prone to errors.
                          It also creates a maintenance nightmare. You *really* don't want to go
                          that route.
                          >
                          I see where you are coming from Jerry, but this point of view then almost
                          leads me to believe that there is no point in creating DB table objects
                          whatsoever. Cause then it pretty much comes down to the same old 'linear'
                          routines again. What then, in your opinion, is the surplus value of creating
                          DB table classes?


                          Comment

                          • Toby A Inkster

                            #14
                            Re: OOP database tables &lt;-&gt; php interface (semi LONG)

                            amygdala wrote:
                            Could you by any chance provide the simplest example of an occassion
                            where making the constructor private makes sense? Cause I can't think of
                            a valuable situation right now.
                            OK -- how about this -- you have a Database class, but you want to make
                            sure that your scripts only ever open a single connection to the database.
                            You don't want both, say, a User object and an Article object to open
                            their own individual connections like this:

                            <?php
                            class User
                            {
                            private $db;
                            public function __construct ()
                            {
                            $this->db = new Database(/*...*/);
                            }
                            }
                            class Article
                            {
                            private $db;
                            public function __construct ()
                            {
                            $this->db = new Database(/*...*/);
                            }
                            }
                            ?>

                            And so to prevent this, you make the Database's constructor function
                            private. This is known as the "singleton" design pattern in the PHP
                            manual. (It's on the same page as the factory design pattern!)

                            <?php
                            class Database
                            {
                            public function query ($q) { /*...*/ }
                            public function type () { /*...*/ }
                            public function escape_string ($s) { /*...*/ }
                            private function __construct ($dsn, $username, $password) { /*...*/ }

                            private static $instance;
                            public static singleton ($dsn, $username, $password)
                            {
                            if (!isset(self::$ instance))
                            self::$instance = new Database ($dsn, $username, $password);

                            return self::$instance ;
                            }
                            }
                            ?>

                            So now you must use "Database::sing leton()" instead of "new Database" to
                            get a database object, but the singleton class method will always return a
                            pointer to the same Database object -- it won't create a brand new one!

                            And your code becomes:

                            <?php
                            class User
                            {
                            private $db;
                            public function __construct ()
                            {
                            $this->db = Database::singl eton(/*...*/);
                            }
                            }
                            class Article
                            {
                            private $db;
                            public function __construct ()
                            {
                            $this->db = Database::singl eton(/*...*/);
                            }
                            }
                            ?>

                            I bet if you think about it there are plenty of occasions when the
                            singleton design pattern would have come in handy if you'd known about it!
                            That OOP stuff is pretty hard to grasp for me
                            Don't worry about it. I think a lot of PHPers are at that stage now. PHP
                            4's object oriented capabilities were fairly limited, so apart from the
                            benefit of namespacing (i.e. being able to wrap up a bunch of functions and
                            variables into something with just one name) objects didn't offer an awful
                            lot of benefit over, say, arrays. A couple of years after its release, PHP
                            5 is only really beginning to get decent penetration onto commercial web
                            servers.

                            I'm quite lucky in that I have direct physical access to most of the PHP
                            servers I use, and quite a lot of say over the ones I don't have physical
                            access to. So I upgraded most of them to PHP 5 when it was still fairly
                            new (I waited until 5.0.4 I think. Most are now on 5.1.x and I'm looking
                            to switch to 5.2.x after another release or two), so I've been able to play
                            with the improved OO facilities for quite a while. But I'm still learning
                            things too!

                            --
                            Toby A Inkster BSc (Hons) ARCS
                            Contact Me ~ http://tobyinkster.co.uk/contact
                            Geek of ~ HTML/SQL/Perl/PHP/Python*/Apache/Linux

                            * = I'm getting there!

                            Comment

                            • Jerry Stuckle

                              #15
                              Re: OOP database tables &lt;-&gt; php interface (semi LONG)

                              amygdala wrote:
                              "Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                              news:UbydnbDR17 4eZYPbnZ2dnUVZ_ tOmnZ2d@comcast .com...
                              >amygdala wrote:
                              >>"Jerry Stuckle" <jstucklex@attg lobal.netschree f in bericht
                              >>news:_L2dncAv 8ZxOfIPbnZ2dnUV Z_sOknZ2d@comca st.com...
                              >>>amygdala wrote:
                              >><snip>
                              >>>
                              >>>
                              >>>Definitely properties should be private. They're part of the
                              >>>implementati on.
                              >>>>
                              >>>However, I often have lots of public methods. For instance, I'll have a
                              >>>getXXX method to fetch 'xxx'. And I may have a setxxx method to set it,
                              >>>if that makes sense - the latter doing validation on the parameter
                              >>>passed, if necessary.
                              >>>>
                              >>>So potentially in a table with 25 columns I can have 25 getXXX and 25
                              >>>setXXX methods (and 25 private variables, one for each column), database
                              >>>related methods, etc. This can easily come out to 60-70 public
                              >>>methods - and often I'll have some private ones, also.
                              >>Well, this is just exactly what I am trying to avoid. I have (unfinished)
                              >>__get and __set methods in the base class DB_Table that should take care
                              >>of this in one go.
                              >>>
                              >>>But don't try to put all of your variables in one 'fieldspec' array.
                              >>>While it will work, it will also be almost impossible to understand
                              >>>later and even worse to maintain.
                              >>Hmm, you are no doubt much more experienced in this field, but my
                              >>gutfeeling says I have to disagree on this one. The whole point of
                              >>creating this framework for me is to avoid the cumbersome task of
                              >>creating getter and setter functions for each and every table field. Thus
                              >>I'm declaring one generic fieldSpecs array that provides properties for
                              >>the fields so that the generic getters and setters as well as the generic
                              >>Validator will take care of the rest. I don't see the fieldSpecs array
                              >>becoming to difficult to understand quickly for me in the future.
                              >>>
                              >>Still, this leaves me wondering: why doesn't a child class just simply
                              >>inherite the 'getFieldSpecs' function and let self::$fieldSpe cs refer to
                              >>the $fieldSpecs in the child class? Should this not be the basics of OOP?
                              >>What am I missing here? Or better yet: how can this be achieved?
                              >>>
                              >>Thanks for your time people. Much appreciated!
                              >OK, now how are you going to validate the entry? For instance - if you
                              >have a date field, ensure they put a date in there? Or an integer?
                              >
                              Well, I would use a generic Validator class for that. Something along the
                              lines of:
                              >
                              class Validator
                              {
                              public function validateField( $fieldName, $fieldValue, $fieldSpecs )
                              {
                              switch( $fieldSpec [ 'type' ] )
                              {
                              case 'boolean':
                              // validate boolean
                              break;
                              case 'string':
                              if( isset( $fieldSpec[ 'subtype' ] ) )
                              {
                              switch( $fieldSpec[ 'subtype' ] )
                              {
                              case 'email':
                              // validate email
                              break;
                              case 'url':
                              // validate url
                              break
                              etc.. etc...
                              }
                              }
                              case 'int':
                              etc.. etc...
                              >
                              And as you add more types and subtypes, this gets longer and longer.
                              And slower and slower. And harder to maintain and more subject to errors.
                              >
                              For dates I _would_ probably use a custom setter which would convert three
                              form elements (dd, mm, yyyy) to a unix timestamp (I like those better then
                              SQL dates) first, but then I would validate its outcome with the generic
                              Validator also. I could even have some minimal and maximal date values in
                              $fieldSpecs to check that the date doesn't exceed a certain time span.
                              >
                              And you'll have to add more custom validators plus hooks for them.
                              For integers I would define some minimal and maximal values in the
                              $fieldSpecs, and check it directly in the generic Validator. Use is_numeric
                              and the likes.
                              >
                              And what about cases where you need non-consecutive numbers? Such as
                              those from the set (1, 2, 3, 5, 8, 13, 21...)? Another custom validator...
                              >Classes also need to be responsible for their own variables. There should
                              >be no way you can ever set an invalid value in any member.
                              >
                              Of course, I agree with you totally. But I don't see how my approach would
                              lead to this happening. I would validate each entry just like you do. But
                              with a generic __set instead of custom setters.
                              >
                              The generic will be much larger, much slower and much harder to maintain.
                              >So you might as well get used to writing the set and get functions. They
                              >go pretty quickly (unless you have some extensive validation), and in the
                              >long run it's a much better way to go.
                              >
                              Maybe you're right. I might be stubborn here. ;-) And off course, I have
                              thought of the fact that exceptional situations _will_ occur. Probably more
                              often then I'm thinking off right now. But then that leads me to the
                              somewhat black and white conclusion stated under your following opinions:
                              >
                              Yes, it's easy to get one idea in your mind as the best way and stick to
                              it too long. You need to be flexible. Even after 40 years of
                              programming I sometimes have to change my approach because someone shows
                              me a better way.
                              >I've been doing OO programming for almost 20 years now, and yes, I've seen
                              >your way before. It ends up being cumbersome and highly prone to errors.
                              >It also creates a maintenance nightmare. You *really* don't want to go
                              >that route.
                              >>
                              >
                              I see where you are coming from Jerry, but this point of view then almost
                              leads me to believe that there is no point in creating DB table objects
                              whatsoever. Cause then it pretty much comes down to the same old 'linear'
                              routines again. What then, in your opinion, is the surplus value of creating
                              DB table classes?
                              >
                              >
                              I create db objects all the time. But they have get and set functions
                              for each field (at least the appropriate ones). They are quite handy
                              for a number of purposes - the biggest one being abstracting the
                              database access. But then that's their major purpose.

                              For instance - one I'm on right now. I have a site coded in VBScript
                              using Access. I want to change it to PHP and MySQL. However, for
                              various reasons this needs to be done in stages. The Access database
                              has over 30 tables, ranging from 2 columns to over 40 columns per table.

                              We're (others are involved - it's a big site) creating DB objects to
                              interface the Access tables. These will handle the actual SQL calls and
                              isolates the program from the database being used (or even flat files,
                              if necessary).

                              Next we'll creating business objects - these objects translate between
                              the program and the database objects, and convert what's in the tables
                              to a format the rest of the program needs. This isolates the rest of
                              the code from the database table design (i.e. if we need to change one
                              or more tables, this and the db objects are all that will need changing).

                              We'll then convert sections of the site at a time. Once we get a
                              section converted, we'll bring it online.

                              When we're done and can change from the Access database to MySQL, we'll
                              change the Database layer and move the data. If at the same time we
                              need to change some of the table design, this will be handled between
                              the database and business object layers. But any changes will be
                              isolated to those layers.

                              Note the business object layer isn't always needed. But due to the
                              complexity of the site and how many tables are interrelated, we decided
                              it would be better to use them here.

                              These are the benefits of database objects (and OO in general).
                              But I would hate to use your fieldspec idea in this case. It would
                              make things much harder to troubleshoot, and we'd end up with a lot of
                              specialized validators. The result would rapidly become unmanageable.

                              So we're putting in the set and get functions for several hundred table
                              columns. Additionally, we're doing a similar number on the business
                              object end. And depending on the data, it may be validated in either level.

                              --
                              =============== ===
                              Remove the "x" from my email address
                              Jerry Stuckle
                              JDS Computer Training Corp.
                              jstucklex@attgl obal.net
                              =============== ===

                              Comment

                              Working...