0

I am new to PHP OOP and would like to try to nest several classes within another class, to latter call them like so:

$sql = new SQL();
$sql->Head()->Description($_SESSION['page']);
  //OR
$sql->Head()->Keywords($_SESSION['page'])
  //OR
$sql->Body()->Clients($_SESSION['client'])
  //ETC
$query = $sql->Run(); // equivalent to mysql_query("...");

As you can guess, I run into some problems and ended with this poor code:

<?php
require( $_SERVER['DOCUMENT_ROOT'] . '/#some_db_directory/database.php');
//This file contains $db['host'], $db['user'], etc...

class SQL {
    public $sql;

    public function __construct() {
        global $db;
    }

    public class Head() {

        public function Description($page) {
            return "SELECT * FROM `$db['database']`.`desciption` WHERE `page` = '$page'";
        }

        public function Keywords($page) {
            return "SELECT * FROM `$db['database']`.`keywords` WHERE `page` = '$page'";
        }
    }
}

$sql = new SQL();
echo $sql->Head()->Description('home'); //For testing
  • Is it possible to nest classes in PHP?
  • If so, how is it done?
PeeHaa
  • 71,436
  • 58
  • 190
  • 262
Omar
  • 11,783
  • 21
  • 84
  • 114
  • Possible duplicate of [php-method-chaining](http://stackoverflow.com/questions/3724112/php-method-chaining). – Hashem Qolami Nov 13 '12 at 11:03
  • I don't think you can nest-declare classes; And even if you can, a **class** is not a **class instance**, so your `$sql->Head` is still a _class_, and `$sql->Head()->Whatever` is invalid. `$sql=new SQL()` is how you **instanize** a `SQL` class. – Passerby Nov 13 '12 at 11:04

3 Answers3

1

What you are trying to do is called Encapsulation. Try google search on PHP encapsulation to learn more.

Here is a code example from http://www.weberdev.com/get_example.php3?ExampleID=4060,

<?php 

class App { 

     private static $_user; 

     public function User( ) { 
          if( $this->_user == null ) { 
               $this->_user = new User(); 
          } 
          return $this->_user; 
     } 

} 

class User { 

     private $_name; 

     public function __construct() { 
          $this->_name = "Joseph Crawford Jr."; 
     } 

     public function GetName() { 
          return $this->_name; 
     } 
} 

$app = new App(); 

echo $app->User()->GetName(); 
?>
Muthu Kumaran
  • 17,682
  • 5
  • 47
  • 70
  • I think what the OP means is PHP5 Method chaining, and adding `return $this;` at the end of each methods in class, would do the trick! – Hashem Qolami Nov 13 '12 at 11:10
1

I'm assuming that database.php is a database class. In that case you could do something like this.

head.php

Class Head{
    private $_db;
    private $_dbName;

    public function __construct($db, $dbName){
        $this->_db = $db;
        $this->_dbName = $dbName;
    }
    public function Description($page) {
       $results = $this->_db->query("SELECT `text` FROM `$this->_dbName`.`description` WHERE `page` = '$page'");
       return '<meta name="description" content="' . $results['text'] . '">';
    }

    public function Keywords($page) {
       $results = $this->_db->query("SELECT * FROM `$this->_dbName`.`keywords` WHERE `page` = '$page'");
       $keywords = array();
       foreach($results as $result){
           array_push($keywords, $result['word']);
       }
       return '<meta name="keywords" content="' . implode(',', $keywords) . '">';
    }
}

sql.php

require( $_SERVER['DOCUMENT_ROOT'] . '/#some_db_directory/database.php');
// Require head class file
require( $_SERVER['DOCUMENT_ROOT'] . '/#some_db_directory/head.php');   

Class SQL{
    public $Head;

    public function __construct($dbName){
        global $db;
        $this->Head = new Head($db, $dbName);
    }
}

You would then pass the name of the database into the SQL class (which propogates through to the Head class).

// Require the sql class file
require( $_SERVER['DOCUMENT_ROOT'] . '/#some_db_directory/sql.php');
$sql = new SQL('mydatabase');
echo $sql->Head->Description('home');

Again note that your database class might not return results the way I'm using them here. You will have to modify this to work with your particular database class.

Community
  • 1
  • 1
Pastor Bones
  • 7,183
  • 3
  • 36
  • 56
  • I got lost in `head.php` @line 10, with the use of `_db->query...`. My $db array only has connection info >_< (host, user, password) . Although I would not mind creating a database class – Omar Nov 14 '12 at 08:53
  • @Omar ah, I was assuming $db was a database class already connected... check http://phpclasses.org they have alot of user contributed classes or what I prefer is [idiorm/paris](http://j4mie.github.com/idiormandparis/) a mysql ORM/AR. – Pastor Bones Nov 14 '12 at 10:38
  • My very first class file, was a database file. I wonder if I can modify it, to make it work with your example?: http://stackoverflow.com/questions/13376356/how-to-create-improve-database-php-oop-class-with-all-full-functions/13376663#comment18266724_13376663 – Omar Nov 14 '12 at 10:42
  • I wouldn't re-invent the wheel (except merely for educational purposes). A community developed ORM or Active Record implementation is tested and can save alot of time developing for more important things :P – Pastor Bones Nov 14 '12 at 10:44
  • Since I do not have a database class that would work with your example, what/how to modify your code? – Omar Nov 14 '12 at 10:46
  • instead of `$this->_db->query(`... would be `$this = mysql_query(..`? – Omar Nov 14 '12 at 10:48
0

Try it like this

<?php
require( $_SERVER['DOCUMENT_ROOT'] . '/#some_db_directory/database.php');
//This file contains $db['host'], $db['user'], etc...

class SQL {
    public $sql;
    private $_head;

    public function __construct() {
        global $db;
        $_head = new HeadClass();
    }

    public function Head() {
        return $this->_head;
    }
}

class HeadClass { // Class cannot have a public access modifier

    public function Description($page) {
        return "SELECT * FROM `" . $db['database'] . "`.`desciption` WHERE page = $page";
    }

    public function Keywords($page) {
        return "SELECT * FROM `" . $db['database'] . "`.`keywords` WHERE page = $page";
    }
}

$sql = new SQL();
echo $sql->Head()->Description('home.html');
?>

I am moving the class declaration outside the class and creating an instance of the class with in SQL. This is then made available via the Head() function.

Note: For body you will need to create a separate class and use a reference in the SQL class to it like I have done for head.

Kami
  • 19,134
  • 4
  • 51
  • 63
  • what do you mean by -ve? **This is the error:** Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in /home/content/81/10038181/html/_tmp/nested-class.php on line 23 – Omar Nov 14 '12 at 09:03
  • Joys of copy paste code - your original had more than one error in it. Have updated the answer with the correct code. – Kami Nov 14 '12 at 18:49
  • Fatal error: Call to a member function Description() on a non-object on line 32 – Omar Nov 15 '12 at 11:44