0

Ok, following from my previous thread (now resolved) i want to convert and use namespace.

headScript.php:

<?php

class headScript
{
    public function connection()
    {
        try
        {
            $dbh = new PDO("mysql:host=localhost;dbname=roundth4_rtb2", 'root', ''); // Dev
            return $dbh;
        }
        catch(PDOException $e)
        {
            echo "Error :- " . $e->getMessage();
            die();
        }
    }

    public function headLoad()
    {
        $cxn = $this->connection()->prepare("SELECT scriptCode FROM head_scripts WHERE active != '0'");

        $cxn->execute();
        $cxn->setFetchMode(PDO::FETCH_ASSOC);

        while($row = $cxn->fetch())
        {
            print "<script>";
            print $row['scriptCode'];
            print "</script>";
        }
    }
}
?>

I'd like to remove the connection function and put this in its own file, then using namespace to pull this in. That way i have one file which can be called via namespace and i can use this function.

Am I thinking this is possible when it is not?

I have tried a few things but cant seem to get it to work.

Can anyone offer assistance?

4
Contributors
12
Replies
18
Views
5 Years
Discussion Span
Last Post by Squidge
Featured Replies
  • 2
    Atli 182   5 Years Ago

    What you are doing there has an inherent flaw. The `connection()` function will alwasy return a *new* PDO object. Unless you're somehow calling the function once and then passing that connection along into all the code that uses the database, you're likely opening one PDO connection per SQL query. That'll … Read More

0

Try this:

<?php

namespace Dbase;
class Dbconn
{
    public function conn()
    {
        return new \PDO("mysql:host=localhost;dbname=roundth4_rtb2", 'root', '');
    }
}
?>

then inside the class you can include the connection class:

<?php
require 'dbconn.class.php';
class headScript
{
    private $db;

    public function __construct()
    {
        $this->db = new Dbase\Dbconn();
    }

    public function headLoad()
    {
        $q = $this->db->conn()->prepare("SELECT scriptCode FROM head_scripts WHERE active != '0'");
        $q->execute();
        $q->setFetchMode(PDO::FETCH_ASSOC);
        $output = array();
        $i = 0;
        while($row = $q->fetch())
        {
            $output[$i]['scriptCode'] = "<script>\n" .$row['scriptCode']. "\n</script>";
            $i++;
        }
        return $output;
    }
}

$play = new headScript();
print_r($play->headLoad());

?>

and it should work. Bye!

2

What you are doing there has an inherent flaw. The connection() function will alwasy return a new PDO object. Unless you're somehow calling the function once and then passing that connection along into all the code that uses the database, you're likely opening one PDO connection per SQL query. That'll start messing with the performance of the script, and the database, quickly.

What I like to do is create a Singleton class that is available to all the code, but makes sure that only one PDO object is created and used everywhere. Consider this:

<?php
namespace organization\projectname\database;

class Database
{
    /** 
     * @var PDO The database link. 
     */
    protected static $dbLink;

    /**
     * Returns an open PDO object. This object will be shared
     * among all who call this method, so that you don't have
     * to be creating multiple connections to MySQL in the
     * same request.
     * @return PDO
     */
    public static function get()
    {
        if(self::$dbLink == null)
        {
            $dns = 'mysql:host=localhost;dbname=thedb';
            self::$dbLink = new \PDO($dns, 'user', 'pass');
            self::$dbLink->exec("SET NAMES 'utf8'");

            // This makes the connection throw exceptions when
            // errors occur. Remove it if you want to use
            // old-shcool return values for that.
            self::$dbLink->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        return self::$dbLink;
    }

    /*
     * We don't want this class to be able to spawn objects.
     * By making these two methods private, we effectively
     * prevent that from happening.
     */
    private function __construct() {
        return false;
    }
    private function __clone() {
        return self::get();
    }
}

Using this class, whenever you need a database connection in your other code you can just do:

use organization\projectname\database\Database as DB;

$sql = "SELECT stuff FROM whatever";
$stmt = DB::get()->prepare($sql);
// etc...

No matter how many times you do that, only one PDO object will exist.

Votes + Comments
Fixed my solution +100000
nice!
0

Thank you both for your suggestions. I will try this when i amhome and post back:-)

0

Tried the above and it kicks out this error

Fatal error: Class 'organization\projectname\database\Database' not found in G:\xampp_server\htdocs\classDrv_rtb\class\scripts\headScripts.php on line 17

