Accessing database within class

learning_brain

New Member
Messages
206
Reaction score
1
Points
0
Am I being stupid here or can you not connect to a database within a class in the same way as procedural php????

PHP:
class imageAnalysis {

   var $whatever = ........... etc.

   function imageAnalysis (){//constructor

   }

   function imageAnalysis (){
       
      //main class structure...

      require_once('http://www.qualityimagesearch.com/Connections/discountdomains.php');
        
      mysql_select_db($database_discountdomains, $discountdomains);
      $query_compImage = "SELECT * FROM IMGCOMPS";
      $compImage = mysql_query($query_compImage, $discountdomains) or die(mysql_error());
      $row_compImage = mysql_fetch_assoc($compImage);
      $totalRows_compImage = mysql_num_rows($compImage);

   }

}

I get

Warning: mysql_select_db(): supplied argument is not a valid MySQL-Link resource in /home2/qualit94/public_html/test.php on line ..........

Warning: mysql_query(): supplied argument is not a valid MySQL-Link resource in /home2/qualit94/public_html/test.php on line ...........


I can get round this problem by directly entering the login details but.... not really sure I want to do that as this will be a commercially available class referencing back to the same db.

I'm very new to classes so go easy on me! :)
 
Last edited:

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
Why do you have

function imageAnalysis

twice?

Why don't you use

__construct()

for your constructor?

Are you creating multiple instances of the class? If so, require_once might be the culprit. Second call, the file not imported.
 

learning_brain

New Member
Messages
206
Reaction score
1
Points
0
Ooops - typo when breaking down into small chunks. The constructor does have a different name...

Ref the instances, I will be requesting multiple instances, although I am only calling it once during development.

I have tried including the connection details, but the same problem.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
As the error message says, $discountdomain isn't a valid MySQL link. (You can always dump a variable if it's not what you expect, or (better yet) use an interactive debugger.) The first time the method is invoked, "discountdomains.php" is executed in the scope of the method, so any global variables defined in "discountdomains.php" are in fact local to imageAnalysis::imageAnalysis. When the function exits, the variables go out of scope and are subject to garbage collection. The next time the function is called, the file isn't included so the variable isn't defined. If you want to include "discountdomains.php" within imageAnalysis::imageAnalysis, use require or include rather than require_once.

A better approach is to use a class to manage DB connections and factory method to create them (see "Display all that would be secret while Mysql is broken" and "
PHP:
 MySQL and PHP[/URL]" for samples). That way, you can include the script once and call the connect method as many times as you want yet use as few connection objects as possible.

Giving a method the same name as a class won't cause problems in the PHP interpreter if you also have a [FONT="Courier New"]__construct[/FONT] method, but it might confuse programmers familiar with the PHP 4 constructor naming convention, which was like the C++ naming convention, wherein the constructor had the same name as the class. For that reason, it's better not to give any method the same name as the class unless you're supporting PHP 4.

Class names should be capitalized nouns and methods should be verbs. For example:

[php]class ImageAnalyzer {
    function analyze() {...}
}
 
Last edited:

learning_brain

New Member
Messages
206
Reaction score
1
Points
0
OK - thanks misson.

I have done most of what you suggest...

constructor now has a different name and class/functions are now fomratted as you suggest.

In the class_db_connect.php connection file I have this..

PHP:
<?php
$hostname_discountdomains = "XXXX";
$username_discountdomains = "XXXX";
$password_discountdomains = "XXXX";

$database_discountdomains = "XXXXX";
global $database_discountdomains;


$discountdomains = mysql_connect($hostname_discountdomains, $username_discountdomains, $password_discountdomains) or trigger_error(mysql_error(),E_USER_ERROR);
global $discountdomains;

?>

Then in the class...

PHP:
require('http://www.qualityimagesearch.com/Connections/class_db_connect.php');
		
mysql_select_db($GLOBALS['database_discountdomains'], $GLOBALS['discountdomains']);
$query_compImage = "SELECT * FROM IMGCOMPS";
$compImage = mysql_query($query_compImage, $GLOBALS['discountdomains']) or die(mysql_error());
$row_compImage = mysql_fetch_assoc($compImage);
$totalRows_compImage = mysql_num_rows($compImage);

This seems to work!!

I'm assuming there is no way to access the local variables in the connection file?? I also hope there is no reason not to disclose the database name as a global? (which anyone could access!).

I'm afraid I didn't follow your second suggestion of a db connection class... :(

Thanks for getting this far - at least I have something that works!

Richard
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
PHP:
...
$database_discountdomains = "XXXXX";
global $database_discountdomains;
A variable isn't global until declared so; you need to declare global variables before setting them. Try:
PHP:
function foo() {
    $a = "locally scoped in " . __FUNCTION__;
    echo __FUNCTION__, " local \$a: $a\n";
    global $a;
    echo __FUNCTION__, " global \$a: $a\n";
}
foo();
$a='globally scoped';
foo();
echo "global \$a: $a\n";

Then in the class...

PHP:
...
$compImage = mysql_query($query_compImage, $GLOBALS['discountdomains']) or die(mysql_error());
...
The class method is responsible for too much: fetching data from the database, handling errors, plus any image analysis... That's too many concerns. Separate them. Handle errors at the top level and create other classes to handle data access.

If you're outputting HTML, don't use die. Outputting the result of mysql_error to non-admin users discloses too much information. I feel we've been over both these points before.

I'm assuming there is no way to access the local variables in the connection file??
If the file is only included within functions, they can't be accessed outside of those functions (unless you can get a stack trace that includes the frame of a function that included the connection script, such as by causing an exception in the function or another function that it calls). Of course, it's easy enough to write a function that includes the connection script. If the file is included in global scope, the variables will be global.

I also hope there is no reason not to disclose the database name as a global? (which anyone could access!).
Anyone with read access to "class_db_connect.php" can access the information either by including the file or by reading the file directly. Locally vs. globally scoped variables gives nothing in terms of security, it's a matter of things such as readability, ease of maintenance and avoiding bugs.

I'm afraid I didn't follow your second suggestion of a db connection class... :(
Instead of storing DB connections in global variables, store them in a class. Under the hood, you can store them in class (i.e. static) variables, but this fact isn't visible outside the class, as access is mediated by class methods. The connections themselves can be of native connection types (e.g. mysql resources, PDO objects), or you can write your own that wrap or extend a native type. See the previously linked posts for incomplete samples.

Thanks for getting this far - at least I have something that works!
There's "works" as in "gives me the output I want (when everything goes well)" and there's "works" as in "doesn't break, even under maintenance." There's also "works with programmers"; since code must be developed and maintained, it should work well with the development process. As-is, the code may not do so well on the latter counts. Of course, given a finite amount of time, there might not be enough right now to make the necessary improvements. Lack of time is one good reason to use a framework.
 
Top