We help IT Professionals succeed at work.

Error in function argument

Can you please help me in that error.
screenshot.JPGscreenshot2.JPG
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once 'Credentials/credentials.php';
require_once ("Entities/CoffeeEntity.php");
$coffee = new CoffeeModel($db);

var_dump( $coffee->GetCoffeeTypes() );
var_dump( $coffee->GetCoffeeByType('sometype') );
require_once ("Entities/CoffeeEntity.php");

//Contains database related code for the Coffee page.
class CoffeeModel {

    private $db;

    public function __construct(\PDO $db) {
        $this->db = $db;
    }

    public function GetCoffeeTypes() {
        $stmt = $this->db->query("SELECT DISTINCT type FROM coffee");
		
        return $stmt->fetchAll();
    }

    public function GetCoffeeByType($type) {
        $stmt = $this->db->prepare("SELECT name, type, price, roast, country, image, review FROM coffee WHERE type LIKE :type");
        $stmt->execute(['%' . $type . '%']);
		
        return $stmt->fetchAll(PDO::FETCH_CLASS, 'CoffeeEntity');
    }

}
?>

Open in new window


<?php

require_once 'Controller/CoffeeController.php';
$coffeeController = new CoffeeController();

if(isset($_POST['types']))
{
    //Fill page with coffees of the selected type
    $coffeeTables = $coffeeController->CreateCoffeeTables($_POST['types']);
}
else 
{
    //Page is loaded for the first time, no type selected -> Fetch all types
    $coffeeTables = $coffeeController->CreateCoffeeTables('%');
}

//Output page data
$title = 'Coffee overview';
$content = $coffeeController->CreateCoffeeDropdownList(). $coffeeTables;

include 'Template.php';
?>

Open in new window


<?php

require_once ("Model/CoffeeModel.php");

//Contains non-database related function for the Coffee page
class CoffeeController {

    function CreateCoffeeDropdownList() {
        $coffeeModel = new CoffeeModel();
        $result = "<form action = '' method = 'post' width = '200px'>
                    Please select a type: 
                    <select name = 'types' >
                        <option value = '%' >All</option>
                        " . $this->CreateOptionValues($coffeeModel->GetCoffeeTypes()) .
                "</select>
                     <input type = 'submit' value = 'Search' />
                    </form>";

        return $result;
    }

    function CreateOptionValues(array $valueArray) {
        $result = "";

        foreach ($valueArray as $value) {
            $result = $result . "<option value='$value'>$value</option>";
        }

        return $result;
    }
    
    function CreateCoffeeTables($types)
    {
        $coffeeModel = new CoffeeModel();
        $coffeeArray = $coffeeModel->GetCoffeeByType($types);
        $result = "";
        
        //Generate a coffeeTable for each coffeeEntity in array
        foreach ($coffeeArray as $key => $coffee) 
        {
            $result = $result .
                    "<table class = 'coffeeTable'>
                        <tr>
                            <th rowspan='6' width = '150px' ><img runat = 'server' src = '$coffee->image' /></th>
                            <th width = '75px' >Name: </th>
                            <td>$coffee->name</td>
                        </tr>
                        
                        <tr>
                            <th>Type: </th>
                            <td>$coffee->type</td>
                        </tr>
                        
                        <tr>
                            <th>Price: </th>
                            <td>$coffee->price</td>
                        </tr>
                        
                        <tr>
                            <th>Roast: </th>
                            <td>$coffee->roast</td>
                        </tr>
                        
                        <tr>
                            <th>Origin: </th>
                            <td>$coffee->country</td>
                        </tr>
                        
                        <tr>
                            <td colspan='2' >$coffee->review</td>
                        </tr>                      
                     </table>";
        }        
        return $result;
        
    }

}

?>

Open in new window

Comment
Watch Question

Most Valuable Expert 2017
Distinguished Expert 2019

Commented:
Line 9 and line 34 of the last listing try to instantiate CoffeeModel() without a parameter.

