Skip to content

Commit

Permalink
Updates to docs and regex patterns
Browse files Browse the repository at this point in the history
Removed un-needed escape sequences in regex patterns
Updated README
  • Loading branch information
noahheck committed May 13, 2016
1 parent 3778e1a commit 702f1f7
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 56 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
##Change Log

###2.1.5 (2015-05-13)

####Added

- Test for successful execution of database query with named placeholders
- Updated README

####Fixed

- Remove un-needed escape sequences in regular expression patterns

###2.1.4 (2015-10-25)

####Added
Expand Down
76 changes: 42 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#E_PDOStatement

Drop in replacement for default PHP PDOStatement class allowing devs to view an interpolated version of a parameterized query. The result is generally suitable for logging activities, debugging and performance analysis.
Extension to the default PHP PDOStatement class providing the ability to generate a version of a parameterized query with the parameters injected into the query string.

#####Update (2015-10-24)
Full PHPUnit Test Suite in place plus re-organization of code
The result is generally suitable for logging activities, debugging and performance analysis.

#####Update (2015-07-19)
Now takes into account bound arguments' datatypes when compiling interpolated string (previously, all values were quoted when it's likely inappropriate to quote INT datatypes). This allows for viewing/using bound values in e.g. LIMIT clauses where the quotes would interfere with processing the resultant query.
View the [changelog](CHANGELOG.md)

##Usage

Expand All @@ -18,14 +16,16 @@ The E_PDOStatement (<strong>E</strong>nhanced PDOStatement) project was designed

```php
<?php
$query = "INSERT INTO users SET username = :user, password = :password";
$stmt = $pdo->prepare($query);
$content = $_POST['content'];
$title = $_POST['title'];
$date = date("Y-m-d");

$username = $_POST['username'];
$password = passwordPrep($_POST['password']);
$query = "INSERT INTO posts SET content = :content, title = :title, date = :date"
$stmt = $pdo->prepare($query);

$stmt->bindParam(":user" , $username, PDO::PARAM_STR);
$stmt->bindParam(":password", $password, PDO::PARAM_STR);
$stmt->bindParam(":content", $content, PDO::PARAM_STR);
$stmt->bindParam(":title" , $title , PDO::PARAM_STR);
$stmt->bindParam(":date" , $date , PDO::PARAM_STR);

$stmt->execute();

Expand All @@ -36,70 +36,79 @@ echo $stmt->fullQuery;
The result of this will be (on a MySQL database):

```
INSERT INTO users SET username = 'admin', password = '45ab6941fed66456afe6239ab875e4fa'
INSERT INTO posts SET content = 'There are several reasons you shouldn\'t do that, including [...]', title = 'Why You Shouldn\'t Do That', date = '2016-05-13'
```

When correctly configured, the interpolated values are escaped appropriately for the database driver, allowing the generated string to be suitable for e.g. log files, backups, etc.

E_PDOStatement supports pre-execution binding to both named and ? style parameter markers:
```php
$query = "INSERT INTO users SET username = ?, password = ?";
$query = "INSERT INTO posts SET content = ?, title = ?, date = ?";

...

$stmt->bindParam(1, $username, PDO::PARAM_STR);
$stmt->bindParam(2, $password, PDO::PARAM_STR);
$stmt->bindParam(1, $content, PDO::PARAM_STR);
$stmt->bindParam(2, $title , PDO::PARAM_STR);
$stmt->bindParam(3, $date , PDO::PARAM_STR);
```

as well as un-named parameters provided as input arguments to the `$stmt->execute()` method:

```php
$query = "INSERT INTO users SET username = ?, password = ?";
$query = "INSERT INTO posts SET content = ?, title = ?, date = ?";

...

$params = array($username, $password);
$params = array($content, $title, $date);

$stmt->execute($params);

```

Named $key => $value pairs can also be provided as input arguments to the `$stmt->execute()` method:
```php
$query = "INSERT INTO users SET username = :username, password = :password";
$query = "INSERT INTO posts SET content = :content, title = :title, date = :date";