This is the code of the script:

<?php
use organization\projectname\database\Database as DB;
#require("dbCon.php");

class headScript
{
    public function headLoad()
    {
        /*$cxn = new dbConnection;

        $cxn = $cxn->pdo();

        $stmt = $cxn->prepare("SELECT scriptCode FROM head_scripts WHERE active != '0'");*/

        $sql = "SELECT scriptCode FROM head_scripts WHERE active != '0'";

        $stmt = DB::get()->prepare($sql);

        $stmt->execute();
        $stmt->setFetchMode(PDO::FETCH_ASSOC);

        while($row = $stmt->fetch())
        {
            print "<script type='text/javascript'>";
            print $row['scriptCode'];
            print "</script>";
        }
    }
}
?>
0

You still need to include (or require) the file that contains the Singleton into the script before you try to use it.

Typically, in an application that uses namespaces extensively, you'd set up an autoloader, but in this situation that may be overkill.

0

@Atli
Thank you, still had that line commented out :)

Although i had to remove self::$dbLink->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); as this was throwing:

Fatal error: Class 'organization\projectname\database\PDO' not found in G:\xampp_server\htdocs\classDrv_rtb\class\scripts\dbconnection.php on line 31

0

O yea, sorry. Forgot to change that. That example was from an old script that didn't use namespaces.

In a script that does use namespaces, you need to specify the namespace of the classes and functions you are trying to use, or PHP will assume you are trying to use classes/functions from the current namespace. - In the case of the built-in classes and functions, they belong to the root namespace: \

So changing it to this will get it to work properly

self::$dbLink->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
0

The PHP manual defines it as Global Space, although I'm not really fond of that term. I like to think of this in terms of a hierachical structure, making the Global Space the root.

Essentially, everything in PHP 5.3+ that is not defined inside a specific namespace belongs to this Global Space. To access classes and functions that belong in the Global Space from within other namespaces, you need to prefix them with \.

0

@Atli

You have been a great help.

All though you say an __autoloader would be overkill, it would be handy to know how to use, so i think i will look into that one also.

0

Ok, so i appricate this is solved, but i though i would follow up:

compact small autoload snippet:

spl_autoload_extensions(".php");
spl_autoload_register();

However this will only function if your namespace follows a directory structure. I came across this on DreaminCode as i was looking for a very simple __autoload

Here is both the files, with the folder they are in in the head:

load_headScript.php:

<?php
// root: -> /classLib/load/load_headScript.php :
spl_autoload_extensions(".php");
spl_autoload_register();

use classLib\database\database_Connection as DB; // import namespace for code reuse

class load_headScript
{

    public function headLoad()
    {

        $sql = "SELECT scriptCode FROM head_scripts WHERE active != '0'";
        $stmt = DB::get()->prepare($sql);
        $stmt->execute();
        $stmt->setFetchMode(PDO::FETCH_ASSOC);

        while($row = $stmt->fetch())
        {
            print "<script type='text/javascript'>";
            print $row['scriptCode'];
            print "</script>";
        }
    }

}
?>

database_Connection.php

<?php
// root -> /classLib/dataBase/database_Connection.php:

namespace classLib\database; // declare namespcae

class database_Connection {
/**
* @var PDO The database link.
*/

    protected static $dbLink;

    /**
    * Returns an open PDO object. This object will be shared
    * among all who call this method, so that you don't have
    * to be creating multiple connections to MySQL in the
    * same request.
    * @return PDO
    */

    public static function get()
    {
        if(self::$dbLink == null)
        {
            $dns = 'mysql:host=localhost;dbname=roundth4_rtb2';
            self::$dbLink = new \PDO($dns, 'root', '');
            self::$dbLink->exec("SET NAMES 'utf8'");
            self::$dbLink->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        }
        return self::$dbLink;
    }

    /*
    * We don't want this class to be able to spawn objects.
    * By making these two methods private, we effectively
    * prevent that from happening.
    */

    private function __construct() {
        return false;
    }

    private function __clone() {
        return self::get();
    }

}
?>

So as long as the namespace is the same as your folder structure, and the class is the same name as what you are calling in, the simple __autoload should function. I have tried this out on a few scripts (converting a website, and admin section to namespace and OOP), and have not come across a problem yet.

HAPPY DAYS

Many thanks to Alti for the Singleton DB class :)

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.