diff --git a/README.md b/README.md index 25d267e6..c877051f 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ > The Lightest PHP database framework to accelerate development -### Main Features +## Main Features -* **Lightweight** - Only 20KB with one file. +* **Lightweight** - 20KB around with only one file. * **Easy** - Extremely easy to learn and use, friendly construction. @@ -18,10 +18,25 @@ * **Free** - Under MIT license, you can use it anywhere if you want. -### Get Started +## Get Started + +### Install via composer + +Add Medoo to composer.json configuration file. +``` +$ composer require catfan/Medoo +``` + +And update the composer +``` +$ composer update +``` ```php -// Include Medoo +// If you installed via composer, just use this code to requrie autoloader on the top of your projects. +require 'vendor/autoload.php'; + +// Or if you just download the medoo.php into directory, require it with the correct path. require_once 'medoo.php'; // Initialize @@ -41,12 +56,9 @@ $database->insert('account', [ 'age' => 25, 'lang' => ['en', 'fr', 'jp', 'cn'] ]); - -// Or initialize from file and then -$database = new medoo(); ``` -### Contribution Guides +## Contribution Guides For most of time, Medoo is using develop branch for adding feature and fixing bug, and the branch will be merged into master branch while releasing a public version. For contribution, submit your code to the develop branch, and start a pull request into it. @@ -54,11 +66,11 @@ On develop branch, each commits are started with `[fix]`, `[feature]` or `[updat Keep it simple and keep it clear. -### License +## License Medoo is under the MIT License. -### Links +## Links * Official website: [http://medoo.in](http://medoo.in) diff --git a/composer.json b/composer.json index 1fabd8b6..b9569a88 100644 --- a/composer.json +++ b/composer.json @@ -6,19 +6,19 @@ "homepage": "http://medoo.in", "license": "MIT", "authors": [ - {"name": "Angel Lai", "email": "angel.lai.cat@gmail.com"} + {"name": "Angel Lai", "email": "angel@catfan.me"} ], "require": { "php": ">=5.1", "ext-pdo": "*" }, "suggest": { - "ext-pdo-mysql": "For MySQL or MariaDB databases", + "ext-pdo_mysql": "For MySQL or MariaDB databases", "ext-pdo_sqlsrv": "For MSSQL databases on Windows platform", - "ext-pdo_dblib": "For MSSQL or Sybase databases on Liunx/UNIX platform", + "ext-pdo_dblib": "For MSSQL or Sybase databases on Linux/UNIX platform", "ext-pdo_oci": "For Oracle databases", - "ext-pdo-pqsql": "For PostgreSQL databases", - "ext-pdo-sqlite": "For SQLite databases" + "ext-pdo_pqsql": "For PostgreSQL databases", + "ext-pdo_sqlite": "For SQLite databases" }, "autoload": { "files": ["medoo.php"] diff --git a/medoo.php b/medoo.php index eb8cdc6d..6897f7a3 100644 --- a/medoo.php +++ b/medoo.php @@ -2,7 +2,7 @@ /*! * Medoo database framework * http://medoo.in - * Version 0.9.8.3 + * Version 1.0 * * Copyright 2015, Angel Lai * Released under the MIT license @@ -32,6 +32,8 @@ class medoo // Optional protected $port; + protected $prefix; + protected $option = array(); // Variable @@ -43,25 +45,19 @@ public function __construct($options = null) { try { $commands = array(); + $dsn = ''; - if (is_string($options) && !empty($options)) - { - if (strtolower($this->database_type) == 'sqlite') - { - $this->database_file = $options; - } - else - { - $this->database_name = $options; - } - } - elseif (is_array($options)) + if (is_array($options)) { foreach ($options as $option => $value) { $this->$option = $value; } } + else + { + return false; + } if ( isset($this->port) && @@ -74,6 +70,11 @@ public function __construct($options = null) $type = strtolower($this->database_type); $is_port = isset($port); + if (isset($options[ 'prefix' ])) + { + $this->prefix = $options[ 'prefix' ]; + } + switch ($type) { case 'mariadb': @@ -189,7 +190,7 @@ public function quote($string) protected function column_quote($string) { - return '"' . str_replace('.', '"."', preg_replace('/(^#|\(JSON\))/', '', $string)) . '"'; + return '"' . str_replace('.', '"."', preg_replace('/(^#|\(JSON\)\s*)/', '', $string)) . '"'; } protected function column_push($columns) @@ -210,9 +211,9 @@ protected function column_push($columns) { preg_match('/([a-zA-Z0-9_\-\.]*)\s*\(([a-zA-Z0-9_\-]*)\)/i', $value, $match); - if (isset($match[1], $match[2])) + if (isset($match[ 1 ], $match[ 2 ])) { - array_push($stack, $this->column_quote( $match[1] ) . ' AS ' . $this->column_quote( $match[2] )); + array_push($stack, $this->column_quote( $match[ 1 ] ) . ' AS ' . $this->column_quote( $match[ 2 ] )); } else { @@ -270,17 +271,17 @@ protected function data_implode($data, $conjunctor, $outer_conjunctor = null) ) { $wheres[] = 0 !== count(array_diff_key($value, array_keys(array_keys($value)))) ? - '(' . $this->data_implode($value, ' ' . $relation_match[1]) . ')' : - '(' . $this->inner_conjunct($value, ' ' . $relation_match[1], $conjunctor) . ')'; + '(' . $this->data_implode($value, ' ' . $relation_match[ 1 ]) . ')' : + '(' . $this->inner_conjunct($value, ' ' . $relation_match[ 1 ], $conjunctor) . ')'; } else { - preg_match('/(#?)([\w\.]+)(\[(\>|\>\=|\<|\<\=|\!|\<\>|\>\<|\!?~)\])?/i', $key, $match); - $column = $this->column_quote($match[2]); + preg_match('/(#?)([\w\.\-]+)(\[(\>|\>\=|\<|\<\=|\!|\<\>|\>\<|\!?~)\])?/i', $key, $match); + $column = $this->column_quote($match[ 2 ]); - if (isset($match[4])) + if (isset($match[ 4 ])) { - $operator = $match[4]; + $operator = $match[ 4 ]; if ($operator == '!') { @@ -318,13 +319,13 @@ protected function data_implode($data, $conjunctor, $outer_conjunctor = null) $column .= ' NOT'; } - if (is_numeric($value[0]) && is_numeric($value[1])) + if (is_numeric($value[ 0 ]) && is_numeric($value[ 1 ])) { - $wheres[] = '(' . $column . ' BETWEEN ' . $value[0] . ' AND ' . $value[1] . ')'; + $wheres[] = '(' . $column . ' BETWEEN ' . $value[ 0 ] . ' AND ' . $value[ 1 ] . ')'; } else { - $wheres[] = '(' . $column . ' BETWEEN ' . $this->quote($value[0]) . ' AND ' . $this->quote($value[1]) . ')'; + $wheres[] = '(' . $column . ' BETWEEN ' . $this->quote($value[ 0 ]) . ' AND ' . $this->quote($value[ 1 ]) . ')'; } } } @@ -342,17 +343,12 @@ protected function data_implode($data, $conjunctor, $outer_conjunctor = null) foreach ($value as $item) { - if ($operator == '!~') - { - $column .= ' NOT'; - } - if (preg_match('/^(?!%).+(?fn_quote($key, $item); + $like_clauses[] = $column . ($operator === '!~' ? ' NOT' : '') . ' LIKE ' . $this->fn_quote($key, $item); } $wheres[] = implode(' OR ', $like_clauses); @@ -429,48 +425,48 @@ protected function where_clause($where) if (!empty($where_AND)) { $value = array_values($where_AND); - $where_clause = ' WHERE ' . $this->data_implode($where[ $value[0] ], ' AND'); + $where_clause = ' WHERE ' . $this->data_implode($where[ $value[ 0 ] ], ' AND'); } if (!empty($where_OR)) { $value = array_values($where_OR); - $where_clause = ' WHERE ' . $this->data_implode($where[ $value[0] ], ' OR'); + $where_clause = ' WHERE ' . $this->data_implode($where[ $value[ 0 ] ], ' OR'); } - if (isset($where['MATCH'])) + if (isset($where[ 'MATCH' ])) { - $MATCH = $where['MATCH']; + $MATCH = $where[ 'MATCH' ]; - if (is_array($MATCH) && isset($MATCH['columns'], $MATCH['keyword'])) + if (is_array($MATCH) && isset($MATCH[ 'columns' ], $MATCH[ 'keyword' ])) { - $where_clause .= ($where_clause != '' ? ' AND ' : ' WHERE ') . ' MATCH ("' . str_replace('.', '"."', implode($MATCH['columns'], '", "')) . '") AGAINST (' . $this->quote($MATCH['keyword']) . ')'; + $where_clause .= ($where_clause != '' ? ' AND ' : ' WHERE ') . ' MATCH ("' . str_replace('.', '"."', implode($MATCH[ 'columns' ], '", "')) . '") AGAINST (' . $this->quote($MATCH[ 'keyword' ]) . ')'; } } - if (isset($where['GROUP'])) + if (isset($where[ 'GROUP' ])) { - $where_clause .= ' GROUP BY ' . $this->column_quote($where['GROUP']); + $where_clause .= ' GROUP BY ' . $this->column_quote($where[ 'GROUP' ]); - if (isset($where['HAVING'])) + if (isset($where[ 'HAVING' ])) { - $where_clause .= ' HAVING ' . $this->data_implode($where['HAVING'], ' AND'); + $where_clause .= ' HAVING ' . $this->data_implode($where[ 'HAVING' ], ' AND'); } } - if (isset($where['ORDER'])) + if (isset($where[ 'ORDER' ])) { $rsort = '/(^[a-zA-Z0-9_\-\.]*)(\s*(DESC|ASC))?/'; - $ORDER = $where['ORDER']; + $ORDER = $where[ 'ORDER' ]; if (is_array($ORDER)) { if ( - isset($ORDER[1]) && - is_array($ORDER[1]) + isset($ORDER[ 1 ]) && + is_array($ORDER[ 1 ]) ) { - $where_clause .= ' ORDER BY FIELD(' . $this->column_quote($ORDER[0]) . ', ' . $this->array_quote($ORDER[1]) . ')'; + $where_clause .= ' ORDER BY FIELD(' . $this->column_quote($ORDER[ 0 ]) . ', ' . $this->array_quote($ORDER[ 1 ]) . ')'; } else { @@ -480,7 +476,7 @@ protected function where_clause($where) { preg_match($rsort, $column, $order_match); - array_push($stack, '"' . str_replace('.', '"."', $order_match[1]) . '"' . (isset($order_match[3]) ? ' ' . $order_match[3] : '')); + array_push($stack, '"' . str_replace('.', '"."', $order_match[ 1 ]) . '"' . (isset($order_match[ 3 ]) ? ' ' . $order_match[ 3 ] : '')); } $where_clause .= ' ORDER BY ' . implode($stack, ','); @@ -490,13 +486,13 @@ protected function where_clause($where) { preg_match($rsort, $ORDER, $order_match); - $where_clause .= ' ORDER BY "' . str_replace('.', '"."', $order_match[1]) . '"' . (isset($order_match[3]) ? ' ' . $order_match[3] : ''); + $where_clause .= ' ORDER BY "' . str_replace('.', '"."', $order_match[ 1 ]) . '"' . (isset($order_match[ 3 ]) ? ' ' . $order_match[ 3 ] : ''); } } - if (isset($where['LIMIT'])) + if (isset($where[ 'LIMIT' ])) { - $LIMIT = $where['LIMIT']; + $LIMIT = $where[ 'LIMIT' ]; if (is_numeric($LIMIT)) { @@ -505,17 +501,17 @@ protected function where_clause($where) if ( is_array($LIMIT) && - is_numeric($LIMIT[0]) && - is_numeric($LIMIT[1]) + is_numeric($LIMIT[ 0 ]) && + is_numeric($LIMIT[ 1 ]) ) { if ($this->database_type === 'pgsql') { - $where_clause .= ' OFFSET ' . $LIMIT[0] . ' LIMIT ' . $LIMIT[1]; + $where_clause .= ' OFFSET ' . $LIMIT[ 0 ] . ' LIMIT ' . $LIMIT[ 1 ]; } else { - $where_clause .= ' LIMIT ' . $LIMIT[0] . ',' . $LIMIT[1]; + $where_clause .= ' LIMIT ' . $LIMIT[ 0 ] . ',' . $LIMIT[ 1 ]; } } } @@ -533,12 +529,12 @@ protected function where_clause($where) protected function select_context($table, $join, &$columns = null, $where = null, $column_fn = null) { - $table = '"' . $table . '"'; + $table = '"' . $this->prefix . $table . '"'; $join_key = is_array($join) ? array_keys($join) : null; if ( - isset($join_key[0]) && - strpos($join_key[0], '[') === 0 + isset($join_key[ 0 ]) && + strpos($join_key[ 0 ], '[') === 0 ) { $table_join = array(); @@ -554,7 +550,7 @@ protected function select_context($table, $join, &$columns = null, $where = null { preg_match('/(\[(\<|\>|\>\<|\<\>)\])?([a-zA-Z0-9_\-]*)\s?(\(([a-zA-Z0-9_\-]*)\))?/', $sub_table, $match); - if ($match[2] != '' && $match[3] != '') + if ($match[ 2 ] != '' && $match[ 3 ] != '') { if (is_string($relation)) { @@ -564,7 +560,7 @@ protected function select_context($table, $join, &$columns = null, $where = null if (is_array($relation)) { // For ['column1', 'column2'] - if (isset($relation[0])) + if (isset($relation[ 0 ])) { $relation = 'USING ("' . implode($relation, '", "') . '")'; } @@ -583,14 +579,14 @@ protected function select_context($table, $join, &$columns = null, $where = null $table . '."' . $key . '"' ) . ' = ' . - '"' . (isset($match[5]) ? $match[5] : $match[3]) . '"."' . $value . '"'; + '"' . (isset($match[ 5 ]) ? $match[ 5 ] : $match[ 3 ]) . '"."' . $value . '"'; } $relation = 'ON ' . implode($joins, ' AND '); } } - $table_join[] = $join_array[ $match[2] ] . ' JOIN "' . $match[3] . '" ' . (isset($match[5]) ? 'AS "' . $match[5] . '" ' : '') . $relation; + $table_join[] = $join_array[ $match[ 2 ] ] . ' JOIN "' . $match[ 3 ] . '" ' . (isset($match[ 5 ]) ? 'AS "' . $match[ 5 ] . '" ' : '') . $relation; } } @@ -673,7 +669,7 @@ public function insert($table, $datas) $lastId = array(); // Check indexed or associative array - if (!isset($datas[0])) + if (!isset($datas[ 0 ])) { $datas = array($datas); } @@ -696,7 +692,7 @@ public function insert($table, $datas) case 'array': preg_match("/\(JSON\)\s*([\w]+)/i", $key, $column_match); - $values[] = isset($column_match[0]) ? + $values[] = isset($column_match[ 0 ]) ? $this->quote(json_encode($value)) : $this->quote(serialize($value)); break; @@ -713,7 +709,7 @@ public function insert($table, $datas) } } - $this->exec('INSERT INTO "' . $table . '" (' . implode(', ', $columns) . ') VALUES (' . implode($values, ', ') . ')'); + $this->exec('INSERT INTO "' . $this->prefix . $table . '" (' . implode(', ', $columns) . ') VALUES (' . implode($values, ', ') . ')'); $lastId[] = $this->pdo->lastInsertId(); } @@ -729,11 +725,11 @@ public function update($table, $data, $where = null) { preg_match('/([\w]+)(\[(\+|\-|\*|\/)\])?/i', $key, $match); - if (isset($match[3])) + if (isset($match[ 3 ])) { if (is_numeric($value)) { - $fields[] = $this->column_quote($match[1]) . ' = ' . $this->column_quote($match[1]) . ' ' . $match[3] . ' ' . $value; + $fields[] = $this->column_quote($match[ 1 ]) . ' = ' . $this->column_quote($match[ 1 ]) . ' ' . $match[ 3 ] . ' ' . $value; } } else @@ -750,7 +746,7 @@ public function update($table, $data, $where = null) preg_match("/\(JSON\)\s*([\w]+)/i", $key, $column_match); $fields[] = $column . ' = ' . $this->quote( - isset($column_match[0]) ? json_encode($value) : serialize($value) + isset($column_match[ 0 ]) ? json_encode($value) : serialize($value) ); break; @@ -767,12 +763,12 @@ public function update($table, $data, $where = null) } } - return $this->exec('UPDATE "' . $table . '" SET ' . implode(', ', $fields) . $this->where_clause($where)); + return $this->exec('UPDATE "' . $this->prefix . $table . '" SET ' . implode(', ', $fields) . $this->where_clause($where)); } public function delete($table, $where) { - return $this->exec('DELETE FROM "' . $table . '"' . $this->where_clause($where)); + return $this->exec('DELETE FROM "' . $this->prefix . $table . '"' . $this->where_clause($where)); } public function replace($table, $columns, $search = null, $replace = null, $where = null) @@ -812,7 +808,7 @@ public function replace($table, $columns, $search = null, $replace = null, $wher } } - return $this->exec('UPDATE "' . $table . '" SET ' . $replace_query . $this->where_clause($where)); + return $this->exec('UPDATE "' . $this->prefix . $table . '" SET ' . $replace_query . $this->where_clause($where)); } public function get($table, $join = null, $column = null, $where = null) @@ -823,7 +819,7 @@ public function get($table, $join = null, $column = null, $where = null) { $data = $query->fetchAll(PDO::FETCH_ASSOC); - if (isset($data[0])) + if (isset($data[ 0 ])) { $column = $where == null ? $join : $column; @@ -907,6 +903,29 @@ public function sum($table, $join, $column = null, $where = null) return $query ? 0 + $query->fetchColumn() : false; } + public function action($actions) + { + if (is_callable($actions)) + { + $this->pdo->beginTransaction(); + + $result = $actions($this); + + if ($result === false) + { + $this->pdo->rollBack(); + } + else + { + $this->pdo->commit(); + } + } + else + { + return false; + } + } + public function debug() { $this->debug_mode = true;