1

I am trying to write a logging function and so far it works. The only issue I am facing right now is that I can execute the function only one time successfully. When I call it a second time PHP states PHP Fatal error: Cannot redeclare function.

Now I wanted to ask:

  1. Why does PHP complain about my workflow? To my understanding I write the function placeholders3 and I can use this function again and again with different parameters. E. g. first:

    $addNewCar->log(array('makeModelDescription','firstRegistration','mileage','logMessage', 'createTime'),
    array($carDetails[0]['FK_makeModelDescription'],
          $carDetails[0]['FK_firstRegistration'],
          $carDetails[0]['FK_mileage'],
          'deleteCarbyID: ' . $addNewCar->affected_rows,
          time()
    )
    

    ); and then e. g.

    $addNewCar->log(array('makeModelDescription','firstRegistration','mileage','logMessage', 'createTime'),
    array($carDetails[0]['FK_makeModelDescription'],
          $carDetails[0]['FK_firstRegistration'],
          $carDetails[0]['FK_mileage'],
          'insertCarById: ' . $addNewCar->affected_rows,
          time()
    ));
    

Function logging:

    public function log($key, $values) {
    try {

        /** @var $tableColumns Column names in MySQL table */
        $tableColumns = $key;

        /** @var $tableRows Use 2-dimensional numeric or associative arrays
         * for multiple records. Single records can be added with a
         * vector */
        $tableRows[] = $values;

        $DBH = $this->DBH;

        /**
         * @param        $text       Unnamed placeholder
         * @param int    $count      Number of unnamed placeholders (size of one array)
         * @param string $separator  Separator
         *
         * @return string            Concatenated unnamed placeholders, e. g. ?, ?, ?
         */
        function placeholders3($text, $count=0, $separator=","){
            $result = array();
            if($count > 0){
                for($x=0; $x<$count; $x++){
                    $result[] = $text;
                }
            }
            return implode($separator, $result);
        }

        /**
         * Generate unnamed placeholders for SQL statement,
         * e. g. (?,?,?,?,?),(?,?,?,?,?),(?,?,?,?,?).
         *
         * Pitfalls:
         *
         * - Nested array:  Take care that you iterate over the items
         *                  of the nested array. E. g. $tableRows[0]
         *                  instead of $tableRows;
         *
         * - sizeof($d):    Number of elements per single array
         *                  (for a single db insert).
         */
        $insert_values = array();
        foreach($tableRows as $d){
            $question_marks[] = '('  . placeholders3('?', sizeof($d)) . ')';
            $insert_values = array_merge($insert_values, array_values($d));
        }

        $sql = "INSERT INTO logging (" . implode(",", $tableColumns ) . ") VALUES " . implode(',', $question_marks);

        $STH = $DBH->prepare($sql);
        $STH->execute($insert_values);
        $this->affected_rows = $STH->rowCount();
    }
    catch(PDOException $e) {
        error_log("PDO error: " . $e->getMessage());
    }
}
  1. How should I change my design to get it working?

Many thanks in advance!

HH.
  • 197
  • 3
  • 17

2 Answers2

3

Functions are declared in the global scope. You are re-declaring the function in the global scope every time you call the log() method. There is an easy solution:

if (!function_exists('placeholders3')) {
    function placeholders3($text, $count=0, $separator=","){
    // ...
    }
}

But you are still declaring a global function, which you probably don't want to do. Since you are using an object anyway, the correct way of doing this is:

class myclass {

       protected function placeholders3($text, $count=0, $separator=","){
           //...
       }

       public function log($key, $values) {
          // ...
          $question_marks[] = '('  . $this->placeholders3('?', sizeof($d)) . ')';
          // ...
       }
}

If for some reason you don't want to create the class method and you are using a relatively recent version of PHP, you can also use a lambda function:

public function log($key, $values) {
    $placeholders3 = function($text, $count=0, $separator=","){
        // ...
    };
    // ...
    $question_marks[] = '('  . $placeholders3('?', sizeof($d)) . ')';
    // ...
}
Matt
  • 1,287
  • 2
  • 11
  • 25
0

Also guys, please check if your function name is a keyword in PHP, like 'reset' - in this case, it also displays "Cannot redeclare function " error

amelie
  • 289
  • 3
  • 16