SitePoint Sponsor

User Tag List

Page 1 of 3 123 LastLast
Results 1 to 25 of 53
  1. #1
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    NAOOPT - Not Another OOP Thread

    Howdie y'all!

    Ok, I've be 'programming' PHP for almost two years now and I thought I should probably get into the OOP side of it, since I want to migrate to C++ and C# overtime for desktop programming.

    I've read many of Vincent's threads and they are absolutely amazing, however I'm having a really hard time trying to get started. I'm trying to dive into the deep end, as I usually learn better than way (Research and Implement) however, I don't know where to start on a project like this.

    I want to attempt to make a simple CMS with only article management using OOP. I can build on this later to form user validation, etc. From what I understand, OOP is supposed to make things simpler, and more easily understandable however, I'm thinking differently at the moment.

    I guess I'd have a database abstraction class so I could easily connect to databases of any type and a query class to query a database of any type. However, would I just set a variable like $dbType, and if it equals something, I call a certain set of functions, or do i would i write seperate classes/functions and class these separately in my code. This option i guess would mean that if i wanted to switch databases, I'd have to replace every reference to a class/function in my code with another.

    Another aspect I'm having trouble with is the Add/Edit/Delete/List functions. I'm sure I could create a general class to do all this, for any data, however would this be wise. What I mean is I'd do something like:

    Class: addData
    Methods:
    -generateForm
    -validateForm
    -submitForm

    Class: editData
    Methods:
    -generateForm
    -validateForm from addData
    -submitForm

    Class: deleteData
    Methods:
    -generateForm
    -submitForm

    Class: listData
    Methods:
    -listData

    Or would I just manually code the form, manually validate everything, then just do a query using the class? The same would go for edit/delete/list options. If i made a general class then I could use it for anything which would be helpful, but i don't know how efficient/reusable it would actually be.

    If anyone has any links to good articles on the net which give a basic introduction to OOP and is easy to understand, could you please post them. Finally, what does the & operator do? Something to do with references but I've no idea. I saw a thread on it once, but i forgot to book mark it and you can't search the forums using less than 3 character search queries.

    Thanks
    -Peter

  2. #2
    SitePoint Member XiXora's Avatar
    Join Date
    May 2002
    Location
    Birmingham, UK
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    i've never really got used to oop :/
    i try to make what you are doing but having a hard time myself

  3. #3
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Know what you mean - think the problem with getting started in OO is knowing where to begin - personally found design patterns really helpful (but that's for later perhaps).

    Begin with the last first, the & operator I've tried to sum up here.

    Think the first thing to consider is how to "layer" your application - building in tiers (try this for starters).

    If you think of your application as having 5 tiers, for example;

    - Presentation GUI: web browser (HTML parsing etc.)
    - Presentation Logic: PHP (HTML rendering etc.)
    - Business Logic: PHP (form validation, data manipulation etc.)
    - Data access tier: PHP (e.g. PEAR:B or Eclipse)
    - Data tier: MySQL, PostGreSQL

    Each tier shouldn't do things that belong in another tier. For example a class shouldn't both connect to a database, run queries, validate data and render HTML.

    Taking the above model, it's probably easiest to start from the bottom up. The Data Tier is no problem. For the Data Access Tier, write a class for a connecting to the database (doesn't necessarily have to be abstract - if your design is write, adding db abstraction can come later).

    Once you've got a simple class for accessing the database (call it DataAccess), put together another class for running the queries and invoking validation e.g.;

    PHP Code:
    class ArticleModel {
        function 
    add () {

        }
        function 
    edit () {

        }
        function 
    delete () {

        }
        
    // Lists a number of articles
        
    function list () {

        }
        
    // For a single article
        
    function view () {

        }

    The above class does not render any HTML - it just receives data from the Presentation Logic does something (e.g. validate) then puts it in the database (and vice versa). PS - for an idea on validation try The Strategy Pattern.

    Once you've got this far, do the rest of the work with normal procedural PHP, rendering the HTML but accessing ArticleModel e.g.

    PHP Code:
    <?php
    /* listarticles.php */

    // Create database connection
    $dBAccess=& new DataAccess ($host,$user,$pass,$dbName);

    // Instantiate the "Model" class, passing it the database connection
    $articleModel=& new ArticleModel($dBAccess);

    echo (
    '<h1>Article List</h1>');

    // Passing the entire result is not a good idea
    // but we'll do it here to keep the example easy
    $articleList=$articleModel->list();

    foreach (
    $articleList as $article) {
         echo ( 
    $article['title'] .'etc...' );
    }
    ?>
    Once this start to make sense, it's time to think about using OO to render HTML (which gets more complicated methinks).

    Couple more articles I've done which I hope are useful and have more examples: MVC Pattern and Data Access Object Pattern

    Phew - more than enough to be going on with.

  4. #4
    SitePoint Zealot
    Join Date
    Oct 2002
    Posts
    158
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The only problem I see with the method that you propose is that that once you start getting deep into creating classes to interact with/use the edit, add, and delete classes you will most likely need to provide more specific functionality than what you anticipated for these classes.

    For instance, let's say you have an Article class, as well as a Comment class....both are relatively similar, but... let's also say that you for articles you want to have a count column that keeps tally of how many times that article has been viewed, or even a count column for the number of comments that the article has...

    In this case it may be better to do something like this...
    PHP Code:
    class Article
    {

      function 
    addArticle() {
          ...
      }

      function 
    deleteArticle($id) {
          ...
      }

      function 
    updateCommentCount($id) {
          ...
       }

      function 
    updateViewCount($id) {
          ...
       }

    Comment class
    PHP Code:

    class Comment
    {
      function 
    addComent($id) {
        
    $sql "INSERT INTO comments (
                                aid, 
                                comment
                   ) VALUES (
                                
    $id
                                '
    $comment'
                   )"
    ;
        
    $this->db->query($sql);
        
    $article =& New Article;
        
    $article->updateCommentCount($id);
      }

    In doing things the way you suggested, you would end up mixing lots unrelated code in to account for the different type of incoming data...

    Another thing to consider is that what if comments and articles need totally different validation routines?

    HTH

  5. #5
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey,

    Thanks for the replies. HarryF, those were good articles you posted, and a nice site! I get the & operator now, it's sorta like a pointer in C++.

    Thanks for separating the different layers out for me, it helps understanding it a bit easier, and the article backed it up. IFrom the reason both of you gave, I see that it would definately be easier, and better if I separate the layers so the article class doesn't actually have anything to do with displaying the content really.

    Does anyone have an suggestions or ideas on very simple little OOP scripts I can write to get into this. I think in this situation, it might be better to were a life vest before diving into deep end. I just need an idea on what I can build a script about, so i can get to work.

    Thanks Again,
    -Peter


    EDIT: I'd also like to ask, for a database class for accessing different types of databases, I guess it would be suitable to create an abstract class, then have another class inherit some methods, and override others. However, how would i design a program that would be able to switch between databases easily.

    Using functional programming I personally would do something like:

    PHP Code:
    define("DB_TYPE",1);

    function 
    connect($username,$password,$host,$dbname) {
        if(
    DB_TYPE == 1) {
             
    // mysql connect and database select
        
    } else {
            
    // postgresql  connect and database select
        
    }

    However, using OOP, how would i go about this? I was thinking you could do the exact same thing, but i don't know if thats suitable or not.

    -Peter
    Last edited by petesmc; Dec 30, 2002 at 01:40.

  6. #6
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also, I'd like to ask, how do you usually go about getting/setting variables from outside the object. Do you call a method of the class to set a variable or do you just set it by doing something like $object->color = 'red';?

    One method I could think of would be to do some thing like this:

    PHP Code:
    <?php
    class GetSet {
        var 
    $color;

        
    // Constructor
        
    function GetSet ($fColor 'green') {
            
    $this->color $fColor;
        }

        
    // Get/Set Method
        
    function color ($fColor "") {
            if(!empty(
    $fColor)) {
                
    $this->color $fColor;
            } else {
                return 
    $this->color;
            }
        }
    }

    $objColor = new GetSet;
    echo 
    $objColor->color(); // Prints green
    $objColor->color("red");
    echo 
    $objColor->color(); // Prints red
    ?>
    Or you could take it further, and create a general method, however, this doesn't allow for private/protected variables.

    PHP Code:
    <?php
    class GetSet {
        var 
    $color;

        
    // Constructor
        
    function GetSet ($fColor 'green') {
            
    $this->color $fColor;
        }

        
    // Get/Set Method
        
    function setVar ($fVarName$fVarVal "") {
            if(!empty(
    $fVarVal)) {
                
    $this->$fVarName $fVarVal;
            } else {
                return 
    $this->$fVarName;
            }
        }
    }

    $objColor = new GetSet;
    echo 
    $objColor->color// Prints Green
    echo $objColor->setVar('color'); // Prints green
    $objColor->setVar('color',"red");
    echo 
    $objColor->setVar('color'); // Prints red
    ?>
    Which do you recommend? Or do you recommend another method?
    -Peter

  7. #7
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One of the principles of Object Oriented Programming is 'encapsulation'. This means, amongst other things, that the internal state of an object can only be changed by calling its methods. It also means that all properties of an object should be regarded as private.

    Because of this principle, you should never set properties of an object directly, but with get and set methods. Personally, I prefer to use something like this:

    PHP Code:
    class MyObject
    {
     var 
    $color '';

     function 
    setColor($color)
     {
      
    $this->color $color;
     }

     function 
    getColor()
     {
      return 
    $this->color;
     }
    }

    // Example of usage
    $obj = new MyObject;
    $obj->setColor('red');
    echo 
    $obj->getColor(); // outputs 'red' 
    I think that with get*() and set*() methods like this, it's immediately obvious what your code does. You can't tell from a method name like 'color()' what it does, but it's obvious what getColor() and setColor() do.

    Another reason you should use get and set methods is this. Say you have a Company object with a property 'employees' that is an array. If you wanted to add an Employee to the company, you could do it like this:

    PHP Code:
    $company = new Company;
    $company->employees[] = new Employee('Joe Dev'20000); // just for example, name and salary 
    But what if you later decide that you don't want the employees array to be an integer indexed array (which is what you get if you use $company->employees[] = ...) but an array that is indexed with the employee's name (i.e. $company->employees['Joe Dev'] = ...). A reason for doing this could be that it's faster to look up one of the Company's Employees by name this way. You would have to change all the code that uses the Company class to add employees.

    So here comes the advantage of an addEmployee() method.
    PHP Code:
    // The old situation
    class Company
    {
     var 
    $employees = array();
     
     function 
    addEmployee(&$employeeObject)
     {
      
    $this->employees[] =& $employeeObject;
     }
    }

    // And now the new situation
    class Company
    {
     var 
    $employees = array();

     function 
    addEmployee(&$employeeObject)
     {
      
    $this->employees[$employeeObject->getName()] =& $employee;
     }

    So if you use get* and set* methods from the start (addEmployee can also be considered a set-method), you avoid code changes caused by a new situation like described above.

  8. #8
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    Could you just clarify if there is a difference between private and protected variables?

    I agree that the get/set methods immediately make it obvious what your ode is doing, however, I also think combining them into one (note: not a general method, but one method for each variable instead of two) is also viable. The same goes for your employee example.

    If Zend2 contains private variables then we should use get/set methods correct? If so, then it'd be an added benefit to use them now, even though they aren't required at all.

    -Pete

  9. #9
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    EDIT: I'd also like to ask, for a database class for accessing different types of databases, I guess it would be suitable to create an abstract class, then have another class inherit some methods, and override others. However, how would i design a program that would be able to switch between databases easily.
    Think the main thing is to reduce the number of times you identify the specific database class. If you look at that DAO article again, the DataAccess class is only specifically named in index.php - after that it's dealt with by all other classes using it's reference.

    If you look at Vincents Eclipse library, you'll notice all his database access classes have the same API - that is the methods to connect to the database and run queries are all the same. So in index.php, you can easily modify it e.g.;

    PHP Code:
    $dataAccess=& new MyDatabase($dbame,$host);

    $dataAccess->connect($user,$pass); 
    Switching to PostGre for example is simply;

    PHP Code:
    $dataAccess=& new PgDatabase($dbame,$host);

    $dataAccess->connect($user,$pass); 
    That's it. Whether you want to wrap that in a function with a switch or some kind of "factory" class, I don't know - how often do you swap databases?

    My understanding of private and protected (in terms of Java) is;

    private - can only be accessed by the class they're declared in - that means child classes can't directly access them

    protected - can only be accessed by the class itself, it's children or classes in the same package (packages are groups of classes - not something PHP uses.

    As a general rule of thumb, I think it's worth providing a seperate set and get method for every variable you declare in a class, at the point where you design the class itself. Looking at Eclipse again, Vincent divides his methods into three groups (which is a useful grouping I think) - CONSTRUCTORS (generally theres only on constructor in a PHP class), ACCESSORS (provide the external interface to the class - the get and set methods we're talking about for example) and MANIPULATORS (methods which "work on" the variables in the class which are generally used only within the class itself, invoked by the CONSTRUCTOR). Dividing methods into three groups like this I've found makes using classes extremely easy - the argument "design is dead" probably holds true for programming these days.

  10. #10
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the reply!

    Regarding the database access, I think I understand what you mean now. By creating a class called say 'Database' defining a few variables and methods, then creating another class(es) which inherit the properties / methods of the parent class, i can just change which class i'm using and it automatically changes databases.

    Something like this I'd say:

    PHP Code:
    <?php
    class Database {

        var 
    $host;
        var 
    $username;
        var 
    $password;
        var 
    $dbname;
        var 
    $link;

        function 
    connect() { }
        function 
    disconnect() { }
        function 
    clearmem() { }

    }

    class 
    MySQL extends Database {

        function 
    MySQL($user,$pass,$host,$dbname) {
            
    $this->username $user;
            
    $this->password $pass;
            
    $this->host $host;
            
    $this->dbname $dbname;
            
    $this->link 0;
        }

        function 
    connect() {
            
    $this->link mysql_connect($this->host,$this->user,$this->pass);
            
    mysql_select_db($this->dbname);
        }

        function 
    disconnect() {
            
    mysql_close($this->link);
        }

        function 
    clearmem() {
            
    mysql_free_result($this->link);
        }
    }

    class 
    PgSQL Extends Database {

        function 
    PgSQL($user,$pass,$host,$dbname) {
            
    $this->username $user;
            
    $this->password $pass;
            
    $this->host $host;
            
    $this->dbname $dbname;
            
    $this->link 0;
        }

        function 
    connect() {
            
    $connectStr "host=" $this->host " user=" $this->username " password=" $this->password " dbname=" $this->dbname;
            
    $this->link pg_connect($connectStr);
        }

        function 
    disconnect() {
            
    pg_close($this->link);
        }

        function 
    clearmem() {
            
    pg_free_result($this->link);
        }
    }

    // Now I can easily call this by
    $DBMySQL = new MySQL("username","password","localhost","dbname");
    $DBMySQL->connect();
    // Open another if i want to
    $DBPgSQL = new PgSQL("username","password","localhost","dbname");
    $DBPgSQL->connect();

    // Do any queries, like transferring between databases...
    $DBMySQL->clearmem();
    $DBMySQL->disconnect();
    $DBPgSQL->clearmem();
    $DBPgSQL->disconnect();

    ?>
    That's really my first try at some useful OOP code so tell me what you think about it. Am i following the concepts of
    OOP? I've got no idea if that code would actually work, just trying to get started. I know i didn't put any get/set methods in there, but it was my first attempt really, and i just want to get the ideas. BTW, would you generally use the get/set methods WITHIN/and outside the class, or just outside like

    PHP Code:
    // Outside the class
    $classa = new classa();
    $classa->setName("Name");

    //Inside/Both
    class classa {

        var 
    $Name;

        function 
    setName($fName) {
            
    $this->Name $fName;
        }

        
    // Do this??
        
    function a() {
            
    //some code
            
    $this->Name $x
        
    }

        
    // Or do this??
        
    function b() {
            
    // some code
            
    $this->setName($x);
        }

    Finally, If i were to use 'function b' above, then how would i go about setting the variable $link in the example at the top?

    PHP Code:
    $this->setLink(mysql_connect(....)); 
    ???

    Thanks
    -Peter

    EDIT: A thought: In the top piece of code i just posted, I have connect() defined twice with the exact same code. If i defined that code in the parent class, when calling the child class, would it call the parent classes constructor assuming I removed the child class constructor?
    Last edited by petesmc; Dec 30, 2002 at 10:11.

  11. #11
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Database classes look real good. Next thing to work out is why Vincent creates a seperate class for dealing with results (I tried explaining it in the DAO article) - the object is to avoid placing a complete SQL result set in PHP's memory but rather leave MySQL to do this work (which can be a disaster when you have SELECT * FROM table ...)

    As to using set and get internally, guess that's a question of preference. The ACCESSORS are most important to get right for other code which will use the class. You could use them internally as well, which would mean you have a method like;

    PHP Code:
    // Note returns a reference...
    function & getLink() {
       return 
    $this->link;

    Then you might have;

    PHP Code:
        function clearmem() {
            
    mysql_free_result($this->getLink());
        } 
    Using set and get internally means you can change the names of declared variables without needing to modify anything but the get and set methods. Having said that, if classes and methods are kept simple (i.e. as little code as possible), should you ever need to change a variable name, it should be much work to modify the rest of the class.

    EDIT: A thought: In the top piece of code i just posted, I have connect() defined twice with the exact same code. If i defined that code in the parent class, when calling the child class, would it call the parent classes constructor assuming I removed the child class constructor?
    Only the constructor in the class that is instantiated is called (if it doesn't exist, no constructor will be called).

    The trick for using the parent constructor, should you need to, is;

    PHP Code:
    class Parent {
        function 
    Parent () {}
    }

    class 
    Child extends Parent {
        function 
    Child () {
            
    Parent::Parent();
        }

    PS - you might want to force people using your classes to use the children like;

    PHP Code:
    class Database {

        var 
    $host;
        var 
    $username;
        var 
    $password;
        var 
    $dbname;
        var 
    $link;

        function 
    connect() {
            die (
    'connect() abstract - use child');
        }
        function 
    disconnect() {
            die (
    'disconnect() abstract - use child');
        }
        function 
    clearmem() {
            die (
    'clearmem() abstract - use child');
        }

    This is the PHP workaround for abstract classes in Java, I guess.

  12. #12
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey,

    I'll work on the results class tomorrow after I get some much needed sleep. Didn't notice that mysql_free_result() refers to a result not a connection resource. I'll also work on the accessors tomorrow, to get it all working and looking nice.

    Referring to the constructors. Using the database code above, I removed the constructors from both the MySQL and PgSQL class, and placed a common constructor in the Database Class. I called the MySQL class the same way as i did in the code above, and then created the object and printed out the values of username/password/host/dbname which should be stored in the 'Database' object. They all printed what they should have, and it also printed out a little message i left in the parent constructor. Could you explain why it would be doing this?

    This is the revised code I'm using, i remove the pgsql class for simplicity:

    PHP Code:
    <?php
    class Database {

        var 
    $host;
        var 
    $username;
        var 
    $password;
        var 
    $dbname;
        var 
    $link;

    function 
    Database ($user,$pass,$host,$dbname)  {
            
    $this->username $user;
            
    $this->password $pass;
            
    $this->host $host;
            
    $this->dbname $dbname;
            
    $this->link 0;
            echo 
    "Parent!";

        function 
    connect() { die("abtract"); }
        function 
    disconnect() { die("abtract"); }

    }

    class 
    MySQL extends Database {

        function 
    connect() {
            
    $this->link mysql_connect($this->host,$this->username,$this->password);
            
    mysql_select_db($this->dbname);
        }

        function 
    disconnect() {
            
    mysql_close($this->link);
        }

    }


    // Now I can easily call this by
    $DBMySQL = new MySQL("myuser","mypass","localhost","mydatabase");
    $DBMySQL->connect();

    echo 
    $DBMySQL->username;
    echo 
    $DBMySQL->password;
    echo 
    $DBMySQL->dbname;

    $DBMySQL->disconnect();

    ?>
    Thanks
    -Peter
    Last edited by petesmc; Dec 30, 2002 at 11:06.

  13. #13
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    They all printed what they should have, and it also printed out a little message i left in the parent constructor. Could you explain why it would be doing this?
    Interesting. Could be I'm wrong and that if the child doesn't have a constructor, the parent gets called instead. Not sure that's a good thing... Will check that out later (I think I'm right in saying Java doesn't do this).

  14. #14
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hm, Okay. I'll check it up as well.

    -Peter

  15. #15
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I couldn't find anything about Java in my books, they didn't go into detail on inheriting constructors. In C#, if the child class has no constructor, then a parent constructor will be called.

    My PHP books say, in PHP, a child class only inherits a parent constructor as a regular method. However, on this page, it says it uses the parents constructor if no child constructor is defined.

    -Peter
    Last edited by petesmc; Dec 30, 2002 at 11:08.

  16. #16
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Regarding Java, the very bottom of this page says "child classes can borrow constructors from their parent classes" which I think means, a child class can invoke a parent constructor, but if a default isn't specified, the parent isn't used.

    -Peter

  17. #17
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I just tested a really simple couple of classes and the child definately gets the parent's constructor if ithe child does not have one.This goes against Programming PHP by O'Reilly, perhaps it is a by-the-version thing. Easy to figure out what your version does:
    PHP Code:
     class Italianfood 
    {
        function 
    Italianfood()
        {
            echo(
    'Italianfood constructor!');
        }
    }
    class 
    Pizza extends Italianfood
    {
        function 
    reality()
        {
            echo(
    'Reality is, Pizza is more American food');
        }
    }
    $ob = new Pizza(); // displays Italianfood constructor on my computer 
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  18. #18
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    According to the page above, this should happen in PHP4, but not in PHP3. I personally think this is helpful, however, with limited knowledge of OOP concepts at the moment, I don't know if they are wise.

    -Peter

  19. #19
    SitePoint Member
    Join Date
    Dec 2002
    Posts
    16
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My data abstraction class:

    http://www.odan.net/source/showsource.php?fn=datasource

    With mine, I only have two functions read and write. These two functions are responsible for handling all types of data, whether it be file access or database access. You can also use the syntax:

    PHP Code:
    # For file access;
    $contents DataSource::read("thisfile.txt");

    # SQL statement;
    $sql "select * from test;";

    # Database connection options;
    $options = Array("user"=>"***","password"=>"***","database"=>"dbtest");

    # MySQL connection;
    $rows DataSource::read($sql,$options,DS_TYPE_MYSQL);

    # --- or for postgresql;
    $rows DataSource::read($sql,$options,DS_TYPE_PGSQL); 
    When doing db access, it returns the /whole/ result in the array. It's stored as $array["result"].

    At the same time, one could use the write method to create files or do database inserts/updates/etc.

  20. #20
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Really like the concept! Similar to the new streams IO functionality.

    Three questions though;

    How do you avoid loading the complete contents of "SELECT * FROM table" into PHP variables?

    Have you considered looking at functions like func_get_args() and the [http://www.php.net/overload]overload extension[/url]? - might be useful...

    Why branch PHP 3.x?

  21. #21
    <? echo "Kick me"; ?> petesmc's Avatar
    Join Date
    Nov 2000
    Location
    Hong Kong
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    HarryF, you said this earlier as well, but i didn't quite understand; avoiding loading entire result sets into a variable.

    What other method is there? All i can think of is, do the query assign that to a variables, do a loop with mysql_fetch_array() and set that to a variable so you can print the results out.

    -Peter

  22. #22
    SitePoint Member
    Join Date
    Dec 2002
    Posts
    16
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How do you avoid loading the complete contents of "SELECT * FROM table" into PHP variables?

    Are you asking is it /possible/ to not get the entire result? If so, the answer is no, not with the current way it's written. You'd have to separate the connection/commands and all that good stuff.


    Have you considered looking at functions like func_get_args() and the overload extension? - might be useful...
    I use func_get_args() in the write function, but not in the read function. It wasn't really needed IMO.


    Why branch PHP 3.x?
    I just read over the Zend license again. I guess I was drugged or something, when I read it the first time. It seems that I /can/ branch from PHP4. That's even better! Maybe I'll just wait until PHP5 is released then branch that one.

  23. #23
    ********* Callithumpian silver trophy freakysid's Avatar
    Join Date
    Jun 2000
    Location
    Sydney, Australia
    Posts
    3,798
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It is well known that I have a love/hate relationship with object-oriented programming - however a big CMS project sounds like it could benefit from an OO design.

    I have only skimmed over the very detailed posts presented so far, however, Pete, one thing that stuck out like a sore thumb about your design ideas is that they are not very object oriented yet.

    One thing that is crucial to developing an OO system is that before one can write a single line of code, one must have designed the object model - the framework of the objects that make up the system. In fact before you design the system you need to do some OO analysis and identify the objects that make up the problem before even worrying about the technical system.

    Don't think about OO in terms of classes. Think about OO in terms of objects. As someone pointed out quite eloquently earlier, OO is about encapsulation. If we identify the objects, we can identify what each object needs to be able to do and which other objects it needs to interact with.

    ANALYSIS
    Looking at Harrry F's 5-tier model. Always start at the business tier. What does this system need to do in human terms (not technical terms)?

    Who will be using this system and what will they be using it to achieve?

    So a quick brainstorm might reveal a whole lot of candidate objects that we need to analyse and consider might make up this system:

    Administrator (user) - there might need to be an administrator with special tasks for the maintenance of the system.
    Staff (user) - a person who is able to add/delete/edit content

    Member (user) - maybe this system will allow members to log in and personalise their view of the site?

    Whoa! - content. What content?
    - Articles?
    - Events?
    - Photos?
    - Discussion threads?

    Next, once you have analysed what things, people, "objects" make up the system, you need to work out what each object needs to do - what behaviour it needs, which will eventually become the methods. You will later on need to identify what data an object needs to know about itself in order to do its job.

    Remember the golden rule of encapsulation. The motto of an object is "I do it myself". If you need to change the state of an article, for example. You need to change it's publish date, or edit it's content, then the object needs to be able to achieve this itself.

    Article::setPublishDate($date)
    Article::setContent($content)

    User::login($userid, $pword)
    User::changePassWord($pword)

    Hmm, this is interesting, there appear to be some patterns here. In our system design it might be usefull to have an abstract business tier class "User" which might specify some methods such as, log-in, change-password. They would all be methods that different types of user (Admin, Staff, Member)(derived classes) would need in common.

    Same with Content. All Content probably needs an Author or owner, a published date, etc. So perhaps in the final design Content will be an abstract base class from which Article, Event, Photo-gallery are derived?

    Anway, these are just some thoughts and might not be relevant to the design or the problem at all. I'm, just trying to demonstrate the importance of analysing the problem from an OO perspective before you go diving into the more detailed layers such as the data abstraction layer.

    For example, while I identified that a User must be able to log in above, we haven't worked out the technicalities of this at this stage of the analysis and design. Most likey we will need to query the database to check the userid and password. But this can come later when we start designing the system in more detail and add in the database layer and the interaction between the business objects and the data objects.

    Start general and move toward the specific.

    Analyse the "business case" - and design the business logic layer.

    It often helps to design or prototype the human interface early on too.

    Then work towards the more technical system requirements such as the data layers.

    If you don't mind waiting a week, I will come back to this forum and post some general (non-language specific) OO links.

    Last edited by freakysid; Jan 11, 2003 at 06:51.

  24. #24
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Great post Sid! Was typing while you posted...

    HarryF, you said this earlier as well, but i didn't quite understand; avoiding loading entire result sets into a variable.

    What other method is there? All i can think of is, do the query assign that to a variables, do a loop with mysql_fetch_array() and set that to a variable so you can print the results out.
    It's really Vincent you have to thank for pointing it out but basically when you write purely procedural code, you probably never have this problem, as you use mysql_fetch_array() on each row then spit our the results into HTML straight away.

    When you start messing with classes though, it's common to load the whole lot into an array then pass everything to the next class to render HTML - that's alot of data in memory.

    If you look at Vincents Eclipse, he makes sure that never more than a row at a time is called from the database. I've explained it again here - look for explaination after the DataAccessResult class.

    Are you asking is it /possible/ to not get the entire result? If so, the answer is no, not with the current way it's written. You'd have to separate the connection/commands and all that good stuff.
    That's exactly it. It might be worth research Iterator patterns or examine Eclipse. The object is to be able to do something like this;

    PHP Code:
    # For file access;
    $dataSource_=_DataSource::init("thisfile.txt");

    # SQL statement;
    $sql_=_"select * from test;";

    # Database connection options;
    $options_=_Array("user"=>"***","password"=>"***","database"=>"dbtest");

    # MySQL connection;
    $dataSource_=_DataSource::init($sql,$options,DS_TYPE_MYSQL);

    # --- or for postgresql;
    $dataSource_=_DataSource::init($sql,$options,DS_TYPE_PGSQL);

    while ( 
    $set$dataSource->read() ) {
        
    print_r($row);

    Note - please ignore underscores _ - something wierd about the forums here...

    Please don't take that as criticism. Really like your concept - treat all data sources as being the same.
    Last edited by HarryF; Jan 11, 2003 at 06:55.

  25. #25
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This has got me thinking... final brainwave for today;

    When connecting to a database, we can use SQL to specify the data we want. But what about files and XML?

    For a file the "query" could be two patterns (preg) marking the start and end of a block of data which repeats itself in a file (a "row" in the file).

    For XML, we could use XPath in the DOMXML extension to specify a block of XML to fetch as a row...

    This has great potential methinks...


Bookmarks

Posting Permissions

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