├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── phpcs.xml ├── phpunit.xml ├── src ├── Api │ ├── AlterInterface.php │ ├── CreateInterface.php │ ├── DeleteInterface.php │ ├── DropInterface.php │ ├── SelectInterface.php │ └── UpdateInterface.php ├── Connect.php ├── DB.php ├── QueryFactory.php ├── SqlGenerator.php ├── Statement │ ├── Alter.php │ ├── Create.php │ ├── Delete.php │ ├── Drop.php │ ├── Insert.php │ ├── Select.php │ └── Update.php └── Utilities.php └── tests ├── CreateTest.php ├── SelectTest.php ├── Statement ├── CreateApi.php ├── SelectApi.php └── UpdateApi.php └── UpdateTest.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | indent_style = tab 8 | indent_size = 4 9 | tab_width = 4 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | vendor 9 | composer.lock 10 | 11 | .DS_Store 12 | .github/ 13 | doc/ 14 | 15 | .phpunit.result.cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 19 | 20 | # Runtime data 21 | pids 22 | *.pid 23 | *.seed 24 | *.pid.lock 25 | 26 | # Directory for instrumented libs generated by jscoverage/JSCover 27 | lib-cov 28 | 29 | # Coverage directory used by tools like istanbul 30 | coverage 31 | *.lcov 32 | 33 | # nyc test coverage 34 | .nyc_output 35 | 36 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 37 | .grunt 38 | 39 | # Bower dependency directory (https://bower.io/) 40 | bower_components 41 | 42 | # node-waf configuration 43 | .lock-wscript 44 | 45 | # Compiled binary addons (https://nodejs.org/api/addons.html) 46 | build/Release 47 | 48 | # Dependency directories 49 | node_modules/ 50 | jspm_packages/ 51 | 52 | # TypeScript v1 declaration files 53 | typings/ 54 | 55 | # TypeScript cache 56 | *.tsbuildinfo 57 | 58 | # Optional npm cache directory 59 | .npm 60 | 61 | # Optional eslint cache 62 | .eslintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variables file 80 | .env 81 | .env.test 82 | 83 | # parcel-bundler cache (https://parceljs.org/) 84 | .cache 85 | 86 | # Next.js build output 87 | .next 88 | 89 | # Nuxt.js build / generate output 90 | .nuxt 91 | dist 92 | 93 | # Gatsby files 94 | .cache/ 95 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 96 | # https://nextjs.org/blog/next-9-1#public-directory-support 97 | # public 98 | 99 | # vuepress build output 100 | .vuepress/dist 101 | 102 | # Serverless directories 103 | .serverless/ 104 | 105 | # FuseBox cache 106 | .fusebox/ 107 | 108 | # DynamoDB Local files 109 | .dynamodb/ 110 | 111 | # TernJS port file 112 | .tern-port 113 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Keramot UL Islam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WP Query Builder 2 |

3 | Relational Database Query builder for WordPress. 4 | WP Query Builder uses PDO for database queries. It has zero dependencies with third-party query builders or any other composer library. 5 |

