diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..fe0f243 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: usmanhalalit diff --git a/.travis.yml b/.travis.yml index aa02544..ad693f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,10 @@ +dist: trusty sudo: false + language: php php: - - 5.4 - 5.5 - 7.0 diff --git a/README.md b/README.md index 82ca0ed..ed731cd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,14 @@ -# Pixie Query Builder [![Build Status](https://travis-ci.org/usmanhalalit/pixie.png?branch=master)](https://travis-ci.org/usmanhalalit/pixie) -A lightweight, expressive, framework agnostic query builder for PHP it can also be referred as a Database Abstraction Layer. Pixie supports MySQL, SQLite and PostgreSQL and it takes care of query sanitization, table prefixing and many other things with a unified API. At least PHP 5.3 is required. +**This project is Not Actively Maintained but most of the features are fully working and there are no major security issues, I'm just not giving it much time.** + + +# Pixie Query Builder + +[![Build Status](https://travis-ci.org/usmanhalalit/pixie.svg?branch=master)](https://travis-ci.org/usmanhalalit/pixie) +[![Total Downloads](https://poser.pugx.org/usmanhalalit/pixie/downloads)](https://packagist.org/packages/usmanhalalit/pixie) +[![Daily Downloads](https://poser.pugx.org/usmanhalalit/pixie/d/daily)](https://packagist.org/packages/usmanhalalit/pixie) + + +A lightweight, expressive, framework agnostic query builder for PHP it can also be referred as a Database Abstraction Layer. Pixie supports MySQL, SQLite and PostgreSQL and it takes care of query sanitization, table prefixing and many other things with a unified API. It has some advanced features like: @@ -17,7 +26,7 @@ The syntax is quite similar to Laravel's query builder. require 'vendor/autoload.php'; // Create a connection, once only. -$config = array( +$config = [ 'driver' => 'mysql', // Db driver 'host' => 'localhost', 'database' => 'your-database', @@ -26,11 +35,11 @@ $config = array( 'charset' => 'utf8', // Optional 'collation' => 'utf8_unicode_ci', // Optional 'prefix' => 'cb_', // Table prefix, optional - 'options' => array( // PDO constructor options, optional + 'options' => [ // PDO constructor options, optional PDO::ATTR_TIMEOUT => 5, PDO::ATTR_EMULATE_PREPARES => false, - ), - ); + ], + ]; new \Pixie\Connection('mysql', $config, 'QB'); ``` @@ -86,7 +95,7 @@ Library on [Packagist](https://packagist.org/packages/usmanhalalit/pixie). - [Connection](#connection) - [Alias](#alias) - [Multiple Connection](#alias) - - [SQLite and PostgreSQL Config Sample](sqlite-and-postgresql-config-sample) + - [SQLite and PostgreSQL Config Sample](#sqlite-and-postgresql-config-sample) - [Query](#query) - [**Select**](#select) - [Get Easily](#get-easily) @@ -159,7 +168,7 @@ new \Pixie\Connection('mysql', $config, 'MyAlias'); When not using an alias you can instantiate the QueryBuilder handler separately, helpful for Dependency Injection and Testing. ```PHP -$connection = new \Pixie\Connection('mysql', $config)); +$connection = new \Pixie\Connection('mysql', $config); $qb = new \Pixie\QueryBuilder\QueryBuilderHandler($connection); $query = $qb->table('my_table')->where('name', '=', 'Sana'); @@ -489,7 +498,7 @@ If you wish to manually commit or rollback your changes, you can use the `commit()` and `rollback()` methods accordingly: ```PHP -QB::transaction(function (qb) { +QB::transaction(function ($qb) { $qb->table('my_table')->insert(array(/* data... */)); $qb->commit(); // to commit the changes (data would be saved) @@ -621,7 +630,7 @@ QB::registerEvent('after-delete', 'my_table', function($queryBuilder, $queryObje Pixie passes the current instance of query builder as first parameter of your closure so you can build queries with this object, you can do anything like usual query builder (`QB`). -If something other than `null` is returned from the `before-*` query handler, the value will be result of execution and DB will not be actually queried (and thus, corresponding `after-*` handler will not be called ether). +If something other than `null` is returned from the `before-*` query handler, the value will be result of execution and DB will not be actually queried (and thus, corresponding `after-*` handler will not be called either). Only on `after-*` events you get three parameters: **first** is the query builder, **third** is the execution time as float and **the second** varies: @@ -656,4 +665,4 @@ Here are some cases where Query Events can be extremely helpful: ___ If you find any typo then please edit and send a pull request. -© 2016 [Muhammad Usman](http://usman.it/). Licensed under MIT license. +© 2020 [Muhammad Usman](http://usman.it/). Licensed under MIT license. diff --git a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php index ade1a1b..d6248c1 100644 --- a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php +++ b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php @@ -65,8 +65,8 @@ public function select($statements) } // Limit and offset - $limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : ''; - $offset = isset($statements['offset']) ? 'OFFSET ' . $statements['offset'] : ''; + $limit = isset($statements['limit']) ? 'LIMIT ' . (int) $statements['limit'] : ''; + $offset = isset($statements['offset']) ? 'OFFSET ' . (int) $statements['offset'] : ''; // Having list($havingCriteria, $havingBindings) = $this->buildCriteriaWithType($statements, 'havings', 'HAVING'); @@ -164,7 +164,7 @@ private function doInsert($statements, array $data, $type) $bindings = array_merge($bindings, $updateBindings); } - $sql = $this->concatenateQuery($sqlArray, ' ', false); + $sql = $this->concatenateQuery($sqlArray); return compact('sql', 'bindings'); } @@ -272,7 +272,7 @@ public function update($statements, array $data) $limit ); - $sql = $this->concatenateQuery($sqlArray, ' ', false); + $sql = $this->concatenateQuery($sqlArray); $bindings = array_merge($bindings, $whereBindings); return compact('sql', 'bindings'); @@ -301,7 +301,7 @@ public function delete($statements) $limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : ''; $sqlArray = array('DELETE FROM', $this->wrapSanitizer($table), $whereCriteria); - $sql = $this->concatenateQuery($sqlArray, ' ', false); + $sql = $this->concatenateQuery($sqlArray); $bindings = $whereBindings; return compact('sql', 'bindings'); diff --git a/src/Pixie/QueryBuilder/QueryBuilderHandler.php b/src/Pixie/QueryBuilder/QueryBuilderHandler.php index 134fba0..f7fd976 100644 --- a/src/Pixie/QueryBuilder/QueryBuilderHandler.php +++ b/src/Pixie/QueryBuilder/QueryBuilderHandler.php @@ -23,7 +23,7 @@ class QueryBuilderHandler protected $statements = array(); /** - * @var \PDO + * @var PDO */ protected $pdo; @@ -47,14 +47,15 @@ class QueryBuilderHandler * * @var array */ - protected $fetchParameters = array(\PDO::FETCH_OBJ); + protected $fetchParameters = array(PDO::FETCH_OBJ); /** * @param null|\Pixie\Connection $connection * - * @throws \Pixie\Exception + * @param int $fetchMode + * @throws Exception */ - public function __construct(Connection $connection = null) + public function __construct(Connection $connection = null, $fetchMode = PDO::FETCH_OBJ) { if (is_null($connection)) { if (!$connection = Connection::getStoredConnection()) { @@ -68,6 +69,8 @@ public function __construct(Connection $connection = null) $this->adapter = $this->connection->getAdapter(); $this->adapterConfig = $this->connection->getAdapterConfig(); + $this->setFetchMode($fetchMode); + if (isset($this->adapterConfig['prefix'])) { $this->tablePrefix = $this->adapterConfig['prefix']; } @@ -102,13 +105,13 @@ public function setFetchMode($mode) */ public function asObject($className, $constructorArgs = array()) { - return $this->setFetchMode(\PDO::FETCH_CLASS, $className, $constructorArgs); + return $this->setFetchMode(PDO::FETCH_CLASS, $className, $constructorArgs); } /** * @param null|\Pixie\Connection $connection - * - * @return static + * @return QueryBuilderHandler + * @throws Exception */ public function newQuery(Connection $connection = null) { @@ -116,7 +119,7 @@ public function newQuery(Connection $connection = null) $connection = $this->connection; } - return new static($connection); + return new static($connection, $this->getFetchMode()); } /** @@ -156,7 +159,8 @@ public function statement($sql, $bindings = array()) /** * Get all rows * - * @return \stdClass|null + * @return \stdClass|array + * @throws Exception */ public function get() { @@ -259,9 +263,9 @@ protected function aggregate($type) } if (is_array($row[0])) { - return (int) $row[0]['field']; + return (int)$row[0]['field']; } elseif (is_object($row[0])) { - return (int) $row[0]->field; + return (int)$row[0]->field; } return 0; @@ -269,7 +273,7 @@ protected function aggregate($type) /** * @param string $type - * @param array $dataToBePassed + * @param array $dataToBePassed * * @return mixed * @throws Exception @@ -291,7 +295,7 @@ public function getQuery($type = 'select', $dataToBePassed = array()) /** * @param QueryBuilderHandler $queryBuilder - * @param null $alias + * @param null $alias * * @return Raw */ @@ -440,10 +444,10 @@ public function delete() } /** - * @param $tables Single table or multiple tables as an array or as - * multiple parameters + * @param string|array $tables Single table or array of tables * - * @return static + * @return QueryBuilderHandler + * @throws Exception */ public function table($tables) { @@ -453,7 +457,7 @@ public function table($tables) $tables = func_get_args(); } - $instance = new static($this->connection); + $instance = new static($this->connection, $this->getFetchMode()); $tables = $this->addTablePrefix($tables, false); $instance->addStatement('tables', $tables); return $instance; @@ -791,7 +795,7 @@ public function join($table, $key, $operator = null, $value = null, $type = 'inn // Build a new JoinBuilder class, keep it by reference so any changes made // in the closure should reflect here $joinBuilder = $this->container->build('\\Pixie\\QueryBuilder\\JoinBuilder', array($this->connection)); - $joinBuilder = & $joinBuilder; + $joinBuilder = &$joinBuilder; // Call the closure with our new joinBuilder object $key($joinBuilder); $table = $this->addTablePrefix($table, false); @@ -1012,7 +1016,7 @@ public function getEvent($event, $table = ':any') /** * @param $event - * @param string $table + * @param string $table * @param callable $action * * @return void @@ -1030,7 +1034,7 @@ public function registerEvent($event, $table, \Closure $action) /** * @param $event - * @param string $table + * @param string $table * * @return void */ @@ -1061,4 +1065,13 @@ public function getStatements() { return $this->statements; } + + /** + * @return int will return PDO Fetch mode + */ + public function getFetchMode() + { + return !empty($this->fetchParameters) ? + current($this->fetchParameters) : PDO::FETCH_OBJ; + } } diff --git a/tests/Pixie/QueryBuilderBehaviorTest.php b/tests/Pixie/QueryBuilderBehaviorTest.php index 40030d9..e1c3a88 100644 --- a/tests/Pixie/QueryBuilderBehaviorTest.php +++ b/tests/Pixie/QueryBuilderBehaviorTest.php @@ -1,6 +1,6 @@ getQuery()->getRawSql() ); } + + public function testYouCanSetFetchModeFromConstructorAsOptionalParameter() + { + $selectedFetchMode = \PDO::FETCH_ASSOC; + $builder = new QueryBuilderHandler($this->mockConnection, $selectedFetchMode); + $this->assertEquals($selectedFetchMode, $builder->getFetchMode()); + } + + public function testFetchModeSelectedWillBeMaintainedBetweenInstances(){ + $selectedFetchMode = \PDO::FETCH_ASSOC; + $builder = new QueryBuilderHandler($this->mockConnection, $selectedFetchMode); + $newBuilder = $builder->table('stuff'); + + $this->assertEquals($selectedFetchMode, $newBuilder->getFetchMode()); + } }