-1

I am not very good with OOP and I need a script. I tried to do my best, but I can't make it work. Can someone make an OOP script for me (it is a small script).

I need a function startTransaction() and inside the function I put two query's. I also create a variable inside this function ($transaction_called=1) and the next time the function is called it should have access to this variable.

I need a second function stopTransaction(). There are also query's inside this function, and I need access to the variable made inside startTransaction().

Every time in a random script I call the startTransaction() and with the variable $transaction_called I check if the function is called.

This is what I have, but I don't know how to fix it.

class Foo
{
    protected $_transaction_called = '0';

    public function transactionCalled()
    {
        // code ...
        $this->_transaction_called = '1';
    }

    public function startTransaction()
    {
        if(!$this->_transaction_called === '1') {
            $this->transactionCalled();
            mysql_query("START TRANSACTION", $db);
        }else{
            //do nothing, transaction already started
        } 
    }

    public function transactionStopped()
    {
        // code ...
        $this->_transaction_called = '0';
    }

    public function stopTransaction()
    {
        if(!$this->_transaction_called === '1') {
            $this->transactionStopped();
            if($transaction_error==true){
                mysql_query("ROLLBACK", $db);
            }else{
                mysql_query("COMMIT", $db);
            }
        }
    }
}

//some random script:
$transaction_error=false;
startTransaction();

$query_1 = "UPDATE x1 SET X1='1' WHERE X1='x'";
$result_1 = mysql_query($query_1, $db);
if(!$result_1){$transaction_error=true;}
//query's, query's and more query's

stopTransaction();
Jordy
  • 4,719
  • 11
  • 47
  • 81
  • 1
    "This is what I have, but I don't know how to fix it." - to fix what? Can you show the error, please. – user4035 Jul 16 '13 at 19:53
  • Well, the whole script doesn't work. For example the $db is undefined. And the variables doesn't work. I think the whole script is one error:P I hope someone can optimize it! – Jordy Jul 16 '13 at 19:55
  • I hope you can help me! This is the only part in my website that is in OOP, and I don't understand how to fix it! – Jordy Jul 16 '13 at 19:59
  • I don't understand, what is the `//code` in transactionCalled and stopTransaction functions. – user4035 Jul 16 '13 at 20:00
  • It is not a good practice to use mysql_* functions as they are deprecated. Are you strictly bounded to them or can use mysqli or PDO? – user4035 Jul 16 '13 at 20:04
  • That's nothing. You can remove that. Well I'm not strictly bounded to them, but I prefer them now. In the future I want to update everything to PDO, but now I like MySQL for the first release of my website! – Jordy Jul 16 '13 at 20:07
  • "That's nothing. You can remove that." - yes, I'll do that. As it seems not reasonable to have a function with just 1 assignment operator. – user4035 Jul 16 '13 at 20:10
  • I have that function to create the variable 'transaction_called'. For example: I have different scripts with different functions. Some of these scripts are included in other scripts. In most of the scripts I start a transaction. But if I start a transaction in multiple scripts it doesn't work. So that variabele is a check to only start a transaction if it isn't started before. – Jordy Jul 16 '13 at 20:14
  • See this: http://stackoverflow.com/a/1933087/881988 – Jordy Jul 16 '13 at 20:20

2 Answers2

1

I made 2 files: class.php and script.php

class.php

<?php
class Transaction
{
    protected $_transaction_called;
    protected $db;

    public function __construct(&$db)
    {
        $this->db = $db;
        $this->_transaction_called = false;
    }

    public function startTransaction()
    {
        if($this->_transaction_called == false) {
            $this->_transaction_called = true;
            mysql_query("START TRANSACTION", $this->db);
        }
    }

    public function stopTransaction($error)
    {
        if($this->_transaction_called == true) {
            $this->_transaction_called = false;
            if($error == true){
                print "ROLLBACK\n";
                mysql_query("ROLLBACK", $this->db);
            }else{
                print "COMMIT\n";
                mysql_query("COMMIT", $this->db);
            }
        }

    }
}