6 | 7 |
8 | 9 | # Documentation 10 | Documentation website [here](https://wp-querybuilder.pages.dev/). 11 |
12 | This Query Builder is also used in [Kathamo](https://kathamo.dev) Framework. Kathamo is a modern framework for WordPress plugin development. 13 | 14 |
15 | 16 | ## Examples 17 | 18 | ### Create Table 19 | ``` php 20 | DB::create('querybuilder') 21 | ->column('ID')->bigInt()->unsigned()->autoIncrement()->primary()->required() 22 | ->column('user_id')->bigInt()->unsigned()->required() 23 | ->column('name')->string(255)->required() 24 | ->column('email')->string(255)->nullable() 25 | ->column('settings')->enum(['active', 'inactive']) 26 | ->column('created_at')->timestamp('now', 'current') 27 | ->foreignKey('user_id', 'users.ID', 'cascade') 28 | ->index(['ID']) 29 | ->execute(); 30 | ``` 31 | 32 |
33 | 34 | ### Insert Statement 35 | ``` php 36 | DB::insert('querybuilder', [ 37 | [ 38 | 'name' => 'Keramot UL Islam', 39 | 'email' => 'keramotul.@gmail.com', 40 | ] 41 | ]); 42 | ``` 43 | 44 |
45 | 46 | ### Update Statement 47 | 48 | ``` php 49 | DB::update('querybuilders', [ 50 | 'name' => 'Keramot UL', 51 | 'email' => 'keramotul.islam@gmail.com' 52 | ]) 53 | ->where('ID', '=', 10) 54 | ->andWhere('name', '=', 'Abm Sourav') 55 | ->execute(); 56 | ``` 57 | 58 |
59 | 60 | ### Select Statement 61 | 62 | ``` php 63 | $result = 64 | DB::select('qb.ID', 'qb.name, qb.email') 65 | ->from('querybuilders') 66 | ->alias('qb') 67 | ->groupBy('name') 68 | ->get(); 69 | 70 | 71 | // *** where clouse 72 | $result = 73 | DB::select('posts.ID', 'posts.post_title') 74 | ->distinct() 75 | ->from('posts posts') 76 | ->where('posts.post_status', '=', 'publish') 77 | ->orderBy('post_title', 'DESC') 78 | ->limit(10)->offset(2) 79 | ->get(); 80 | 81 | // *** JOIN 82 | DB::select('users.display_name name') 83 | ->count('posts.ID', 'posts') 84 | ->from('users users') 85 | ->join('posts posts') 86 | ->where('posts.post_status', '=', 'publish') 87 | ->andWhere('posts.post_type', '=', 'post') 88 | ->get(); 89 | 90 | // raw sql 91 | DB::select('posts.post_title') 92 | ->from('posts posts') 93 | ->raw("WHERE posts.post_type = 'post'") 94 | ->andWhere('posts.post_status', '=', 'publish') 95 | ->raw("LIMIT 10") 96 | ->get(); 97 | ``` 98 | 99 |
100 | 101 | ### Delete Statement 102 | 103 | ``` php 104 | // delete one row 105 | DB::delete('posts') 106 | ->where('ID', '=', 3) 107 | ->execute(); 108 | 109 | // delete all records 110 | DB::delete('posts')->execute(); 111 | ``` 112 | 113 |
114 | 115 | ### Drop Statement 116 | 117 | ``` php 118 | DB::drop('posts'); 119 | DB::dropIfExists('terms'); 120 | ``` 121 | 122 |
123 | 124 | ### Alter Statement 125 | 126 | ``` php 127 | DB::alter('cv_users') 128 | ->modify('name', 'username')->string(455)->required() 129 | ->modify('settings')->json() 130 | ->execute(); 131 | ``` 132 | 133 |
134 |
135 | 136 | ### Single instence 137 |

138 | Expressions also can be exicuted with one instence of DB class. By doing this database connection will be stablished only once. 139 |

140 | 141 | ``` php 142 | $db = new DB(); 143 | 144 | $result = 145 | $db::select('posts.ID', 'posts.post_title') 146 | ... 147 | 148 | $db::create('meta') 149 | ... 150 | ``` 151 | 152 |
153 |
154 | 155 | ### Database Connection 156 | By default database connection will set out of the box, automaically. But you can also manually input database configurations. This way, you also can debug your database queries from terminal. 157 | 158 | ```php 159 | $db = DB::setConnection( 160 | [ 161 | "dbhost" => 'mysql_host', 162 | "dbname" => 'database_name', 163 | "dbuser" => 'database_user', 164 | "dbpassword" => 'database_password', 165 | "prefix" => 'database_table_prefix' 166 | ] 167 | ); 168 | ``` 169 | 170 |
171 |
172 | 173 | ### Driver 174 | 175 | The default driver is `pdo`. But if you want to use `wpdb` which uses Mysqli, you also can do that by changing the driver. 176 | ``` php 177 | $db = new DB('wpdb'); 178 | 179 | $db::select('posts.post_title') 180 | ->from('posts posts') 181 | ->get(); 182 | ``` 183 | 184 |
185 |
186 | 187 | ## Dev Envirenment Setup for Contributors 188 | Want to contribute to this package? Please follow the steps below. 189 | 190 | 211 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codesvault/howdy-qb", 3 | "description": "Mysql Query Builder for WordPress", 4 | "version": "1.6.4", 5 | "minimum-stability": "stable", 6 | "scripts": { 7 | "test": "phpunit", 8 | "phpcs": "phpcs ", 9 | "phpcbf": "phpcbf ", 10 | "post-package-install": "phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility" 11 | }, 12 | "autoload": { 13 | "psr-4": { 14 | "CodesVault\\Howdyqb\\": "src/" 15 | } 16 | }, 17 | "autoload-dev": { 18 | "psr-4": { 19 | "CodesVault\\Howdyqb\\Tests\\": "tests/" 20 | } 21 | }, 22 | "authors": [ 23 | { 24 | "name": "CodesVault", 25 | "email": "codesvault@gmail.com" 26 | }, 27 | { 28 | "name": "Keramot UL Islam", 29 | "email": "keramotul.islam@gmail.com" 30 | } 31 | ], 32 | "license": "MIT", 33 | "require": { 34 | "php": ">=7.1" 35 | }, 36 | "require-dev": { 37 | "phpunit/phpunit": "^9.5", 38 | "symfony/var-dumper": "^5.4", 39 | "squizlabs/php_codesniffer": "^3.7", 40 | "wp-coding-standards/wpcs": "^2.3", 41 | "phpcompatibility/php-compatibility": "^9.3" 42 | }, 43 | "keywords": [ 44 | "wordpress", 45 | "database", 46 | "query builder", 47 | "pdo", 48 | "mysqli", 49 | "query", 50 | "builder", 51 | "mysql", 52 | "wp" 53 | ], 54 | "archive": { 55 | "exclude": [ 56 | ".editorconfig", 57 | ".gitignore", 58 | "tests", 59 | "phpunit.xml", 60 | "phpcs.xml" 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | /tests/* 18 | /vendor/* 19 | /.github/* 20 | 21 | 22 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 13 | 16 | 17 | 18 | ./tests 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Api/AlterInterface.php: -------------------------------------------------------------------------------- 1 | dbhost, ENT_QUOTES); 20 | $dbname = htmlspecialchars($configs->dbname, ENT_QUOTES); 21 | $user = htmlspecialchars($configs->dbuser, ENT_QUOTES); 22 | $password = $configs->dbpassword; 23 | $dns = "mysql:host=$host;dbname=$dbname"; 24 | 25 | try { 26 | return new \PDO($dns, $user, $password); 27 | } catch (\PDOException $exception) { 28 | Utilities::throughException($exception); 29 | } 30 | } 31 | 32 | public static function setManualConnection(array $configs = []) 33 | { 34 | $configurations = []; 35 | if (! defined('DB_HOST')) { 36 | $path = explode('/wp-content', dirname(__DIR__)); 37 | if (! empty($path) && ! file_exists($path[0] . '/wp-config.php')) { 38 | throw new \Exception('wp-config.php file not found'); 39 | } 40 | require $path[0] . '/wp-config.php'; 41 | 42 | $configurations = [ 43 | "dbhost" => DB_HOST, 44 | "dbname" => DB_NAME, 45 | "dbuser" => DB_USER, 46 | "dbpassword" => DB_PASSWORD, 47 | "prefix" => $table_prefix, 48 | ]; 49 | } 50 | 51 | $configurations = array_merge($configurations, $configs); 52 | static::$configs = (object)$configurations; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/DB.php: -------------------------------------------------------------------------------- 1 | selectQuery(); 17 | $query = $query->columns(...$columns); 18 | return $query; 19 | } 20 | 21 | public static function insert(string $table_name, array $data) 22 | { 23 | $factory = new self(static::$driver); 24 | $factory->insertQuery($table_name, $data); 25 | return $factory; 26 | } 27 | 28 | public static function create(string $table_name): CreateInterface 29 | { 30 | $factory = new self(static::$driver); 31 | $create = $factory->createQuery($table_name); 32 | return $create; 33 | } 34 | 35 | public static function alter(string $table_name): AlterInterface 36 | { 37 | $factory = new self(static::$driver); 38 | $alter = $factory->alterQuery($table_name); 39 | return $alter; 40 | } 41 | 42 | public static function update(string $table_name, array $data): UpdateInterface 43 | { 44 | $factory = new self(static::$driver); 45 | $update = $factory->updateQuery($table_name, $data); 46 | return $update; 47 | } 48 | 49 | public static function delete(string $table_name): DeleteInterface 50 | { 51 | $factory = new self(static::$driver); 52 | $delete = $factory->deleteQuery($table_name); 53 | return $delete; 54 | } 55 | 56 | public static function drop(string $table_name) 57 | { 58 | $factory = new self(static::$driver); 59 | $drop = $factory->dropQuery($table_name); 60 | $drop->drop(); 61 | } 62 | 63 | public static function dropIfExists(string $table_name) 64 | { 65 | $factory = new self(static::$driver); 66 | $drop = $factory->dropQuery($table_name); 67 | return $drop->dropIfExists(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/QueryFactory.php: -------------------------------------------------------------------------------- 1 | db) return; 28 | 29 | static::$driver = $driver; 30 | 31 | if ('pdo' === $driver) { 32 | $this->db = Connect::pdo(); 33 | } elseif ('wpdb' === $driver) { 34 | global $wpdb; 35 | $this->db = $wpdb; 36 | } 37 | } 38 | 39 | /** 40 | * Set manula connection 41 | * 42 | * @param array $configs 43 | * @param string $driver 44 | * @return CodesVault\Howdyqb\DB 45 | */ 46 | public static function setConnection($configs = [], $driver = 'pdo') 47 | { 48 | if (! empty($configs)) { 49 | Connect::setManualConnection($configs); 50 | } 51 | static::$config = $configs; 52 | return new DB($driver); 53 | } 54 | 55 | protected function selectQuery(): SelectInterface 56 | { 57 | return new Select($this->db); 58 | } 59 | 60 | protected function insertQuery(string $table_name, array $data) 61 | { 62 | return new Insert($this->db, $table_name, $data); 63 | } 64 | 65 | protected function createQuery(string $table_name) 66 | { 67 | return new Create($this->db, $table_name); 68 | } 69 | 70 | protected function alterQuery(string $table_name) 71 | { 72 | return new Alter($this->db, $table_name); 73 | } 74 | 75 | protected function updateQuery(string $table_name, array $data) 76 | { 77 | return new Update($this->db, $table_name, $data); 78 | } 79 | 80 | protected function deleteQuery(string $table_name) 81 | { 82 | return new Delete($this->db, $table_name); 83 | } 84 | 85 | protected function dropQuery(string $table_name) 86 | { 87 | return new Drop($this->db, $table_name); 88 | } 89 | 90 | public static function getConfig() 91 | { 92 | return static::$config; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/SqlGenerator.php: -------------------------------------------------------------------------------- 1 | $value) { 14 | if ($key == 'start') continue; 15 | $query .= $value . ' '; 16 | } 17 | return trim($query); 18 | } 19 | 20 | public static function insert(array $sql) 21 | { 22 | $query = ''; 23 | if (isset($sql['start'])) { 24 | $query .= $sql['start'] . ' '; 25 | unset($sql['start']); 26 | } 27 | foreach ($sql as $value) { 28 | $query .= $value . ' '; 29 | } 30 | return trim($query); 31 | } 32 | 33 | public static function create(array $sql) 34 | { 35 | $query = ''; 36 | if (isset($sql['start'])) { 37 | $query .= $sql['start'] . ' '; 38 | } 39 | if (isset($sql['table_name'])) { 40 | $query .= $sql['table_name'] . ' '; 41 | } 42 | 43 | $query .= '('; 44 | foreach ($sql as $ex => $expression) { 45 | if ( $ex == 'start' || $ex == 'table_name' ) continue; 46 | 47 | if (is_array($expression)) { 48 | foreach ($expression as $name => $column) { 49 | $expression[$name] = '`'. $name . '` ' . implode(' ', $column); 50 | } 51 | $query .= implode(', ', $expression); 52 | 53 | continue; 54 | } 55 | 56 | $query .= ', ' . $expression . ''; 57 | } 58 | 59 | $query .= ')'; 60 | 61 | return trim($query); 62 | } 63 | 64 | public static function alter(array $sql) 65 | { 66 | $query = ''; 67 | if (isset($sql['start'])) { 68 | $query .= $sql['start'] . ' '; 69 | } 70 | foreach ($sql as $key => $value) { 71 | if ($key == 'start') continue; 72 | $query .= $value . ' '; 73 | } 74 | $query = trim($query); 75 | return $query . ";"; 76 | } 77 | 78 | public static function update(array $sql) 79 | { 80 | $query = ''; 81 | if (isset($sql['start'])) { 82 | $query .= $sql['start'] . ' '; 83 | } 84 | if (isset($sql['set_columns'])) { 85 | $query .= $sql['set_columns'] . ' '; 86 | } 87 | foreach ($sql as $key => $value) { 88 | if ($key == 'start' || $key == 'set_columns') continue; 89 | $query .= $value . ' '; 90 | } 91 | return trim($query); 92 | } 93 | 94 | public static function delete(array $sql) 95 | { 96 | $query = ''; 97 | if (isset($sql['start'])) { 98 | $query .= $sql['start'] . ' '; 99 | } 100 | if (isset($sql['drop'])) { 101 | $query = $sql['drop'] . ' '; 102 | return trim($query); 103 | } 104 | foreach ($sql as $key => $value) { 105 | if ($key == 'start') continue; 106 | $query .= $value . ' '; 107 | } 108 | return trim($query); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Statement/Alter.php: -------------------------------------------------------------------------------- 1 | db = $db; 22 | $this->table_name = $table_name; 23 | 24 | $this->start(); 25 | } 26 | 27 | public function add(string $column): self 28 | { 29 | $this->column_name = $column; 30 | if ($this->hasColumn($column)) { 31 | $this->column_exists = true; 32 | } 33 | 34 | $this->sql[$column] = "ADD $column"; 35 | return $this; 36 | } 37 | 38 | public function modify(string $old_column, string $new_column = ''): self 39 | { 40 | $this->column_name = $new_column; 41 | $this->sql[$new_column] = trim("MODIFY COLUMN $old_column $new_column"); 42 | return $this; 43 | } 44 | 45 | public function drop(string $column): self 46 | { 47 | $this->sql[$column] = "DROP COLUMN $column"; 48 | return $this; 49 | } 50 | 51 | public function int(int $size = 255): self 52 | { 53 | $this->sql[$this->column_name] .= " INT($size)"; 54 | return $this; 55 | } 56 | 57 | public function bigInt(int $size = 255): self 58 | { 59 | $this->sql[$this->column_name] .= " BIGINT($size)"; 60 | return $this; 61 | } 62 | 63 | public function double(int $size = 255, int $d = 2): self 64 | { 65 | $this->sql[$this->column_name] .= " DOUBLE($size, $d)"; 66 | return $this; 67 | } 68 | 69 | public function boolean(): self 70 | { 71 | $this->sql[$this->column_name] .= " BOOLEAN"; 72 | return $this; 73 | } 74 | 75 | public function string(int $size = 255): self 76 | { 77 | $this->sql[$this->column_name] .= " VARCHAR($size)"; 78 | return $this; 79 | } 80 | 81 | public function text(int $size = 10000): self 82 | { 83 | $this->sql[$this->column_name] .= " TEXT($size)"; 84 | return $this; 85 | } 86 | 87 | public function longText(int $size): self 88 | { 89 | $this->sql[$this->column_name] .= " LONGTEXT($size)"; 90 | return $this; 91 | } 92 | 93 | public function json(): self 94 | { 95 | $this->sql[$this->column_name] .= " JSON"; 96 | return $this; 97 | } 98 | 99 | public function required(): self 100 | { 101 | $this->sql[$this->column_name] .= " NOT NULL"; 102 | return $this; 103 | } 104 | 105 | public function primary($columns = []): self 106 | { 107 | if (! empty($columns)) { 108 | $this->sql['primary'] = "PRIMARY KEY (" . implode(',', $columns) . ")"; 109 | return $this; 110 | } 111 | $this->sql[$this->column_name] .= " PRIMARY KEY"; 112 | return $this; 113 | } 114 | 115 | public function index(array $columns): self 116 | { 117 | $this->sql['index'] = "INDEX (" . implode(',', $columns) . ")"; 118 | return $this; 119 | } 120 | 121 | public function date(): self 122 | { 123 | $this->sql[$this->column_name] .= " DATE"; 124 | return $this; 125 | } 126 | 127 | public function dateTime(): self 128 | { 129 | $this->sql[$this->column_name] .= " DATETIME"; 130 | return $this; 131 | } 132 | 133 | public function timestamp($default = null, $on_update = null): self 134 | { 135 | $this->sql[$this->column_name] .= " TIMESTAMP"; 136 | 137 | if ($default === 'now') { 138 | $this->sql[$this->column_name] .= " DEFAULT CURRENT_TIMESTAMP"; 139 | } elseif ($default && $default !== 'now') { 140 | $this->sql[$this->column_name] .= " DEFAULT " . $default; 141 | } 142 | 143 | if ($on_update === 'current') { 144 | $this->sql[$this->column_name] .= " ON UPDATE CURRENT_TIMESTAMP"; 145 | } elseif ($on_update && $on_update !== 'current') { 146 | $this->sql[$this->column_name] .= " ON UPDATE " . $on_update; 147 | } 148 | 149 | return $this; 150 | } 151 | 152 | public function unsigned(): self 153 | { 154 | $this->sql[$this->column_name] .= " UNSIGNED"; 155 | return $this; 156 | } 157 | 158 | public function autoIncrement(): self 159 | { 160 | $this->sql[$this->column_name] .= " AUTO_INCREMENT"; 161 | return $this; 162 | } 163 | 164 | public function default($value): self 165 | { 166 | $val = is_string($value) ? "'$value'" : $value; 167 | $this->sql[$this->column_name] .= " DEFAULT $val"; 168 | return $this; 169 | } 170 | 171 | public function nullable(): self 172 | { 173 | return $this->default('NULL'); 174 | } 175 | 176 | public function foreignKey(string $column, string $reference_table, string $reference_column): self 177 | { 178 | $table_name = Utilities::get_db_configs()->prefix . $reference_table; 179 | $this->sql['foreignKey'] = "ADD FOREIGN KEY (`$column`) REFERENCES $table_name (`$reference_column`)" ; 180 | return $this; 181 | } 182 | 183 | public function onDelete(string $action): self 184 | { 185 | $this->sql['onDelete'] = "ON DELETE $action"; 186 | return $this; 187 | } 188 | 189 | public function enum(array $allowed): self 190 | { 191 | $list = ''; 192 | foreach ($allowed as $value) { 193 | if (gettype($value) === 'string') { 194 | $list .= "'$value', "; 195 | } else { 196 | $list .= $value . ", "; 197 | } 198 | } 199 | 200 | $list = substr(trim($list), 0, -1); 201 | 202 | $this->sql[$this->column_name] .= " ENUM(" . $list . ")"; 203 | return $this; 204 | } 205 | 206 | protected function start() 207 | { 208 | $table_name = $this->get_table_name(); 209 | $this->sql['start'] = "ALTER TABLE $table_name"; 210 | } 211 | 212 | private function get_table_name() 213 | { 214 | return $this->getTablePrefix()->prefix . $this->table_name; 215 | } 216 | 217 | private function getTablePrefix() 218 | { 219 | if (empty(QueryFactory::getConfig())) { 220 | global $wpdb; 221 | return $wpdb; 222 | } 223 | return QueryFactory::getConfig(); 224 | } 225 | 226 | private function hasColumn($column) 227 | { 228 | $columns = []; 229 | $driver = $this->db; 230 | $table_name = Utilities::get_db_configs()->prefix .$this->table_name; 231 | 232 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 233 | $columns = $driver->get_results("DESCRIBE `$table_name`", ARRAY_N); 234 | } else { 235 | $columns = $driver->query("DESCRIBE `$table_name`")->fetchAll(\PDO::FETCH_COLUMN); 236 | } 237 | 238 | foreach ($columns as $value) { 239 | if (is_array($value) && $value[0] === $column) { 240 | return $column; 241 | } 242 | if (! is_array($value) && $value === $column) { 243 | return $column; 244 | } 245 | } 246 | 247 | return false; 248 | } 249 | 250 | // get only sql query string 251 | public function getSql() 252 | { 253 | $this->start(); 254 | $query = [ 255 | 'query' => SqlGenerator::alter($this->sql), 256 | ]; 257 | return $query; 258 | } 259 | 260 | private function driver_execute($sql) 261 | { 262 | $driver = $this->db; 263 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 264 | return $driver->query($sql); 265 | } 266 | 267 | try { 268 | return $driver->exec($sql); 269 | } catch (\PDOException $exception) { 270 | Utilities::throughException($exception); 271 | } 272 | } 273 | 274 | public function execute() 275 | { 276 | $this->start(); 277 | $query = SqlGenerator::alter($this->sql); 278 | 279 | if ($this->column_exists) { 280 | return; 281 | } 282 | 283 | $this->driver_execute($query); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /src/Statement/Create.php: -------------------------------------------------------------------------------- 1 | db = $db; 21 | $this->table_name = $table_name; 22 | 23 | $this->start(); 24 | $this->sql['table_name'] = $this->get_table_name(); 25 | } 26 | 27 | public function column(string $column_name): self 28 | { 29 | $this->column_name = $column_name; 30 | $this->sql['columns'][$column_name] = []; 31 | return $this; 32 | } 33 | 34 | public function int(int $size = 255): self 35 | { 36 | $this->sql['columns'][$this->column_name]['int'] = "INT($size)"; 37 | return $this; 38 | } 39 | 40 | public function bigInt(int $size = 255): self 41 | { 42 | $this->sql['columns'][$this->column_name]['bigInt'] = "BIGINT($size)"; 43 | return $this; 44 | } 45 | 46 | public function double(int $size = 255, int $d = 2): self 47 | { 48 | $this->sql['columns'][$this->column_name]['double'] = "DOUBLE($size, $d)"; 49 | return $this; 50 | } 51 | 52 | public function boolean(): self 53 | { 54 | $this->sql['columns'][$this->column_name]['boolean'] = "BOOLEAN"; 55 | return $this; 56 | } 57 | 58 | public function string(int $size = 255): self 59 | { 60 | $this->sql['columns'][$this->column_name]['string'] = "VARCHAR($size)"; 61 | return $this; 62 | } 63 | 64 | public function text(int $size = 10000): self 65 | { 66 | $this->sql['columns'][$this->column_name]['text'] = "TEXT($size)"; 67 | return $this; 68 | } 69 | 70 | public function longText(): self 71 | { 72 | $this->sql['columns'][$this->column_name]['longText'] = "LONGTEXT"; 73 | return $this; 74 | } 75 | 76 | public function json(): self 77 | { 78 | $this->sql['columns'][$this->column_name]['json'] = "JSON"; 79 | return $this; 80 | } 81 | 82 | public function required(): self 83 | { 84 | $this->sql['columns'][$this->column_name]['required'] = "NOT NULL"; 85 | return $this; 86 | } 87 | 88 | public function nullable(): self 89 | { 90 | return $this->default('NULL'); 91 | } 92 | 93 | public function primary($columns = []): self 94 | { 95 | if (! empty($columns)) { 96 | $this->sql['primary'] = "PRIMARY KEY (" . implode(',', $columns) . ")"; 97 | return $this; 98 | } 99 | $this->sql['columns'][$this->column_name]['primary'] = "PRIMARY KEY"; 100 | return $this; 101 | } 102 | 103 | public function index(array $columns): self 104 | { 105 | $this->sql['index'] = "INDEX (" . implode(',', $columns) . ")"; 106 | return $this; 107 | } 108 | 109 | public function date(): self 110 | { 111 | $this->sql['columns'][$this->column_name]['date'] = "DATE"; 112 | return $this; 113 | } 114 | 115 | public function dateTime(): self 116 | { 117 | $this->sql['columns'][$this->column_name]['dateTime'] = "DATETIME"; 118 | return $this; 119 | } 120 | 121 | public function timestamp($default = null, $on_update = null): self 122 | { 123 | $this->sql['columns'][$this->column_name]['timestamp'] = "TIMESTAMP"; 124 | 125 | if ($default === 'now') { 126 | $this->sql['columns'][$this->column_name]['default'] = "DEFAULT CURRENT_TIMESTAMP"; 127 | } elseif ($default && $default !== 'now') { 128 | $this->sql['columns'][$this->column_name]['default'] = "DEFAULT " . $default; 129 | } 130 | 131 | if ($on_update === 'current') { 132 | $this->sql['columns'][$this->column_name]['onUpdate'] = "ON UPDATE CURRENT_TIMESTAMP"; 133 | } elseif ($on_update && $on_update !== 'current') { 134 | $this->sql['columns'][$this->column_name]['onUpdate'] = "ON UPDATE " . $on_update; 135 | } 136 | 137 | return $this; 138 | } 139 | 140 | public function unsigned(): self 141 | { 142 | $this->sql['columns'][$this->column_name]['unsigned'] = "UNSIGNED"; 143 | return $this; 144 | } 145 | 146 | public function autoIncrement(): self 147 | { 148 | $this->sql['columns'][$this->column_name]['autoIncrement'] = "AUTO_INCREMENT"; 149 | return $this; 150 | } 151 | 152 | public function default($value): self 153 | { 154 | $val = is_string($value) ? "'$value'" : $value; 155 | $this->sql['columns'][$this->column_name]['default'] = "DEFAULT $val"; 156 | return $this; 157 | } 158 | 159 | public function foreignKey(string $column, string $ref_table_column, string $on_delete = null): self 160 | { 161 | $ref_table_column = explode('.', $ref_table_column); 162 | $table_name = Utilities::get_db_configs()->prefix . $ref_table_column[0]; 163 | $this->sql['foreignKey'] = "FOREIGN KEY ($column) REFERENCES $table_name ($ref_table_column[1])"; 164 | 165 | if ($on_delete) { 166 | $this->sql['foreignKey'] .= " ON DELETE " . strtoupper($on_delete); 167 | } 168 | return $this; 169 | } 170 | 171 | public function onDelete(string $action): self 172 | { 173 | $this->sql['onDelete'] = "ON DELETE " . strtoupper($action); 174 | return $this; 175 | } 176 | 177 | public function enum(array $allowed): self 178 | { 179 | $list = ''; 180 | foreach ($allowed as $value) { 181 | if (gettype($value) === 'string') { 182 | $list .= "'$value', "; 183 | } else { 184 | $list .= $value . ", "; 185 | } 186 | } 187 | 188 | $list = substr(trim($list), 0, -1); 189 | 190 | $this->sql['columns'][$this->column_name]['enum'] = "ENUM(" . $list . ")"; 191 | return $this; 192 | } 193 | 194 | protected function start() 195 | { 196 | $this->sql['start'] = 'CREATE TABLE IF NOT EXISTS'; 197 | } 198 | 199 | protected function get_table_name() 200 | { 201 | return Utilities::get_db_configs()->prefix . $this->table_name; 202 | } 203 | 204 | // get only sql query string 205 | public function getSql() 206 | { 207 | $this->start(); 208 | $query = [ 209 | 'query' => SqlGenerator::create($this->sql), 210 | ]; 211 | return $query; 212 | } 213 | 214 | private function driver_execute($sql) 215 | { 216 | $driver = $this->db; 217 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 218 | return $driver->query($sql); 219 | } 220 | 221 | try { 222 | return $driver->exec($sql); 223 | } catch (\PDOException $exception) { 224 | Utilities::throughException($exception); 225 | } 226 | } 227 | 228 | public function execute() 229 | { 230 | $this->start(); 231 | $query = SqlGenerator::create($this->sql); 232 | 233 | $this->driver_execute($query); 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /src/Statement/Delete.php: -------------------------------------------------------------------------------- 1 | db = $db; 20 | $this->table_name = Utilities::get_db_configs()->prefix . $table_name; 21 | } 22 | 23 | protected function start() 24 | { 25 | $this->sql['start'] = 'DELETE FROM ' . $this->table_name; 26 | } 27 | 28 | public function where($column, string $operator = null, string $value = null): self 29 | { 30 | if ( is_callable( $column ) ) { 31 | call_user_func( $column, $this ); 32 | return $this; 33 | } 34 | $this->sql['where'] = 'WHERE ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 35 | $this->params[] = $value; 36 | return $this; 37 | } 38 | 39 | public function andWhere(string $column, string $operator = null, string $value = null): self 40 | { 41 | $this->sql['andWhere'] = 'AND ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 42 | $this->params[] = $value; 43 | return $this; 44 | } 45 | 46 | public function orWhere(string $column, string $operator = null, string $value = null): self 47 | { 48 | $this->sql['orWhere'] = 'OR ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 49 | $this->params[] = $value; 50 | return $this; 51 | } 52 | 53 | public function drop() 54 | { 55 | $this->sql['drop'] = 'DROP TABLE ' . $this->table_name; 56 | return $this; 57 | } 58 | 59 | public function dropIfExists() 60 | { 61 | $this->sql['drop'] = 'DROP TABLE IF EXISTS ' . $this->table_name; 62 | return $this; 63 | } 64 | 65 | private function driver_exicute($sql) 66 | { 67 | $driver = $this->db; 68 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 69 | return $driver->query($driver->prepare($sql, $this->params)); 70 | } 71 | 72 | $data = $driver->prepare($sql); 73 | try { 74 | return $data->execute($this->params); 75 | } catch (\PDOException $exception) { 76 | Utilities::throughException($exception); 77 | } 78 | } 79 | 80 | private function delete_data() 81 | { 82 | $query = SqlGenerator::delete($this->sql); 83 | 84 | return $this->driver_exicute($query); 85 | } 86 | 87 | // get only sql query string 88 | public function getSql() 89 | { 90 | $this->start(); 91 | $query = [ 92 | 'query' => SqlGenerator::delete($this->sql), 93 | 'params' => $this->params, 94 | ]; 95 | return $query; 96 | } 97 | 98 | public function execute() 99 | { 100 | $this->start(); 101 | $this->delete_data(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Statement/Drop.php: -------------------------------------------------------------------------------- 1 | db = $db; 21 | $this->table_name = Utilities::get_db_configs()->prefix . $table_name; 22 | } 23 | 24 | public function drop() 25 | { 26 | $this->sql['drop'] = 'DROP TABLE ' . $this->table_name; 27 | $this->drop_table(); 28 | } 29 | 30 | public function dropIfExists() 31 | { 32 | $this->sql['drop'] = 'DROP TABLE IF EXISTS ' . $this->table_name; 33 | $this->drop_table(); 34 | } 35 | 36 | private function driver_execute($sql) 37 | { 38 | $driver = $this->db; 39 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 40 | return $driver->query($sql); 41 | } 42 | 43 | $data = $driver->prepare($sql); 44 | try { 45 | return $data->execute($this->params); 46 | } catch (\Exception $exception) { 47 | Utilities::throughException($exception); 48 | } 49 | } 50 | 51 | private function drop_table() 52 | { 53 | $query = trim($this->sql['drop']); 54 | 55 | $this->driver_execute($query); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Statement/Insert.php: -------------------------------------------------------------------------------- 1 | db = $db; 21 | $this->data = $data; 22 | $this->table_name = $table_name; 23 | 24 | $this->start(); 25 | $this->sql['table_name'] = $this->get_table_name(); 26 | $this->sql['columns'] = $this->get_columns(); 27 | $this->sql['value_placeholders'] = $this->get_value_placeholders(); 28 | $this->params = $this->get_params(); 29 | 30 | $this->insert_data(); 31 | } 32 | 33 | private function insert_data() 34 | { 35 | $query = SqlGenerator::insert($this->sql); 36 | 37 | $this->driver_execute($query); 38 | } 39 | 40 | private function driver_execute($sql) 41 | { 42 | $driver = $this->db; 43 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 44 | return $driver->query($driver->prepare($sql, $this->params)); 45 | } 46 | 47 | $data = $driver->prepare($sql); 48 | try { 49 | return $data->execute($this->params); 50 | } catch (\Exception $exception) { 51 | Utilities::throughException($exception); 52 | } 53 | } 54 | 55 | private function start() 56 | { 57 | $this->sql['start'] = 'INSERT INTO'; 58 | } 59 | 60 | private function get_table_name() 61 | { 62 | return Utilities::get_db_configs()->prefix . $this->table_name; 63 | } 64 | 65 | private function get_columns() 66 | { 67 | if (empty($this->data)) return; 68 | 69 | $columns = []; 70 | foreach ($this->data[0] as $column => $value) { 71 | $columns[] = $column; 72 | } 73 | return '(' . implode(', ', $columns) . ')'; 74 | } 75 | 76 | private function get_value_placeholders() 77 | { 78 | $placeholders = []; 79 | 80 | if (count($this->data) > 1) { 81 | foreach ($this->data as $row) { 82 | $placeholders[] = '(' . implode(',', array_fill(0, count($row), Utilities::get_placeholder($this->db, $row))) . ')'; 83 | } 84 | } else { 85 | $placeholders[] = '(' . implode(',', array_fill(0, count($this->data[0]), Utilities::get_placeholder($this->db, $this->data))) . ')'; 86 | } 87 | return 'VALUES ' . implode(',', $placeholders); 88 | } 89 | 90 | private function get_params() 91 | { 92 | $params = []; 93 | foreach ($this->data as $value) { 94 | foreach ($value as $val) { 95 | $params[] = $val; 96 | } 97 | } 98 | return $params; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Statement/Select.php: -------------------------------------------------------------------------------- 1 | db = $db; 22 | } 23 | 24 | protected function start() 25 | { 26 | $this->sql['start']['select'] = 'SELECT'; 27 | } 28 | 29 | protected function setStartExpression() 30 | { 31 | $sql = ''; 32 | if (isset($this->sql['start']['select'])) { 33 | $sql .= 'SELECT '; 34 | } 35 | if (isset($this->sql['start']['distinct'])) { 36 | $sql .= 'DISTINCT '; 37 | } 38 | if (isset($this->sql['columns'])) { 39 | $sql .= $this->sql['columns']; 40 | unset($this->sql['columns']); 41 | } 42 | if (isset($this->sql['start']['count'])) { 43 | $sql .= ', ' . $this->sql['start']['count']; 44 | } 45 | return $this->sql['start'] = $sql; 46 | } 47 | 48 | public function distinct(): self 49 | { 50 | $this->sql['start']['distinct'] = 'DISTINCT'; 51 | return $this; 52 | } 53 | 54 | public function columns(...$columns): self 55 | { 56 | $this->sql['columns'] = implode(', ', $columns); 57 | return $this; 58 | } 59 | 60 | public function alias(string $name): self 61 | { 62 | $this->sql['alias'] = 'AS ' . $name; 63 | return $this; 64 | } 65 | 66 | public function from(string $table_name): self 67 | { 68 | $this->sql['table_name'] = 'FROM ' . Utilities::get_db_configs()->prefix . $table_name; 69 | return $this; 70 | } 71 | 72 | public function where($column, ?string $operator = null, $value = null): self 73 | { 74 | if ( is_callable( $column ) ) { 75 | call_user_func( $column, $this ); 76 | return $this; 77 | } 78 | $this->sql['where'] = 'WHERE ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 79 | $this->params[] = $value; 80 | return $this; 81 | } 82 | 83 | public function andWhere(string $column, string $operator = null, $value = null): self 84 | { 85 | $this->sql['andWhere'] = 'AND ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 86 | $this->params[] = $value; 87 | return $this; 88 | } 89 | 90 | public function orWhere(string $column, string $operator = null, $value = null): self 91 | { 92 | $this->sql['orWhere'] = 'OR ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 93 | $this->params[] = $value; 94 | return $this; 95 | } 96 | 97 | public function whereNot(string $column, string $operator = null, $value = null): self 98 | { 99 | $this->sql['whereNot'] = 'WHERE NOT ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 100 | $this->params[] = $value; 101 | return $this; 102 | } 103 | 104 | public function andNot(string $column, string $operator = null, $value = null): self 105 | { 106 | $this->sql['andNot'] = 'AND NOT ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 107 | $this->params[] = $value; 108 | return $this; 109 | } 110 | 111 | public function whereIn(string $column, ...$value): self 112 | { 113 | $this->sql['whereIn'] = 'WHERE ' . $column . ' IN (' . implode( ', ', $value ) . ')'; 114 | return $this; 115 | } 116 | 117 | public function orderBy($column, string $sort_type): self 118 | { 119 | $col = is_array( $column ) ? implode( ', ', $column ) : $column; 120 | $this->sql['orderBy'] = 'ORDER BY ' . $col . ' ' . $sort_type; 121 | return $this; 122 | } 123 | 124 | public function groupBy($column): self 125 | { 126 | $col = is_array( $column ) ? implode( ', ', $column ) : $column; 127 | $this->sql['groupBy'] = 'GROUP BY ' . $col; 128 | return $this; 129 | } 130 | 131 | public function limit(int $count): self 132 | { 133 | $this->sql['limit'] = 'LIMIT ' . $count; 134 | return $this; 135 | } 136 | 137 | public function offset(int $count): self 138 | { 139 | $this->sql['offset'] = 'OFFSET ' . $count; 140 | return $this; 141 | } 142 | 143 | public function count(string $column, string $alias = ''): self 144 | { 145 | $alias = $alias ? ' ' . $alias : ''; 146 | $this->sql['start']['count'] = 'COUNT(' . $column . ')' . $alias; 147 | return $this; 148 | } 149 | 150 | private function setJoin($table_name, string $col1 = null, string $col2 = null, string $joinType = 'JOIN'): self 151 | { 152 | $table_names = []; 153 | if (is_array($table_name)) { 154 | foreach ($table_name as $table) { 155 | $table_names[] = Utilities::get_db_configs()->prefix . $table; 156 | } 157 | } else { 158 | $table_names[] = Utilities::get_db_configs()->prefix . $table_name; 159 | } 160 | 161 | $table = ''; 162 | if (count($table_names) > 1) { 163 | $table = '(' . implode(',', $table_names) . ')'; 164 | } else { 165 | $table = $table_names[0]; 166 | } 167 | 168 | $this->sql['join'] = $joinType . ' ' . $table; 169 | if ($col1 && $col2) { 170 | $this->sql['join'] .= ' ON ' . $col1 . ' = ' . $col2; 171 | } 172 | return $this; 173 | } 174 | 175 | public function join($table_name, string $col1 = null, string $col2 = null): self 176 | { 177 | return $this->setJoin($table_name, $col1, $col2); 178 | } 179 | 180 | public function innerJoin($table_name, string $col1 = null, string $col2 = null): self 181 | { 182 | return $this->setJoin($table_name, $col1, $col2, 'INNER JOIN'); 183 | } 184 | 185 | public function leftJoin($table_name, string $col1 = null, string $col2 = null): self 186 | { 187 | return $this->setJoin($table_name, $col1, $col2, 'LEFT JOIN'); 188 | } 189 | 190 | public function rightJoin($table_name, string $col1 = null, string $col2 = null): self 191 | { 192 | return $this->setJoin($table_name, $col1, $col2, 'RIGHT JOIN'); 193 | } 194 | 195 | public function raw(string $sql): self 196 | { 197 | $this->sql['raw_'. $this->row_count++] = $sql; 198 | return $this; 199 | } 200 | 201 | protected function setAlias() 202 | { 203 | if (! isset($this->sql['alias'])) return; 204 | 205 | $this->sql['table_name'] .= ' ' . $this->sql['alias']; 206 | unset($this->sql['alias']); 207 | } 208 | 209 | private function fetch($query, array $args = []) 210 | { 211 | try { 212 | return $this->driver_execute($query, $args); 213 | } catch (\Exception $exception) { 214 | Utilities::throughException($exception); 215 | } 216 | } 217 | 218 | private function driver_execute($sql, $placeholders) 219 | { 220 | $driver = $this->db; 221 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 222 | if (empty($placeholders)) { 223 | return $driver->get_results($sql, ARRAY_A); 224 | } 225 | 226 | return $driver->get_results( 227 | $driver->prepare($sql, $placeholders), 228 | ARRAY_A 229 | ); 230 | } 231 | 232 | $data = $driver->prepare($sql); 233 | $data->execute($placeholders); 234 | return $data->fetchAll(\PDO::FETCH_ASSOC); 235 | } 236 | 237 | // get only sql query string 238 | public function getSql() 239 | { 240 | $this->start(); 241 | $this->setAlias(); 242 | $this->setStartExpression(); 243 | $query = [ 244 | 'query' => SqlGenerator::select($this->sql), 245 | 'params' => $this->params 246 | ]; 247 | return $query; 248 | } 249 | 250 | // get data from database 251 | public function get() 252 | { 253 | $this->start(); 254 | $this->setAlias(); 255 | $this->setStartExpression(); 256 | $query = SqlGenerator::select($this->sql); 257 | 258 | $data = $this->fetch($query, $this->params); 259 | return $data; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /src/Statement/Update.php: -------------------------------------------------------------------------------- 1 | db = $db; 21 | 22 | $this->data = $data; 23 | $this->table_name = $this->get_table_prefix()->prefix . $table_name; 24 | $this->sql['set_columns'] = $this->set_columns(); 25 | } 26 | 27 | private function driver_execute($sql) 28 | { 29 | $driver = $this->db; 30 | if (class_exists('wpdb') && $driver instanceof \wpdb) { 31 | return $driver->query($driver->prepare($sql, $this->params)); 32 | } 33 | 34 | $data = $driver->prepare($sql); 35 | try { 36 | return $data->execute($this->params); 37 | } catch (\Exception $exception) { 38 | Utilities::throughException($exception); 39 | } 40 | } 41 | 42 | private function update_data() 43 | { 44 | $query = SqlGenerator::update($this->sql); 45 | 46 | $this->driver_execute($query); 47 | } 48 | 49 | public function execute() 50 | { 51 | $this->start(); 52 | $this->update_data(); 53 | } 54 | 55 | // get only sql query string 56 | public function getSql() 57 | { 58 | $this->start(); 59 | $query = [ 60 | 'query' => SqlGenerator::update($this->sql), 61 | 'params' => $this->params, 62 | ]; 63 | return $query; 64 | } 65 | 66 | private function get_table_prefix() 67 | { 68 | if (empty(QueryFactory::getConfig())) { 69 | global $wpdb; 70 | return $wpdb; 71 | } 72 | return QueryFactory::getConfig(); 73 | } 74 | 75 | protected function start() 76 | { 77 | $this->sql['start'] = 'UPDATE ' . $this->table_name; 78 | } 79 | 80 | protected function set_columns() 81 | { 82 | if (empty($this->data)) return; 83 | 84 | $columns = []; 85 | foreach ($this->data as $column => $value) { 86 | $columns[] = $column . '=' . Utilities::get_placeholder($this->db, $value); 87 | $this->params[] = $value; 88 | } 89 | return 'SET ' . implode(', ', $columns); 90 | } 91 | 92 | public function where($column, string $operator = null, $value = null): self 93 | { 94 | if ( is_callable( $column ) ) { 95 | call_user_func( $column, $this ); 96 | return $this; 97 | } 98 | $this->sql['where'] = 'WHERE ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 99 | $this->params[] = $value; 100 | return $this; 101 | } 102 | 103 | public function andWhere(string $column, string $operator = null, $value = null): self 104 | { 105 | $this->sql['andWhere'] = 'AND ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 106 | $this->params[] = $value; 107 | return $this; 108 | } 109 | 110 | public function orWhere(string $column, string $operator = null, $value = null): self 111 | { 112 | $this->sql['orWhere'] = 'OR ' . $column . ' ' . $operator . ' ' . Utilities::get_placeholder($this->db, $value); 113 | $this->params[] = $value; 114 | return $this; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Utilities.php: -------------------------------------------------------------------------------- 1 | "); 10 | $error_msg = sprintf( 11 | "%s %s", 12 | 'ERROR Message:', 13 | $exception->getMessage() 14 | ); 15 | printf($error_msg); 16 | printf("
In %s %s

", $exception->getFile(), $exception->getLine()); 17 | printf( 18 | "
Trace:
%s

", 19 | print_r($exception->getTrace(), true) 20 | ); 21 | printf(""); 22 | 23 | throw new \Exception($exception->getMessage()); 24 | } 25 | 26 | public static function get_placeholder($db, $value) 27 | { 28 | if ($db instanceof \wpdb) { 29 | if (is_array($value)) return '%s'; 30 | if (is_string($value)) return '%s'; 31 | if (is_integer($value)) return '%d'; 32 | if (is_float($value)) return '%f'; 33 | } 34 | return "?"; 35 | } 36 | 37 | public static function get_db_configs() 38 | { 39 | if (empty(QueryFactory::getConfig())) { 40 | global $wpdb; 41 | return $wpdb; 42 | } 43 | return QueryFactory::getConfig(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/CreateTest.php: -------------------------------------------------------------------------------- 1 | column('ID')->bigInt()->unsigned()->autoIncrement()->primary()->required() 16 | ->column('name')->string(255)->required() 17 | ->column('email')->string(255)->default('nil') 18 | ->index(['ID']) 19 | ->getSql(); 20 | 21 | $this->assertSame($sql, $query); 22 | } 23 | 24 | public function test_nullable() 25 | { 26 | $sql = "CREATE TABLE IF NOT EXISTS wp_test (secondary_email VARCHAR(255) DEFAULT 'NULL')"; 27 | 28 | $query = CreateApi::create('test') 29 | ->column('secondary_email')->string(255)->default('NULL') 30 | ->getSql(); 31 | 32 | $this->assertSame($sql, $query); 33 | 34 | $query = CreateApi::create('test') 35 | ->column('secondary_email')->string(255)->nullable() 36 | ->getSql(); 37 | 38 | $this->assertSame($sql, $query); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/SelectTest.php: -------------------------------------------------------------------------------- 1 | from('posts') 16 | ->getSql(); 17 | 18 | $this->assertSame($sql, $query); 19 | } 20 | 21 | public function testDistinct() 22 | { 23 | $sql = 'SELECT DISTINCT * FROM wp_posts'; 24 | $query = 25 | SelectApi::select('*') 26 | ->distinct() 27 | ->from('posts') 28 | ->getSql(); 29 | 30 | $this->assertSame($sql, $query); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Statement/CreateApi.php: -------------------------------------------------------------------------------- 1 | db = $db; 14 | $this->table_name = $table_name; 15 | $this->wpdb_object = new \stdClass; 16 | $this->wpdb_object->prefix = 'wp_'; 17 | 18 | $this->start(); 19 | $this->sql['table_name'] = $this->get_table_name(); 20 | } 21 | 22 | public static function create($table_name) 23 | { 24 | $driver = new \stdClass; 25 | $create = new self($driver, $table_name); 26 | return $create; 27 | } 28 | 29 | public function getSql() 30 | { 31 | $this->start(); 32 | $query = SqlGenerator::create($this->sql); 33 | 34 | return $query; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/Statement/SelectApi.php: -------------------------------------------------------------------------------- 1 | db = $db; 14 | $this->wpdb_object = new \stdClass; 15 | $this->wpdb_object->prefix = 'wp_'; 16 | } 17 | 18 | public static function select($colmns) 19 | { 20 | $driver = new \stdClass; 21 | $select = new self($driver); 22 | $select->columns($colmns); 23 | return $select; 24 | } 25 | 26 | public function getSql() 27 | { 28 | $this->start(); 29 | $this->setAlias(); 30 | $this->setStartExpression(); 31 | $query = SqlGenerator::select($this->sql); 32 | 33 | return $query; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/Statement/UpdateApi.php: -------------------------------------------------------------------------------- 1 | db = $db; 13 | $this->data = $data; 14 | $this->wpdb_object = new \stdClass; 15 | 16 | $this->table_name = 'wp_' . $table_name; 17 | $this->sql['set_columns'] = $this->set_columns(); 18 | } 19 | 20 | public static function update(string $table_name, array $data) 21 | { 22 | $driver = new \stdClass; 23 | $update = new self($driver, $table_name, $data); 24 | return $update; 25 | } 26 | 27 | public function getSql() 28 | { 29 | $this->start(); 30 | $query = SqlGenerator::update($this->sql); 31 | 32 | return $query; 33 | } 34 | 35 | public function getParams() 36 | { 37 | return $this->params; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/UpdateTest.php: -------------------------------------------------------------------------------- 1 | 'Keramot UL', 16 | 'email' => 'keramotul.islam@gmail.com' 17 | ]) 18 | ->getSql(); 19 | 20 | $this->assertEquals($sql, $query); 21 | } 22 | 23 | public function testWhere() 24 | { 25 | $sql = 'UPDATE wp_querybuilders SET name=?, email=? WHERE ID = ?'; 26 | $query = 27 | UpdateApi::update('querybuilders', [ 28 | 'name' => 'Keramot UL', 29 | 'email' => 'keramotul.islam@gmail.com' 30 | ]) 31 | ->where('ID', '=', 1) 32 | ->getSql(); 33 | 34 | $this->assertEquals($sql, $query); 35 | } 36 | 37 | public function testParams() 38 | { 39 | $params = ['Keramot UL', 'keramotul.islam@gmail.com', 1]; 40 | $query = 41 | UpdateApi::update('querybuilders', [ 42 | 'name' => 'Keramot UL', 43 | 'email' => 'keramotul.islam@gmail.com' 44 | ]) 45 | ->where('ID', '=', 1) 46 | ->getParams(); 47 | 48 | $this->assertEquals($params, $query); 49 | } 50 | } 51 | --------------------------------------------------------------------------------