Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

PHP

Derrick Lee
Derrick Lee
7,743 Points

[PHP] Calling DB function in another DB function

Hey guys, I'm having problems with the below code which I improvised from the "Using PHP with MySQL" topic.

Here are the two functions

function retrieveProductBySlug($productSlug) {

    require_once ("database.php");

    try {
        $results = $db->prepare("SELECT * FROM products WHERE productSlug = ?");
        $results->bindParam(1, $productSlug);
        $results->execute();
    } catch (Exception $e) {
        header("Location: " . BASE_URL . "not-found?error=database");
        exit();
    }

    $product = $results->fetch(PDO::FETCH_ASSOC);

    // If product is empty/false, return the product
    if ($product === false) {
        return $product;
    }

    $product["productFeatures"] = retrieveProductFeaturesByProductSKU($product["productSKU"]);

    return $product;
};
function retrieveProductFeaturesByProductSKU($productSKU) {
    require_once ("database.php");

    // Load the product features into the product variable
    try {
        $results = $db->prepare("SELECT featureTitle 
                                FROM productFeatures pf
                                INNER JOIN features f ON pf.featureID = f.featureID
                                WHERE productSKU = ?
                                ORDER by f.featureID");
        $results->bindParam(1, $product["productSKU"]);
        $results->execute();
    } catch (Exception $e) {
        header("Location: " . BASE_URL . "not-found?error=database");
        exit();
    }

    while ($row = $results->fetch(PDO::FETCH_ASSOC)) {
        $productFeatures[] = $row["featureTitle"];
    }

    return $productFeatures;
}

**The Error Code **

[13-Mar-2014 08:24:11 Europe/Berlin] PHP Notice:  Undefined variable: db in /Applications/MAMP/htdocs/inc/model.php on line 71
[13-Mar-2014 08:24:11 Europe/Berlin] PHP Fatal error:  Call to a member function prepare() on a non-object in /Applications/MAMP/htdocs/inc/model.php on line 71

Where line 71 refers to "$results = $db->prepare("SELECT featureTitle"

Derrick Lee
Derrick Lee
7,743 Points

In the video tutorial, Randy showed us how to do this by combining both functions into one. But by being a neat freak, I needed to separate them so it looks neater. But I'm having this error whenever I do something like that.

8 Answers

Mike Baxter
Mike Baxter
4,442 Points

I think the problem is using require_once; you should just use require. You need to load the "database.php" file whenever you intend to use it, but "require_once" prevents you from doing that. To be honest, I'm not sure why that works, but it does. I'm not sure why it has to be included in the local scope for each use, why it doesn't persist across functions. Maybe the database connection closes and needs to be re-established?

Derrick Lee
Derrick Lee
7,743 Points

That solved my problem. Thank you! Hopefully someone can explain why?

hi there, your code looks fine but you need to globally require your database connection.. not inside the function

 $db = new PDO();.

 function retrieveProduct ($parama)
{
   global $db;
   // rest of code
}

php is not recognizing your require statement because of the local scope of your database inside the function ... I believe that should do the trick . let me know if it works

Hello,

A little late in the game I know, but another thing you can do to prevent having to include the database file over and over again or even declare a global variable in each function is to make what you are using a constant. Constants can be used throughout your code once you include it once and gets injected into functions and classes automatically. I use constants all the time in the applications I write and not only does it solve this type of issue, you can also rest assure that your constant will not and cannot change no matter what as remember, constants (once defined) cannot be modified.

Cheers!

Mike Baxter
Mike Baxter
4,442 Points

Oh really, you can do that with a database connection? I'm just wondering at what point the connection closes. (If it disconnects, you would need to re-connect, and it doesn't seem like a constant would trigger that reconnect—wouldn't it just use the same disconnected object? Maybe I'm thinking about this wrong in terms of connecting and disconnecting. Maybe disconnecting isn't necessary?)

Mike

Yeah I misunderstood exactly what needed to be used in order for everything to work. You cannot put a live connection into a constant. I thought they were talking about the information to make the connection. To the OP I would stay away from putting the connection declaration in an external file and just declare it once on top of the PHP file and do Muhammad's way of using global. Like I said I was a little bit late into the game and the OP question had been answered, I was just putting my two cents in.

Cheers!

database connection , technically speaking pretty much disconnects automatically once its called and it finishes its job e.g. querying a database..

Mike Baxter
Mike Baxter
4,442 Points

Thanks for the info, guys! I really appreciate what you all brought to this discussion—I learned a lot!

Mike Baxter
Mike Baxter
4,442 Points

I just thought of something: What prevents someone from fishing out the name of your "database.php" connect file and borrowing it to connect to your database? All the authentication information is there, right?

Mike Baxter
Mike Baxter
4,442 Points

I just thought of something: What prevents someone from fishing out the name of your "database.php" connect file and borrowing it to connect to your database? All the authentication information is there, right?

Hi Mike, Thats where you need to be a little clever about where you store this information. That comes under the security.. like for example this is what i will do ,

- config.php
--- public_html
----------- css
----------- img
----------- js
--------- includes
-------------- database.php

Now if your config file should contain values i.e CONSTANTS like

    define( "DB_USER", " admin");
   define( "DB_PASSWORD", " admin");
   define( "DB_HOST", " localhost");
   define( "DB_NAME", " mydatabase");

Now in your database.php you can require the config.php and use the defined constants as

    require_once ('../../config.php');

Notice the structure of the files. When you upload your website to a hosting account i.e. domain, the all of your files are in the root directory. so when you put your file outside the root i.e. public_html or www then its rather more secured. you can also look into the permissions as well . hope that helps . ALi

Mike Baxter
Mike Baxter
4,442 Points

Thanks Muhammad! That's really helpful!