script.php

<?php
include_once("class.php");

//connect to DB
$db = mysql_connect('localhost', 'user', '');
if (!$db) {
    die('Could not connect: ' . mysql_error());
}

echo "Connected successfully\n";
mysql_select_db('test');


$trans = new Transaction($db);
$trans->startTransaction();

$query = "UPDATE Document SET Description='!!!' WHERE DataID=1";
$result = mysql_query($query, $db);
//if $result is false, there is an error
$trans->stopTransaction(!$result);

//2-nd transaction
$trans->startTransaction();

$query = "INCORRECT QUERY";
$result = mysql_query($query, $db);
//if $result is false, there is an error
$trans->stopTransaction(!$result);

Database

The database is called test and has the following table, used for testing:

DROP TABLE IF EXISTS `Document`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `Document` (
  `DataID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Description` varchar(50) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`DataID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `Document`
--

LOCK TABLES `Document` WRITE;
/*!40000 ALTER TABLE `Document` DISABLE KEYS */;
INSERT INTO `Document` VALUES (1,'This is document 1');
/*!40000 ALTER TABLE `Document` ENABLE KEYS */;
UNLOCK TABLES;

After running the script, it prints the following messages:

Connected successfully
COMMIT
ROLLBACK

Please, read the code and let me know, if you have any questions.

user4035
  • 22,508
  • 11
  • 59
  • 94
  • Absolutely awesome. I'm going to check it tomorrow, and I let you know! – Jordy Jul 16 '13 at 20:25
  • One question, if I have multiple query's inside the transaction, how can I check if all of them succeeded? In my first post I used the variable $transaction_error that has the value 'true' when there was an error. How do you do that? – Jordy Jul 16 '13 at 20:28
  • And another question, I also start a transaction inside a function. There I have the error 'Undefined variable: trans'. A solution would be to pass the $trans parameter to the function, but in that case I should edit all my code with an extra parameter. I would like to do that an other way. Is something like new Transaction($db)->startTransaction(); inside a function also good? – Jordy Jul 16 '13 at 20:39
  • @Jordy "And another question, I also start a transaction inside a function." OOP usually requires dealing with a global object. So you can create $trans as a global variable and use it. Your code: `Transaction($db)->startTransaction();` is still in procedural style. There is no need to use objects in this case. – user4035 Jul 16 '13 at 20:45
  • @Jordy "if I have multiple query's inside the transaction, how can I check if all of them succeeded?" Get the results of all the queries and use & operation for all of them. If at least 1 is false - the result will be false. And you'll know, there is an error. – user4035 Jul 16 '13 at 20:46
  • "So you can create $trans as a global variable and use it." On the internet I read that they strongly advise not to use global variables. But should I make $trans global in every function. Is that the best option? – Jordy Jul 16 '13 at 20:47
  • @Jordy Yes, most of the time global variables are bad. But if you use 1 instance of your class with everything encapsulated inside it, it's ok. Mind, that you are using $db global variable every time you call mysql_* function. And nobody says it's a bad style. – user4035 Jul 16 '13 at 20:51
  • @Jordy Any luck with this script? – user4035 Jul 17 '13 at 11:40
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33638/discussion-between-jordy-and-user4035) – Jordy Jul 17 '13 at 14:22
0

To call a function of a class, you first need to create an instance of that class.

$myFoo = new Foo();
$myFoo->startTransaction();
...
...

You also mix the variables:

$transaction_error inside the class is not the same as $transaction_error outside. For using it inside the class, first define it and the access it like

$this->transaction_error

You must realize that the variables inside the object are not visible outside, unless they are public and you access using the object reference. For example if $transaction_error was defined as public you could access it with:

$myFoo->transaction_error

Same issue happens with your $db, which I don't see defined inside the class.

Aris
  • 4,643
  • 1
  • 41
  • 38