You are trying to call a query() method on the Database class. While that class contains a mysqli object in its $connection property, it does not expose the query() method of that mysqli object.
Given your current code, you could drill further into the object structure to call query() directly on the mysqli, but this is messy.
// Call the query() method directly on the connection
$result = $this->mysqli->connection->query( "SELECT shops.*, shops.id AS shop,SUM(price)...
I don't like this approach because it requires that your classes know more about the inner workings of the Database class than they probably should. It couples them too tightly.
As an alternative, you could create a query() method in the Database class that wraps the necessary functionality of the mysqli object within it.
class Database {
function __construct(){
$this->connect();
}
public function connect(){
$this->connection = mysqli_connect(SERVER, USERNAME, PASSWORD, DATABASE);
}
// Expose a query() method that calles the inner mysqli's query
public function query($sql) {
return $this->connection->query($sql);
}
}
This would allow you to pack in more functionality, such as querying and fetching all result rows in one method call:
class Database {
//....
// A more featured query() that returns the
// rows as an array
public function query($sql) {
$result = $this->connection->query($sql);
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
// Return an array of all the rows fetched from the query
return $rows;
}
}
If you do it this way, you should be able to call $this->mysqli->query("...") as you originally attempted and either get back the result resource with the simple version, after which you must fetch in the code yourself, or get back an array of associative result rows in the more featured version.
Creating these kinds of database wrapper classes can get unwieldy rather quickly though. Think carefully about what aspects of the mysqli object you want to expose to the other classes in your application. It's not a good idea to go down a path of wrapping every mysqli method in your Database class. At that point, the utility of the Database class is greatly reduced and you may as well just be passing in a mysqli object directly. If you are not actively adding functionality to mysqli, it makes less sense to create another class that wraps it.
A note about the var $mysqli;... This is an old deprecated class property syntax. The var keyword is a vestige from PHP4 and its use is discouraged nowadays. In fact, it has been removed from recent PHP versions. Instead, you should declare it via the PHP5+ syntax:
// Declare as a public property
public $mysqli;
// Or better, as a private (or protected) property so it cannot
// be accessed outside the Main class' own methods
private $mysqli;
In your question title, you mentioned injection. Your class doesn't do that right now, but it would be a good idea to instantiate a Database ahead of time and inject one into the class constructors that need it.
class Main{
public $mysqli;
// Pass a database as a constructor param
public function __construct($database){
$this->mysqli = $database;
}
Then instantiate it as:
$db = new Database();
// Pass the $db to the other classes
$main = new Main($db);
Importantly, this will prevent you from opening up a separate database connection for each object you instantiate of Main and any other class you construct in the same way. Doing that can quickly use up the server's available MySQL connections.
queryhere so we can not help youquery()in the Database class must be as$this->connection->query()unless you write aquery()method to wrap it directly in theDatabaseclass. Please post the code where you're trying to callquery().