473,804 Members | 3,259 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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
Apr 11 '07
22 3527
amygdala wrote:
"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:_L******** *************** *******@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.
js*******@attgl obal.net
=============== ===
Apr 13 '07 #11
amygdala wrote:
"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:_L******** *************** *******@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.
js*******@attgl obal.net
=============== ===
Apr 13 '07 #12

"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:Ub******** *************** *******@comcast .com...
amygdala wrote:
>"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:_L******* *************** ********@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?
Apr 13 '07 #13
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!
Apr 13 '07 #14
amygdala wrote:
"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:Ub******** *************** *******@comcast .com...
>amygdala wrote:
>>"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:_L****** *************** *********@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.
js*******@attgl obal.net
=============== ===
Apr 13 '07 #15

"Toby A Inkster" <us**********@t obyinkster.co.u kschreef in bericht
news:r1******** ****@ophelia.g5 n.co.uk...
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(/*...*/);
}
}
?>
Aaah yes of course, I read about such an example at one point in time. And
at first I didn't understand how such an object could ever be made since the
constructor is private. So I left it for what it was. But the object is of
course constructed from within the object itself with its singleton method.
Doh! ;-)
It all makes sense now. Thanks Toby.

Apr 13 '07 #16

"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:mp******** *************** *******@comcast .com...
amygdala wrote:
<snip>
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.
<snip>
And you'll have to add more custom validators plus hooks for them.
<snip>
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...
<snip>
The generic will be much larger, much slower and much harder to maintain.
<snip>
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.
<snip>
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.
Some darned good points Jerry. Especially the getting too large and slow
parts are starting to convince me

Good point about the flexibility too! I try my best to keep up a flexible
attitude. The thing is though that I often get caught up in trying to
generalize things too much and/or mixing up in what 'layer' certain routines
should take place.

For instance, as you put in your example: Where would validating in the
bussiness objects stop and validating in DB objects start, or vice versa.
Are there some ground rules or methodologies for determining this in early
stages of coding a project? Do you know of some pointers; some good clear
articles perhaps?

Just out of curiousity though. I assume that you _do_ have some sort of
generic validator routines for repeating column / field validation right?
For instance a generic validateEmail() function which you call for the
specific task when doing a setEmail. You're not reinventing the wheel in
each and every getter methods right?

Thanks again!
Apr 13 '07 #17
amygdala wrote:
"Jerry Stuckle" <js*******@attg lobal.netschree f in bericht
news:mp******** *************** *******@comcast .com...
>amygdala wrote:

<snip>
>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.

<snip>
>And you'll have to add more custom validators plus hooks for them.

<snip>
>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...

<snip>
>The generic will be much larger, much slower and much harder to maintain.

<snip>
>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.

<snip>
>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.

Some darned good points Jerry. Especially the getting too large and slow
parts are starting to convince me

Good point about the flexibility too! I try my best to keep up a flexible
attitude. The thing is though that I often get caught up in trying to
generalize things too much and/or mixing up in what 'layer' certain routines
should take place.

For instance, as you put in your example: Where would validating in the
bussiness objects stop and validating in DB objects start, or vice versa.
Are there some ground rules or methodologies for determining this in early
stages of coding a project? Do you know of some pointers; some good clear
articles perhaps?
Generally the business object is at least (if not more) restrictive than
the database object, so the validation would be done in the business
object. I don't normally validate in the database object if it's not
being accessed by the program itself.
Just out of curiousity though. I assume that you _do_ have some sort of
generic validator routines for repeating column / field validation right?
For instance a generic validateEmail() function which you call for the
specific task when doing a setEmail. You're not reinventing the wheel in
each and every getter methods right?

Thanks again!

Not necessarily functions - just some spare code running around. I
either copy and paste into a function or create a validator function
with it, depending on my needs.

I generally don't create a separate function just to validate one
attribute. I just put the code directly in the setxxx function.

--
=============== ===
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attgl obal.net
=============== ===
Apr 14 '07 #18

"Toby A Inkster" <us**********@t obyinkster.co.u kschreef in bericht
news:rr******** ****@ophelia.g5 n.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.
I think I am starting to get the hang of this factory design pattern. My
class User up until now looks something like (stripped version, and needs
custom error handling, etc.):

<?php

require_once( 'Database.class .php' );

class User
{
// database handler values
private static $dbh;
private static $dbt = DB_TABLE_USER;

// table columns
private $id;
private $userType;
private $username;
private $password;
private $email;
private $active;
private $timeCreated;
private $timeActivated;
private $timeUpdated;

public function __construct()
{
self::$dbh = Database::getIn stance( DB_INTERFACE, DB_HOST, DB_SCHEMA,
DB_USERNAME, DB_PASSWORD );
}

public function getUsername()
{
return $this->username;
}

// and a bunch of other getter and setter methods

public static function getUserById( $id )
{
if( is_mysql_int( $id, true ) )
{
self::$dbh = Database::getIn stance( DB_INTERFACE, DB_HOST, DB_SCHEMA,
DB_USERNAME, DB_PASSWORD );
$sql = 'SELECT * FROM ' . self::$dbt . ' WHERE id = :id LIMIT 1';
$sth = self::$dbh->prepare( $sql );
try
{
$sth->execute( array(
':id' =$id
)
);
}
catch( PDOException $e )
{
die( $e->getMessage() . ' on line: ' . __LINE__ );
}
$row = $sth->fetch( PDO::FETCH_ASSO C );
if( $row )
{
$user = new User();
foreach( $row as $column =$value )
{
$user->{ $column } = $value;
}
return $user;
}
echo 'no user found!';
return NULL;
}
echo 'invalid id!';
return NULL;
}
}
?>

