Search code examples
phpms-accessodbc

PHP writing to odbc datasource fails



today I need some help with a php-script, that doesn't work anymore.

I have to setup a backup server, where a simple timesheet works with a web-interface, connected to an odbc datasource (Access 2007-database) Everything works well on the original server but now the hardware is about to be changed.
On both servers, the PHP Version 5.4.9 is running, for compatibility-reason. (local network, so no risk with the old php-version)

Reading from the datasource works well but I could not write to the datasource. Is there any readonly-flag, that I didn't find, in the datasource-environment? I have no idea how to get over this problem.
I could follow the code up to the "INSERT INTO" command without any fault.

$result = odbc_exec($con,"INSERT INTO Zeitkarten (BeginnTätigkeit,EndeTätigkeit,Mitarbeiter,Projekt,ArbeitscodeNr,datum,Pause,AnzahlUeber,FZhin,FZrueck,Anmerkung) 
          VALUES (#".$_POST['kommen']."#,#".$_POST['gehen']."#,$benutzer,".$_POST['projekt'].",".$_POST['adt'].",#".$_POST['heute']."#,".str_Replace(",",".",$_POST['pause']).",".str_Replace(",",".",$_POST['ama']).",".str_Replace(",",".",$_POST['fzhin']).",".str_Replace(",",".",$_POST['fzrueck']).",'".$_POST['anmerkung']."')");
                    echo $result;
                    }

This should normally echo any result (e.g. on the original server I get: Resource id #136). Here I get nothing.

Can please anyone help me to search the problem?


Solution

  • While your issue involves read-only permissions on the data source file, consider two best practices going forward:

    • Parameterization to facilitate code security especially with $POST variables as well as readability and maintainability without need of messy variable concatenation or quote punctuation. Parameters are supported in the odbc library using odbc_prepare.

    • Error handling using try/catch for more informative errors or exceptions per this answer.

    Below uses MS Access's CDate() and avoid need of enclosing # and converts numeric types of parameters with PHP's floatval. Adjust untested code as needed.

    // ENSURE ERRORS RAISE AS EXCEPTIONS
    set_error_handler(
        function($errno, $errstr, $errfile, $errline ) { 
            throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
        }
    );
    
    // PREPARED STATEMENT WITH ? PLACEHOLDERS
    $sql = "INSERT INTO Zeitkarten
              (BeginnTätigkeit, EndeTätigkeit, Mitarbeiter, Projekt, ArbeitscodeNr,
               datum, [Pause], AnzahlUeber, FZhin, FZrueck, Anmerkung) 
            VALUES (CDate(?), CDate(?), ?, ?, ?, CDate(?), ?, ?, ?, ?, ?)";
    
    try { 
        // BIND PARAMS AND EXECUTE
        $stmt = odbc_prepare($con, $sql);
        $result = odbc_execute(
             $stmt, 
             array( 
                 $_POST['kommen'],
                 $_POST['gehen'], 
                 $benutzer, 
                 $_POST['projekt'], 
                 $_POST['adt'], 
                 $_POST['heute'],
                 floatval(str_replace(",", ".", $_POST['pause'])),
                 floatval(str_replace(",", ".", $_POST['ama'])),
                 floatval(str_replace(",", ".", $_POST['fzhin'])),
                 floatval(str_replace(",", ".", $_POST['fzrueck'])),
                 $_POST['anmerkung']
             )
        ); 
    
        echo $result; 
    } catch (Exception $e) { 
        // ECHO EXCEPTION MESSAGE
        echo $e->getMessage(); 
    }