-1

I´m trying to get all records from the database and then instantiate a new object with the data from each one:

$stmt = $this->pdo->prepare('SELECT * FROM '.$this->table.' ORDER BY '.$order.' ASC');
    $stmt->execute();
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    if ($results){
        for ($i=0; $i<count($results); ++$i){
            $strValues = '';
            $values = array_values($results[$i]);
            for ($j=0; $j<count($values); ++$j){//Extract the values to pass them as arguments to the constructor below
                if ($j == 0) $strValues .= $values[$j];
                else{
                    $strValues .= ',';
                    $strValues .= '"'.$values[$j].'"';
                }
            }
            eval('$result['.$i.'] = new '.get_class($this->instance).'('.$strValues.');');              
        }
    }

The problem is that the object type can vary depending on if I'm querying the users or labels databases, so the call to constructor may be new User(user_id, username, name, surname) or new Label(label_id, name, description, color). The code above runs on the ObjectMapper class, which on creation gets assigned an object type and stores an instance of it in the private instance variable. This way I can get the name of the required constructor with get_class($this->instance).

I finally managed to make it work using an eval as shown, but I've read that this is not a good practice and I would like to know of better and cleaner ways to do it.

Dharman
  • 30,962
  • 25
  • 85
  • 135
correojon
  • 11
  • 3
  • For future reference, `fetchAll()` is best used when you do not intend to iterate the results in the same "layer". If you intending to immediately perform iterated processes on the result set, then you should make looped `fetch()` calls. – mickmackusa Jun 13 '20 at 12:52
  • Thanks a lot for the help! I use fetch_all() because this is the controller which prepares the $result array for the view to display in a later step. However this is still in early development, my idea is to limit the results in the query to not have too much load.Thanks again for your answer, I was going in the wrong direction all along. – correojon Jun 13 '20 at 18:08

1 Answers1

2

This should do what you are trying to achieve. Do not use eval

PDO has plenty of useful fetch modes and they are described here https://phpdelusions.net/pdo/fetch_modes#FETCH_CLASS

$stmt = $this->pdo->prepare('SELECT * FROM '.$this->table.' ORDER BY '.$order.' ASC');
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_CLASS, get_class($this->instance));

P.S. Remember to properly whitelist the table name and $order variable.

Dharman
  • 30,962
  • 25
  • 85
  • 135