【问题标题】:Call to a member function prepare() on a non-object in PDO using PHP使用 PHP 在 PDO 中的非对象上调用成员函数 prepare()
【发布时间】:2014-09-04 14:44:56
【问题描述】:

我使用 PHP 与 Oracle 11g 数据库进行通信。此代码旨在供用户上传 .xls 或 .csv 文件。如果是 .xls,则转换为 .csv。如果是 .csv,请继续。之后,它获取 csv 并更新一个 oracle 数据库。过去,我使用过 sql 注入,却没有意识到与之相关的安全缺陷。于是,我开始学习使用PDO。但是,我很新。我设计的代码(如下)出现此错误:

Fatal error: Call to a member function prepare() on a non-object in /opt/apache/servers/planninganddesign/htdocs/JointUse/update_handler.php on line 89 

第 89 行已标记,如下所示。

代码:

<?php
require_once('Classes/PHPExcel/IOFactory.php'); 
require_once("mcl_Oci.php");
?>

<br>

<?php

    $filename = $_FILES['uploaded']['name'];
    $file = $_FILES['uploaded']['tmp_name'];
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    if($ext='xls') {



        $inputFileType = 'Excel5';
        $inputFileName = $file;

        $objReader = PHPExcel_IOFactory::createReader($inputFileType);
        $objPHPExcelReader = $objReader->load($inputFileName);

        $loadedSheetNames = $objPHPExcelReader->getSheetNames();

        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcelReader, 'CSV');

        foreach($loadedSheetNames as $sheetIndex => $loadedSheetName) {
                $objWriter->setSheetIndex($sheetIndex);
                $objWriter->save('abc.csv');}
        $files = fopen('abc.csv', 'r'); 
            if($files) {
                    while (($line = fgetcsv($files)) !== FALSE) {
                    $csv_array[] = array_combine(range(1, count($line)), array_values($line));
            }           echo 'Your .xls file was uploaded successfully. Have a nice day.';
        }
        elseif ($ext='csv'){
            while (($line = fgetcsv($files)) !== FALSE) {
                    $csv_array[] = array_combine(range(1, count($line)), array_values($line));
            }   echo 'Your .csv file was uploaded successfully. Have a nice day.';
        }
        else {
            echo "This is not an accepted file type. Please save as either '*.csv' or '*.xls' and re-upload.";
        }
    }


    $ArrayNumber = 0;   

    while ($csv_array["$ArrayNumber"] != NULL) {

    $ArrayNumber = $ArrayNumber + 1;
    $RECEIVED=$csv_array["$ArrayNumber"]["1"];
    $REGION=$csv_array["$ArrayNumber"]["2"];
    $PERMIT=$csv_array["$ArrayNumber"]["3"];
    $CUSTOMER=$csv_array["$ArrayNumber"]["4"];
    $TO_BUSINESS=$csv_array["$ArrayNumber"]["5"];
    $TO_PERMIT=$csv_array["$ArrayNumber"]["6"];
    $POWER_ADDRESS=$csv_array["$ArrayNumber"]["7"];
    $COMPANY=$csv_array["$ArrayNumber"]["8"];
    $MAP_SECTION = $csv_array["$ArrayNumber"]["9"];
    $POLES = $csv_array["$ArrayNumber"]["10"];
    $FEE = $csv_array["$ArrayNumber"]["11"];
    $INVOICE = $csv_array["$ArrayNumber"]["12"];
    $DATE_LARRY = $csv_array["$ArrayNumber"]["13"];
    $DAYS_LARRY = $csv_array["$ArrayNumber"]["14"];
    $PI_PON = $csv_array["$ArrayNumber"]["15"];
    $DATE_PD = $csv_array["$ArrayNumber"]["16"];
    $DATE_LARRY_PD = $csv_array["$ArrayNumber"]["17"];
    $RETURNED = $csv_array["$ArrayNumber"]["18"];
    $DAYS_PD = $csv_array["$ArrayNumber"]["19"];
    $ERRORS_PD = $csv_array["$ArrayNumber"]["20"];
    $ERRORS_MULTIPLE = $csv_array["$ArrayNumber"]["21"];
    $DATE_MAKEREADY_JU = $csv_array["$ArrayNumber"]["22"];
    $DATE_MAKEREADY_COMPLETE = $csv_array["$ArrayNumber"]["23"];
    $DAYS_MAKEREADY = $csv_array["$ArrayNumber"]["24"];
    $DAYS_JU_PROCES = $csv_array["$ArrayNumber"]["25"];
    $APPROVAL = $csv_array["$ArrayNumber"]["26"];
    $DAYS_PERMIT_IN_JU = $csv_array["$ArrayNumber"]["27"];
    $DATE_PLANNING = $csv_array["$ArrayNumber"]["28"];
    $DAYS_OPEN = $csv_array["$ArrayNumber"]["29"];
    $DATE_ROUTED = $csv_array["$ArrayNumber"]["30"];
    $DAYS_TOTAL = $csv_array["$ArrayNumber"]["31"];
    $COMMENTS = $csv_array["$ArrayNumber"]["32"];

    $conn = oci_connect("user", "pass", "(description=(address=(protocol=tcp)(host=host)(port=1533))(connect_data=(service_name=name)))");
    $sql = 'INSERT INTO INTOXDM.JOINT_USE (RECEIVED, REGION, PERMIT, CUSTOMER, TO_BUSINESS, TO_PERMIT, POWER_ADDRESS, COMPANY, MAPSECTION, POLES, FEE, INVOICE, DATE_LARRY, DAYS_LARRY, PI_PON, DATE_PD, DAYS_LARRY_PD, RETURNED, DAYS_PD, ERRORS_PD, ERRORS_MULTIPLE, DATE_MAKEREADY_JU, DATE_MAKEREADY_COMPLETE, DAYS_MAKEREADY, DAYS_JU_PROCES, APPROVAL, DAYS_PERMIT_IN_JU, DATE_PLANNING, DAYS_OPEN, DATE_ROUTED, DAYS_TOTAL, COMMENTS)
         VALUES (:RECEIVED, :REGION, :PERMIT, :CUSTOMER, :TO_BUSIENSS, :TO_PERMIT, :POWER_ADDRESS, :COMPANY, :MAP_SECTION, :POLES, :FEE, :INVOICE, :DATE_LARRY, :DAYS_LARRY, :PI_PON, :DATE_PD, :DATE_LARRY_PD, :RETURNED, :DAYS_PD, :ERRORS_PD, :ERRORS_MULTIPLE, 
        :DATE_MAKEREADY_JU, :DATE_MAKEREADY_COMPLETE, :DAYS_MAKEREADY, :DAYS_JU_PROCES, :APPROVAL, :DAYS_PERMIT_IN_JU, :DATE_PLANNING, :DAYS_OPEN, :DATE_ROUTED, :DAYS_TOTAL, :COMMENTS)';
    *****$stmt = $conn->prepare($sql);***** line 89
    $sql->bindValue(':RECEIVED',$RECEIVED);
    $sql->bindValue('REGION',$REGION);
    $sql->bindValue(':PERMIT',$PERMIT);
    $sql->bindValue(':TO_BUSINESS',$TO_BUSINESS);
    $sql->bindValue(':TO_PERMIT',$TO_PERMIT);
    $sql->bindValue(':POWER_ADDRESS',$POWER_ADDRESS);
    $sql->bindValue(':MAP_SECTION',$MAP_SECTION);
    $sql->bindValue(':POLES',$POLES);
    $sql->bindValue(':FEE',$FEE);
    $sql->bindValue(':INVOICE',$INVOCE);
    $sql->bindValue(':$DATE_LARRY',$DATE_LARRY);
    $sql->bindValue(':$DAYS_LARRY',$DAYS_LARRY);
    $sql->bindValue(':$PI_PON',$PI_PON);
    $sql->bindValue(':$DATE_PD',$DATE_PD);
    $sql->bindValue(':$DATE_LARRY_PD',$DATE_LARRY_PD);
    $sql->bindValue(':RETURNED',$RETURNED);
    $sql->bindValue(':DAYS_PD',$DAYS_PD);
    $sql->bindValue(':ERRORS_PD',$ERRORS_PD);
    $sql->bindValue(':ERRORS_MULTIPLE',$ERRORS_MULTIPLE);
    $sql->bindValue(':DATE_MAKEREADY_JU',$DATE_MAKEREADY_JU);
    $sql->bindValue(':DATE_MAKEREADY_COMPLETE',$DATE_MAKEREADY_COMPLETE);
    $sql->bindValue(':DAYS_MAKEREADY',$DAYS_MAKEREADY);
    $sql->bindValue(':DAYS_JU_PROCES',$DAYS_JU_PROCES);
    $sql->bindValue(':DATE_PERMIT_IN_JU',$DATE_PERMIT_IN_JU);
    $sql->bindValue(':DATE_PLANNING',$DATE_PLANNING);
    $sql->bindValue(':DAYS_OPEN',$DAYS_OPEN);
    $sql->bindValue(':DATE_ROUTED',$DATE_ROUTED);
    $sql->bindValue(':DAYS_TOTAL',$DAYS_TOTAL);
    $sql->bindValue(':COMMENTS',$COMMENTS);
    $stmt->execute();

    $exec = execute();

    }