...

$params = array(
":username" => $username
, ":password" => $password
":content" => $content
, ":title" => $title
, ":date" => $date
);

$stmt->execute($params);
```

You can also generate the full query string without executing the query:
```php
$query = "INSERT INTO users SET username = :user, password = :password";
$stmt = $pdo->prepare($query);
$content = $_POST['content'];
$title = $_POST['title'];
$date = date("Y-m-d");

$username = $_POST['username'];
$password = passwordPrep($_POST['password']);
$query = "INSERT INTO posts SET content = :content, title = :title, date = :date"
$stmt = $pdo->prepare($query);

$stmt->bindParam(":user" , $username, PDO::PARAM_STR);
$stmt->bindParam(":password", $password, PDO::PARAM_STR);
$stmt->bindParam(":content", $content, PDO::PARAM_STR);
$stmt->bindParam(":title" , $title , PDO::PARAM_STR);
$stmt->bindParam(":date" , $date , PDO::PARAM_STR);

$fullQuery = $stmt->interpolateQuery();
```
or
```php
$query = "INSERT INTO users SET username = :user, password = :password";
$stmt = $pdo->prepare($query);
$content = $_POST['content'];
$title = $_POST['title'];
$date = date("Y-m-d");

$username = $_POST['username'];
$password = passwordPrep($_POST['password']);
$query = "INSERT INTO posts SET content = ?, title = ?, date = ?"
$stmt = $pdo->prepare($query);

$params = array($username, $password);
$params = array(
$content
, $title
, $date
);