According to your CoffeeModel class you have to inject a db parameter - it is required.

When you create your CoffeeModel you need to give it a PDO connection
public function __construct(\PDO $db) {
                                 ^^^

Open in new window

Author

Commented:
Can you please change my coffeeModel page.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once 'Credentials/credentials.php';
require_once ("Entities/CoffeeEntity.php");
$coffee = new CoffeeModel($db);

var_dump( $coffee->GetCoffeeTypes() );
var_dump( $coffee->GetCoffeeByType('sometype') );
require_once ("Entities/CoffeeEntity.php");

//Contains database related code for the Coffee page.
class CoffeeModel {

    private $db;

    public function __construct(\PDO $db) {
        $this->db = $db;
    }

    public function GetCoffeeTypes() {
        $stmt = $this->db->query("SELECT DISTINCT type FROM coffee");
		
        return $stmt->fetchAll();
    }

    public function GetCoffeeByType($type) {
        $stmt = $this->db->prepare("SELECT name, type, price, roast, country, image, review FROM coffee WHERE type LIKE :type");
        $stmt->execute(['%' . $type . '%']);
		
        return $stmt->fetchAll(PDO::FETCH_CLASS, 'CoffeeEntity');
    }

}
?>

Open in new window

Most Valuable Expert 2017
Distinguished Expert 2019

Commented:
Change it to what?

Your CoffeeModel expects a DB parameters (PDO connection) and you are not passing that to the constructor.

The problem is not in the CoffeeModel - but in where you are instantiating the CoffeeModel instances in your code - you need to do something like

$model = new CoffeeModel($db);

Open in new window

NB NB NB NB - this is not the solution - I don't know what or where your DB connection is defined in your code - you must replace $db in the above line with whatever variable you are storing that PDO db connection.

Author

Commented:
screenshot.JPG
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$user = "root";
$passwd = "";
$dsn      = 'mysql:host=localhost;dbname=coffeedb;charset=utf8mb4'; 
$options  = [
    PDO::ATTR_EMULATE_PREPARES   => false,
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
];

$db = new \PDO($dsn, $user, $passwd, $options);
?>

Open in new window

Most Valuable Expert 2017
Distinguished Expert 2019
Commented:
Ok but that is going to be out of scope inside a function.

How are you passing that $db around? Are you injecting it into your classes or using global?

Author

Commented:
require_once 'Credentials/credentials.php';
Most Valuable Expert 2017
Distinguished Expert 2019
Commented:
That is not the right answer.

Including a file does not magically make a global variable available in function scope.

Please take the time to read my posts and provide proper feedback. I cannot help you if you are not prepared to do some of the work on your end.

Here is the problem

You have this somewhere in your code

$db = new \PDO($dsn, $user, $passwd, $options); // <=== $db is in the global scope

Open in new window

You can use $db anywhere in the global scope but as soon as you do this
function someFunction() {
   $db->query(...); // <===== ERROR!!! Global scope is not available here
}

Open in new window

Usually we use DI (Dependency Injection) to ensure the $db variable is available
function someFunction($db) {
   $db->query(...); // <===== This now works
}
$db = new \PDO($dsn, $user, $passwd, $options); // <=== $db is in the global scope
someFunction($db);

Open in new window

The above code will now be valid as you are passing $db to the function so it is in scope when it is used.

A hack is to do this
function someFunction() {
  global $db;
  $db->query(...);
}
someFunction();

Open in new window

This will also work but it is generally considered a bad practice.

I can't tell you how to fix this as I don't know anything about your code base - if you are using a framework there may be a standard way of doing this - if this is your own framework then you need to work out how to get the $db variable into your controller to you can pass it to the CoffeeModel class.

UPDATE: Altered comment in second snippet.

Author

Commented:
Thank You.
Most Valuable Expert 2017
Distinguished Expert 2019

Commented:
You are welcome.