A few questions though:

Since I would like to have only one database handler that can be accessed by
both the constructor and the factory method (?) getUserById() I decided to
declare $dbh static. Does this make sense? If so, it seems I'm not allowed
to declare it all in one go at the start of the class like so:

private static $dbh = Database::getIn stance( DB_INTERFACE, DB_HOST,
DB_SCHEMA, DB_USERNAME, DB_PASSWORD );

Any ideas why not?

But what is of more concern for me right now is the following:

A user should be able to register and later on login to the website I'm
building. Logging in, seems pretty obvious, should be a method of the User
class, which returns a User object just like getUserById(). But would a
register method be a logical thing to put in the User class? Or would you
put that somewhere else?

Thank you once more for any insight.
Apr 15 '07 #19
amygdala wrote:
Since I would like to have only one database handler that can be accessed by
both the constructor and the factory method (?) getUserById() I decided to
declare $dbh static. Does this make sense?
It makes sense, but a better solution would be to make your database
object into a singleton class. That is, similar to the Database object
here:

http://message-id.net/<r1************ @ophelia.g5n.co .uk>

--
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!
Apr 16 '07 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
3061
by: lkrubner | last post by:
I have a webserver through Rackspace. I create a domain. I create an FTP user. I upload some files. I create a database called testOfSetupScript and then I create a database user named setup. I write some PHP code which should, I think, be able to to auto create the tables. The SQL looks like this:
5
674
by: Don Vaillancourt | last post by:
Hello all, Over the years as I design more database schemas the more I come up with patterns in database design. The more patterns I recognize the more I want to try to design some kind of generic design patterns that can be used and shared amongst many sub-schemas. For example, the grouping of entities. I may have the following tables: employee, product and client. These tables have no direct relationship with each other. But...
0
2250
by: gasturbtec | last post by:
please help im new at access programming and i just got this project dropped in my lap because the old programmer quit. i've been doing ok so far but now i need to add code to an existing database that is used to connect to other databases and generate reports. below is sample code of how the database does the linking i hope i give you enough info to help me but if not let me know and i will give more. Sub txtShipDataFileSub() Dim...
7
2435
by: PC Datasheet | last post by:
Looking for suggestions ---- A database was designed for a national automobile inspection program. In it's simplest form, the database has two tables: TblOwner OwnerID <Year/Make/Model owned by owner, Owner name/address, etc) TblInspection InspectionID
35
4856
by: Terry Jolly | last post by:
Web Solution Goal: Have a global database connection Why: (There will be 30+ tables, represented by 30+ classes) I only want to reference the database connection once. I put the connection string in the web.config. I created a class with a static database connection and the class opens and closes the database.
76
272588
MMcCarthy
by: MMcCarthy | last post by:
Normalisation is the term used to describe how you break a file down into tables to create a database. There are 3 or 4 major steps involved known as 1NF (First Normal Form), 2NF (Second Normal Form), 3NF (Third Normal Form) and BCNF (Boyce-Codd Normal Form). There are others but they are rarely if ever used. A database is said to be Normalised if it is in 3NF (or ideally in BCNF). These steps are descibed as follows: Note: When attribute...
0
5000
bartonc
by: bartonc | last post by:
With one small change to the view/control: self.staticText3 = wx.StaticText(id=wxID_DBCONNECTDIALOGSTATICTEXT3, label='ODBC Data Source Name', name='staticText3', parent=self, pos=wx.Point(240, 40), size=wx.Size(143, 16), style=0) and some rework of the model:##from MySQLdb import * from mx.ODBC.Windows import * from time import time class DBServer: def __init__(self, master):
8
2764
by: situ | last post by:
Hello all, i have Database1 and database2, is it possible to make database connection to database2 by running stored procedure on database1. Thanks and Regards Situ
12
3948
by: grace | last post by:
i am wondering why my database retrieval becomes too slow...we set up a new server (ubuntu, breezy badger) machine where we transferred all our files from the old server.. Our new server uses Asus p5pe-vm motherboard and an Intel Pentium D 3.0Ghz processor, compared to the old one where we uses asrock motherboard and AMD Duron. Both has the same version of mysql installed... To summarized, both machine has the same configuration except...
9
2339
by: Peter Duniho | last post by:
Is there a straightfoward API in .NET that allows for inspection of a database? That is, to look at the structure of the database, without knowing anything in advance about it? For example, retrieving a list of tables in the database. Doing a little browsing in MSDN, I see that the abstract representation of a database appears to be the DataSet class. I also see that I can use "data adapter" classes (e.g. OdbcDataAdapter) to connect a...
0
9704
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9572
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10562
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9132
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6845
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5508
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4282
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3803
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2978
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.