$fullQuery = $stmt->interpolateQuery($params);
```
Expand Down Expand Up @@ -139,9 +148,8 @@ $pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array("EPDOStatement\EPDOStatement

That's all there is to it.

The classname has been updated to allow strict conformance to PSR-0 autoloading (e.g. removed the _ from the class/filename).

Ideally, your project would have a PDO abstraction/wrapper class allowing you to implement this modification in only one place. If you don't have this luxury, success was shown with extending the \PDO class to set the ATTR_STATEMENT_CLASS attribute in the constructor of the PDO.
Ideally, your project would have a PDO abstraction/wrapper class allowing you to implement this modification in only one place.
If you don't have this luxury, success was shown with extending the \PDO class to set the ATTR_STATEMENT_CLASS attribute in the constructor of the PDO.

##Get in Touch
There are a lot of forum posts related to or requesting this type of functionality, so hopefully someone somewhere will find it helpful. If it helps you, comments are of course appreciated.
Expand Down
17 changes: 8 additions & 9 deletions src/EPDOStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private function replaceMarker($queryString, $marker, $replValue)
if (is_numeric($marker)) {
$marker = "\?";
} else {
$marker = (preg_match("/^\:/", $marker)) ? $marker : ":" . $marker;
$marker = (preg_match("/^:/", $marker)) ? $marker : ":" . $marker;
}

$testParam = "/" . $marker . "(?!\w)/";
Expand Down Expand Up @@ -169,16 +169,15 @@ public function execute($inputParams = null)
*/
private function prepareValue($value)
{
if ($this->_pdo) {

if (PDO::PARAM_INT === $value['datatype'])
{
return (int) $value['value'];
}
if (!$this->_pdo) {
return "'" . addslashes($value['value']) . "'";
}

return $this->_pdo->quote($value['value']);
if (PDO::PARAM_INT === $value['datatype'])
{
return (int) $value['value'];
}

return "'" . addslashes($value['value']) . "'";
return $this->_pdo->quote($value['value']);
}
}
49 changes: 36 additions & 13 deletions tests/src/EPDOStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public function testValuesGetInterpolatedIntoQueryStatementWhenBoundIndividually
$this->assertTrue(false != preg_match("/123/", $result));
$this->assertTrue(false != preg_match("/active/", $result));

$this->assertTrue(false == preg_match("/\:userId/", $result));
$this->assertTrue(false == preg_match("/\:user_status/", $result));
$this->assertTrue(false == preg_match("/:userId/", $result));
$this->assertTrue(false == preg_match("/:user_status/", $result));
}

public function testValuesGetInterpolatedIntoQueryStatementWhenBoundIndividuallyAsNamedParametersWithoutLeadingColons()
Expand All @@ -89,8 +89,8 @@ public function testValuesGetInterpolatedIntoQueryStatementWhenBoundIndividually
$this->assertTrue(false != preg_match("/123/", $result));
$this->assertTrue(false != preg_match("/active/", $result));

$this->assertTrue(false == preg_match("/\:userId/", $result));
$this->assertTrue(false == preg_match("/\:user_status/", $result));
$this->assertTrue(false == preg_match("/:userId/", $result));
$this->assertTrue(false == preg_match("/:user_status/", $result));
}

public function testValuesGetInterpolatedIntoQueryStatementWhenBoundIndividuallyAsUnnamedParameters()
Expand Down Expand Up @@ -140,8 +140,8 @@ public function testValuesGetInterpolatedIntoQueryWhenProvidedAsNamedInputParame
$this->assertTrue(false != preg_match("/123/", $result));
$this->assertTrue(false != preg_match("/active/", $result));

$this->assertTrue(false == preg_match("/\:userId/", $result));
$this->assertTrue(false == preg_match("/\:user_status/", $result));
$this->assertTrue(false == preg_match("/:userId/", $result));
$this->assertTrue(false == preg_match("/:user_status/", $result));
}

public function testValuesGetInterpolatedIntoQueryWhenProvidedAsUnnamedInputParameters()
Expand Down Expand Up @@ -194,25 +194,48 @@ public function testValuesGetInterpolatedCorrectlyWhenSimilarlyNamedPlaceholders
$this->assertTrue(false != preg_match("/123/", $result));
$this->assertTrue(false != preg_match("/log content/", $result));

$this->assertTrue(false == preg_match("/\:logContent/", $result));
$this->assertTrue(false == preg_match("/\:log/", $result));
$this->assertTrue(false == preg_match("/:logContent/", $result));
$this->assertTrue(false == preg_match("/:log/", $result));
}

public function testInterpolationAllowsSuccessfulExecutionOfQueries()
{
$pdo = $this->getPdo();

$query = "SELECT ? + ? + ?";
$query = "SELECT ? + ? + ?, ?";

$stmt = $pdo->prepare($query);

$values = array(1, 1, 1);
$values = array(1, 1, 1, "test string");

$stmt->execute($values);

list($sum) = $stmt->fetch();
list($sum, $testString) = $stmt->fetch();

$this->assertEquals(3, $sum);
$this->assertEquals("test string", $testString);
}

public function tetstInterpolationAllowsSuccessfulExecutionOfQueriesWithNamedPlaceholders()
{
$num = 3;
$string = "someString";

$pdo = $this->getPdo();

$query = "SELECT :num, :string";

$stmt = $pdo->prepare($query);

$stmt->bindParam(":num", $num, PDO::PARAM_INT);
$stmt->bindParam(":string", $string, PDO::PARAM_STR);

$stmt->execute();

list($sum, $testString) = $stmt->fetch();

$this->assertEquals(3, $sum);
$this->assertEquals("test string", $testString);
}

public function testValuesAreSuccessfullyInterpolatedIfNoPdoProvidedToEPDOStatement()
Expand Down Expand Up @@ -240,8 +263,8 @@ public function testValuesAreSuccessfullyInterpolatedIfNoPdoProvidedToEPDOStatem
$this->assertTrue(false != preg_match("/123/", $result));
$this->assertTrue(false != preg_match("/active/", $result));

$this->assertTrue(false == preg_match("/\:userId/", $result));
$this->assertTrue(false == preg_match("/\:user_status/", $result));
$this->assertTrue(false == preg_match("/:userId/", $result));
$this->assertTrue(false == preg_match("/:user_status/", $result));
}

public function testQueryIsNotChangedIfNoParametersUsedInQuery()
Expand Down

0 comments on commit 702f1f7

Please sign in to comment.