在封装PDO事务中使用闭包不起作用。为什么?

时间:2015-11-14 11:53:41

标签: php mysql pdo transactions

我目前在封装PDO事务方面存在问题,易于使用;执行事务后,没有发生数据库更改!我的想法是只提供在PDO事务中执行所需的参数和可调用事务。受保护的executeTransaction方法定义PDO事务的封装,如下所示。客户端方法是getNextWidWithLock,它使用executeTransaction方法。我试图将交易从关闭中移出来并且有效!可能是为什么它似乎没有将更改提交到数据库的原因。

    class ParentRepository
    { ...
       /**
         * Executes a transaction with logging. 
         * @param  [type]   $data        data to be passed inside the callable.
         * @param  Callable $transaction function of the procedure
         * @return [type]                [description]
         */
        protected function executeTransaction(Array $data, Callable $transaction)
        {
            $returnVariable = false;

            try 
            {
                $this->mySqlConnect->beginTransaction();
                $returnVariable = $transaction($data);
                $this->mySqlConnect->commit();
            }
            catch(\PDOException $e)
            {
                $this->mySqlConnect->rollBack();
                // Log errors.
                $dateTime = date("Y-m-d H:i", time());
                self::log(sprintf("Error Transaction @ %s" . PHP_EOL, $dateTime));
                self::log(sprintf("[Error Message] => %s %s" . PHP_EOL, PHP_EOL, $e->getMessage()));
                self::log(sprintf("[File] => %s" . PHP_EOL, $e->getFile()));
                self::log(sprintf("[Line Number] => %s" . PHP_EOL, $e->getLine()));
                self::log(sprintf("[Back Trace] => %s %s" . PHP_EOL, PHP_EOL, $e->getTraceAsString()));
                self::log("______________________________________" . PHP_EOL);
                throw $e;
            }

            return $returnVariable;
        }

    /**
         * Reserves wid in the given table with write-locking. 
         * @param  [type]  $tableName     [description]
         * @param  [type]  $branchId      [description]
         * @param  integer $reservedSlots [description]
         * @return array                  returns an array of wids. 
         * The last element must be used in an UPDATE statement while 
         * the rest must be used in an INSERT statement.  
         */
        protected function getNextWidWithLock($tableName, $branchId, $reservedSlots = 1)
        {
            if ($reservedSlots === 0)
                return [];

            $this->executeTransaction(
                [
                    'tableName' => $tableName, 
                    'branchId' => $branchId, 
                    'reservedSlots' => $reservedSlots
                ], 
                function($params)
                {
                    extract($params);

                    $minimumWid = $branchId . "0000000";
                    $maximumWid = $branchId . "9999999";

                    $preparedStatements = array(
                        $this->mySqlConnect->prepare("SET @wid_d = 0"),
                        $this->mySqlConnect->prepare("SELECT COALESCE(MAX(`wid`), $minimumWid) INTO @wid_d FROM $tableName
                                    WHERE `wid` >= $minimumWid AND `wid` <= $maximumWid FOR UPDATE"),
                        $this->mySqlConnect->prepare("INSERT INTO $tableName(`wid`)
                                 VALUES ( IF(@wid_d = 0, $minimumWid + 1 , @wid_d + $reservedSlots) )")
                    );


                    foreach ($preparedStatements as $statement)
                        $statement->execute();

                    $result = $this->mySqlConnect->prepare("SELECT `wid` FROM $tableName WHERE id = " . $this->mySqlConnect->lastInsertId());
                    $result->execute();
                    $end = $result->fetchColumn();

                    $statement = $this->mySqlConnect->prepare("SELECT IF(@wid_d = 0, $minimumWid + 1 , @wid_d + 1)");
                    $statement->execute();
                    $begin = $statement->fetchColumn();

                    return range($begin, $end);
                }
            ); 
        }


    }

1 个答案:

答案 0 :(得分:2)

你在闭包中使用$ this,但是从PHP 5.3开始是not supporting

你可以这样写:

    protected function getNextWidWithLock($tableName, $branchId, $reservedSlots = 1)
    {
        if ($reservedSlots === 0)
            return [];

        $self = $this;
        $this->executeTransaction(
            [
                'tableName' => $tableName, 
                'branchId' => $branchId, 
                'reservedSlots' => $reservedSlots
            ], 
            function($params) use ($self, $tableName, $branchId, $reservedSlots)
            {
                extract($params);

                $minimumWid = $branchId . "0000000";
                $maximumWid = $branchId . "9999999";

                $preparedStatements = array(
                    $self->mySqlConnect->prepare("SET @wid_d = 0"),
                    $self->mySqlConnect->prepare("SELECT COALESCE(MAX(`wid`), $minimumWid) INTO @wid_d FROM $tableName
                                WHERE `wid` >= $minimumWid AND `wid` <= $maximumWid FOR UPDATE"),
                    $self->mySqlConnect->prepare("INSERT INTO $tableName(`wid`)
                             VALUES ( IF(@wid_d = 0, $minimumWid + 1 , @wid_d + $reservedSlots) )")
                );


                foreach ($preparedStatements as $statement)
                    $statement->execute();

                $result = $self->mySqlConnect->prepare("SELECT `wid` FROM $tableName WHERE id = " . $self->mySqlConnect->lastInsertId());
                $result->execute();
                $end = $result->fetchColumn();

                $statement = $self->mySqlConnect->prepare("SELECT IF(@wid_d = 0, $minimumWid + 1 , @wid_d + 1)");
                $statement->execute();
                $begin = $statement->fetchColumn();

                return range($begin, $end);
            }
        ); 
    }


}