?>

什么可能导致此问题,是否有简单的解决方法?蒂亚!

【问题讨论】:

  • Reference - What does this error mean in PHP? 的可能副本。您不能将oci_ 函数与PDO 函数混合使用。使用 100% oci 或 100% PDO(通过使用 PDO_OCI)。
  • 在我看来,对oci_connect 的调用似乎失败了,$conn 并没有引用有效的连接。祝你好运。
  • @BobJarvis 感谢您的帮助,但连接肯定成功。我有其他页面使用完全相同的 conn 字符串从数据库中提取数据。

标签: php sql oracle pdo prepare


【解决方案1】:

oci 扩展没有面向对象的用法。 oci_connect() 返回一个资源,而不是一个对象。资源没有方法。

@h2ooooooo 的评论是正确的。您似乎在混合使用 oci 和 PDO 使用。选择其中一个,最好是 PDO。

换句话说,不要调用oci_connect(),而是这样做:

$dsn = 'oci:dbname=host:1533/name';
$user = 'user';
$password = 'pass';

try {
    $conn = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

如果成功,您应该可以使用$conn 作为 PDO 对象。

但是您的代码中还有其他一些错误。

$sql->bindValue(':RECEIVED',$RECEIVED);

如果您使用bindValue(),它是您的语句对象的方法,而不是$sql 字符串。字符串没有方法。改为这样做:

$stmt->bindValue(':RECEIVED',$RECEIVED);

对于所有其他对bindValue() 的调用也是如此。

您的代码末尾还有一条多余的行似乎什么都不做:

$exec = execute();

除非你的应用程序中有一个函数execute(),否则我不知道它应该做什么。

另一个错误:您的 while 循环测试当前索引 $ArrayNumber 是否有条目,然后在获取值之前递增 $ArrayNumber。您肯定会导致错误,因为您的代码将尝试读取数组末尾的内容。您应该在读取该数组元素中的数据之后增加$ArrayNumber

或者使用for循环而不是while

$count = count($csv_array);
for ($ArrayNumber = 0; $ArrayNumber < $count; ++$ArrayNumber) {
  ...

甚至更简单:

foreach ($csv_array as $row) {
  ...

关于使用准备好的语句的一些提示。如果您只是将数组传递给PDOStatement::execute(),则可以跳过所有乏味的bindValue() 调用。而且您已经将数据保存在数组中!您甚至不需要创建所有这些局部变量。

由于您的数据是使用整数而不是列名来索引的,因此您应该使用序数参数(以 ? 作为占位符)而不是命名参数。

此外,您不需要为循环的每次迭代都准备语句。准备好的语句的最大优点之一是您可以准备一次并在循环期间以不同的值重复使用它。

这是一个例子:

$sql = 'INSERT INTO INTOXDM.JOINT_USE (RECEIVED, REGION, PERMIT, CUSTOMER, TO_BUSINESS, TO_PERMIT, POWER_ADDRESS, COMPANY, MAPSECTION, POLES, FEE, INVOICE, DATE_LARRY, DAYS_LARRY, PI_PON, DATE_PD, DAYS_LARRY_PD, RETURNED, DAYS_PD, ERRORS_PD, ERRORS_MULTIPLE, DATE_MAKEREADY_JU, DATE_MAKEREADY_COMPLETE, DAYS_MAKEREADY, DAYS_JU_PROCES, APPROVAL, DAYS_PERMIT_IN_JU, DATE_PLANNING, DAYS_OPEN, DATE_ROUTED, DAYS_TOTAL, COMMENTS)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
$stmt = $conn->prepare($sql);

foreach ($csv_array as $row) {
  $stmt->execute($row);
}

最后一个提示:在读取数据后执行此操作:

echo 'Your .csv file was uploaded successfully. Have a nice day.';

但我会在数据成功导入数据库后输出该消息。如果插入数据库有任何问题,肯定消息可能不会是真的。

【讨论】:

  • 首先,感谢您的详细回答,它教会了我很多东西。我很感激!当我更新我的连接字符串时,我得到以下信息:Connection failed: could not find driver。之前也出现了同样的错误,但是我想这可能是由于上面发布的错误。这是否意味着我需要安装 PDO?我该怎么做?
  • 您的 PHP 实例似乎没有安装 OCI 驱动程序。有关该问题的答案,请参阅 stackoverflow.com/search?q=pdo+oci+could+not+find+driver
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-29
  • 1970-01-01
  • 2011-07-17
  • 2013-08-21
相关资源
最近更新 更多