1

I'm having problem with global variable in PHP. I have mysqli config file which contains only following data:

$mysqli = new mysqli("localhost", "user", "pass", "db");
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

I have the following class on another file:

class user{

function username_exists($username){
    global $mysqli;
    if ($stmt = $mysqli->prepare("SELECT username FROM users WHERE username=?")) {
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->store_result();
        $count=$stmt->num_rows;
        $stmt->close();
    }
    return ($count > 0 ? true : false);
    }

    ...
    some more functions
    ...

    }

Now this works fine, but in my previous question on SO, i was told that it is a bad practice to access global variable like I'm doing in above class. So, I'm trying to pass the global variable in the constructor, in following way:

private $mysqli;
      function __construct()
      {
        global $mysqli;
        $this->mysqli = $mysqli;
      }

    function username_exists($username){
    //global $mysqli;
    if ($stmt = $this->mysqli->prepare("SELECT username FROM users WHERE username=?")) {

And I get the following error:

Fatal error: Call to a member function prepare() on a non-object in...(line number)

Can you please tell me whats problem with it and how this can be fixed? Thanks. Edit: Sorry for the spelling mistake of __construct. It was only mistake typing here, and the error isnt because of that.

Community
  • 1
  • 1
Jay
  • 10,831
  • 9
  • 26
  • 33

7 Answers7

3

Well... having global in your constructor kindof beats the point. Consider passing it in as a parameter __construct($mysqli).

  public function __construct($mysqli)
  {
    $this->mysqli = $mysqli;
  }

What you're trying to do here is called dependency injection.

Alex Ciminian
  • 11,398
  • 15
  • 60
  • 94
1

I think the problem is you misstyped __construct try changing your __cuntruct to the right name for the constructor.

The global in username_exists is also useless.

You should also write a constructor which takes the variable as argument and avoid using global completly :

class User {
     var $mysqli;

     function __construct($mysqli) {
         $this->mysqli = $mysqli;
     }

     [ ... some functions ... ]
}

You must create your object like this :

$myuser = new User($mysqli);
$myUser->prepare();
krtek
  • 26,334
  • 5
  • 56
  • 84
  • Thanks for your reply. I'm sorry I mistyped the construct, but that was not the problem. I tried using the method you described and i get 2 errors, first Warning: `Missing argument 1 for user::__construct(), called in ...` and the second error is same which i mentioned in my original post. Can you please have a look the code of my config file which I have put in original file. Thanks again. – Jay Mar 07 '11 at 16:23
  • You must pass your $mysqli variable when you create your object. I think you should read the PHP documentation about objects : http://php.net/manual/en/language.oop5.basic.php It seems to me that you don't really understand what you're doing. BTW, I updated my post with a little example on how you should create the object – krtek Mar 07 '11 at 16:29
1

Your constructor is not getting called because it is not the constructor at all

__cuntruct

should be

__construct
Shakti Singh
  • 84,385
  • 21
  • 134
  • 153
  • Probably someone trying to cancel my upvote so their answer ranks higher... Your answer is correct and was the quickest at being so. – bradenkeith Mar 07 '11 at 13:24
  • 1
    I am facing this problem on SO that someone downvote and did not respond why he did? Downvote, it is okay but care to leave comment – Shakti Singh Mar 07 '11 at 13:31
1

The code as written was not really what the others on SO were attempting to encourage you to do.

function __construct($mysql_handler){
  $this->mysql = $mysql_handler;
}

This is passing in the parameter into the object scope at construction. When you create an instance of your object, you would pass in the MySQL handle.

$mysqli = new mysqli("localhost", "user", "pass", "db");
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$u = new User($mysqlli);

Then you should be able to call mysqli member functions on the property itself.

Your constructor is also misspelled. It will only work properly with the magic method name __construct().

Dharman
  • 30,962
  • 25
  • 85
  • 135
DeaconDesperado
  • 9,977
  • 9
  • 47
  • 77
1

Couple of things. I think it would work OK if you changed __cuntruct to __construct.

You're still using the global declaration inside the username_exists function. Why not just pass the $mysqli variable in the constructor?

function _construct($mysqli) {
    $this->mysqli = $mysqli;
}

then you have no globals in the class.

Tim Niblett
  • 1,187
  • 7
  • 8
  • Thanks for the reply, however the spelling mistake was only typing here, sorry for that. I've fixed that, and also tried passing the variable in the constructor, it still gives same error. If you see my config file code above, Do i need to change anything in that? Thanks. – Jay Mar 07 '11 at 14:04
-1

Remove global $mysqli; in the function username_exists(), it does not makes sense.

The global $mysqli; is not required/does not makes sense since you want this variable to store the reference the connection IN THE CONTEXT of your object.

powtac
  • 40,542
  • 28
  • 115
  • 170
-1

change __cuntruct() to __construct()

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Muhammad Ummar
  • 3,541
  • 6
  • 40
  • 71