├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── install_mssql.sh └── workflows │ ├── ezsql-linux.yml │ ├── ezsql-macos.yml │ └── ezsql-windows.yml ├── CHANGELOG.md ├── CONTRIBUTORS.md ├── LICENSE ├── README.md ├── WIKI.md ├── _config.yml ├── cacert.pem ├── composer.json ├── lib ├── Config.php ├── ConfigAbstract.php ├── ConfigInterface.php ├── Constants.php ├── DInjector.php ├── Database.php ├── Database │ ├── ez_mysqli.php │ ├── ez_pdo.php │ ├── ez_pgsql.php │ ├── ez_sqlite3.php │ └── ez_sqlsrv.php ├── DatabaseInterface.php ├── Db.php ├── Exception │ ├── ContainerException.php │ └── NotFoundException.php ├── ezFunctions.php ├── ezQuery.php ├── ezQueryInterface.php ├── ezResultset.php ├── ezSchema.php ├── ezsqlModel.php └── ezsqlModelInterface.php ├── openssl.cnf └── unsupported ├── .travis.yml ├── appveyor.yml ├── ez_sql_loader.php ├── lib ├── ez_sql_cubrid.php ├── ez_sql_oracle8_9.php └── ez_sql_oracleTNS.php └── tests ├── cubrid └── ezSQL_cubridTest.php └── oracle8_9 ├── ezSQL_oracle8_9Test.php └── ezSQL_oracleTNSTest_.php /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: error-bug, warning-bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | > *Warning*: Failing to provide necessary information may cause the issue to be closed without consideration 20 | 21 | **Environment (please complete the following information):** 22 | - EZSQL Version : 23 | - PHP Version: 24 | - SQL Driver:[ mysql, pgsql, sqlserver, sqlite3] 25 | 26 | **PHP code snippet used** 27 | 28 | ```php 29 | rows_affected (thx Pere Pasqual) 41 | 42 | 2.14 - Added sybase connector by Muhammad Iyas 43 | 44 | 2.13 - Support for transactions. See: http://stackoverflow.com/questions/8754215/ezsql-with-multiple-queries/8781798 45 | 46 | 2.12 - Added $db->get_set() - Creates a SET nvp sql string from an associative array (and escapes all values) 47 | 48 | 2.11 - Fixed $db->insert_id in postgres version 49 | 50 | 2.10 - Added isset($this->dbh) check to oracle version 51 | 52 | 2.09 - Fixed issues with mysql_real_escape_string not working if no connection 53 | (Thanks to Nicolas Vannier) 54 | 55 | 2.08 - Re-added timer functions that seemed to have disappeared 56 | 57 | 2.07 - Used mysql_real_escape_string instead of mysql_escape_string 58 | 59 | 2.02 - Please note, this change log is no longer being used 60 | please see change_log.htm for changes later than 61 | 2.02 62 | 63 | 2.01 - Added Disk Caching & Multiple DB connection support 64 | 65 | 2.00 - Re-factored **ezsql** for Oracle, mySQL & SQLite 66 | 67 | - DB Object is no longer initialized by default 68 | (makes it easier to use multiple connections) 69 | 70 | - Core **ezsql** functions have been separated from DB 71 | specific functions (makes it easier to add new databases) 72 | 73 | - Errors are being piped through trigger_error 74 | (using standard PHP error logging) 75 | 76 | - Abstracted error messages (enabling future translation) 77 | 78 | - Upgraded $db->query error return functionality 79 | 80 | - Added $db->systdate function to abstract mySQL NOW() 81 | and Oracle SYSDATE 82 | 83 | Note: For other DB Types please use version 1.26 84 | 85 | 1.26 - Update (All) 86 | 87 | - Fixed the pesky regular expression that tests for 88 | an insert/update etc. Now it works even for the most 89 | weirdly formatted queries! (thx dille) 90 | 91 | 1.25 - Update (mySQL/Oracle) 92 | 93 | - Optimise $db->query function in both mySQL and Oracle versions. 94 | Now the return value is working 'as expected' in ALL cases so you 95 | are always safe using: 96 | 97 | if ( $db->query("some query") ) 98 | 99 | No matter if an insert or a select. 100 | 101 | In the case of insert/update the return value is based on the 102 | number of rows affected (used to be insert id which is 103 | not valid for an update) 104 | 105 | In the case of select the return value is based on number of 106 | rows returned. 107 | 108 | Thx Bill Bruggemeyer :) 109 | 110 | 1.24 - Update (Docs) 111 | 112 | - Now includes tutorial for using EZ Results with Smarty 113 | templating engine - thx Steve Warwick 114 | 115 | 1.23 - Update (All PHP versions) 116 | 117 | - Fixed the age old problem of returning false on 118 | successful insert. $db->query()now returns the insert_id 119 | if there was a successful insert or false if not. Sorry 120 | that this took so long to fix! 121 | 122 | Version Affected: mySQL/Porgress/ms-sql/sqlite 123 | 124 | - Added new variable $db->debug_all 125 | 126 | By default it is set to false but if you change it 127 | to true. i.e. 128 | 129 | include_once "ez_sql.php"; 130 | $db->debug_all = true; 131 | 132 | Then it will print out each and every query and all 133 | of the results that your script creates. 134 | 135 | Very useful if you want to follow the entire logic 136 | path of what ALL your queries are doing, but can't 137 | be bothered to put $db->debug() statements all over 138 | the place! 139 | 140 | Update (Postgress SQL Version) 141 | 142 | - Our old friend Tom De Bruyne as updated the postgress 143 | version. 144 | 145 | 1) It now works without throwing errors (also thanks Geert Nijpels) 146 | 147 | 2) It now, in theory, returns $this->insert_id after an insert. 148 | 149 | 150 | 1.22 - Update (All PHP versions) 151 | 152 | - Added new variable $db->num_queries it keeps track 153 | of exactly how many 'real' (not cached) queries were 154 | executed (using **ezsql**) during the lifetime of one script. 155 | Useful for debugging and optimizing. 156 | 157 | - Put a white table behind the vardump output so that 158 | it doesn't get lost on dark websites. 159 | 160 | 1.21 - Update (All Versions) 161 | 162 | - Now 'replace' really does return an insert id.. 163 | (the 1.19 fix did not complete the job. Doh!) 164 | 165 | 1.20 - Update (New Version) 166 | 167 | - C++ SQLite version added. Look at ez_demo.cpp. 168 | (thanks Brennan Falkner) 169 | 170 | 1.19 - Update (All Versions) 171 | 172 | - Fixed bug where any string containing the word 'insert', 173 | 'delete' or 'update' (where those words were not the actual 174 | query) was causing unexpected results (thx Simon Willison). 175 | 176 | The fix was to alter the regular expression to only match 177 | queries containing those words at the beginning of the query 178 | (with optional whitespace allowed before the words) 179 | 180 | i.e. 181 | 182 | THIS: preg_match("/$word /", strtolower($query)) 183 | TO THIS: preg_match("/^\\s*$word /", strtolower($query)) 184 | 185 | - Added new sql word 'replace' to the above match pattern 186 | so that the $db->insert_id would be also be populated 187 | on 'replace' queries (thx Rolf Dahl) 188 | 189 | 1.18 - Update (All Versions) 190 | 191 | - Added new SQLite version (thanks Brennan Falkner) 192 | 193 | - Fixed new bug that was introduced with bug fix 1.14 194 | false was being returned on successful insert update etc. 195 | now it is true 196 | 197 | 1.17 - Update (All Versions) 198 | 199 | - New MS-SQL version added (thanks to Tom De Bruyne) 200 | - Made the donation request 'less annoying' by making it more subtle! 201 | 202 | 1.16 - Update (All Versions) 203 | 204 | - Added new function $db->escape() 205 | Formats a string correctly to stop accidental 206 | mal formed queries under all PHP conditions 207 | 208 | 1.15 - Bug fixes 209 | 210 | - (Postgres) 211 | $this->result = false; was in the wrong place. 212 | Fixed! Thanks (Carlos Camiña García) 213 | 214 | - (all versions) 215 | Pesky get_var was still returning null instead of 0 in 216 | certain cases. Bug fix of !== suggested by Osman 217 | 218 | 1.14 - Bug fixes 219 | 220 | - (all versions) 221 | Added !='' into the conditional return of get_var. 222 | because if the result was the number 0 it was not returning anything 223 | 224 | - (mySQL / Interbase / Postgres) 225 | Added $this->result = false; if insert / update / delete 226 | because it was causing mysql retrieval errors that no one 227 | knew about due to the @ signs. 228 | 229 | 1.13 - Update (All Versions) 230 | 231 | - Swapped 2nd and 3rd argument order. 232 | - From.. get_row(query, int row offset, output type) 233 | - To.... get_row(query, output type, int row offset) 234 | 235 | 1.12 - Update (All Versions) 236 | 237 | - Tweaked the new hide/show error code 238 | - Made sure the $this->show_errors was always initialized 239 | - $db->query() function now returns false if there was an SQL error. 240 | So that you can now do the following when you hide errors. 241 | 242 | if ( $db->query("BAD SYNTAX") ) 243 | { 244 | echo "Bad Query"; 245 | } 246 | 247 | 1.11 - Update (All Versions) 248 | 249 | - added $db->hide_errors(); 250 | - added $db->show_errors(); 251 | - added global array $EZSQL_ERROR; 252 | 253 | 1.10 - Fix (mySQL) 254 | 255 | - Insist that mysql_insert_id(); uses $this->dbh. 256 | 257 | 1.09 - Bug Fix 258 | 259 | - Oracle version had the wrong number of parameters in the 260 | $db = new db(etc,etc,etc,etc) part. 261 | 262 | - Also added var $vardump_called; to all versions. 263 | 264 | 1.08 - Bug Fix 265 | 266 | - Michael fixed the select function in PostgreSQL version. 267 | 268 | 1.07 - Bug Fix 269 | 270 | - Added var $debug_called; to all versions. 271 | 272 | 1.06 - Update 273 | 274 | - Fixed Bug In Oracle Version where an insert was 275 | causing an error with OCIFetch 276 | - New PostgreSQL Version Added by Michael Paesold (mpaesold@gmx.at) 277 | 278 | 1.05 - Bug Fix (mySQL) 279 | 280 | - Removed repeated piece of code. 281 | 282 | 1.04 - Update 283 | 284 | - $db->num_rows - variable added (All Versions) 285 | - $db->rows_affected - variable added ( mySQL / Oracle ) 286 | - New InterBase/FireBase Version Added by LLCedar (llceder@wxs.nl) 287 | 288 | 1.03 - Update (All Versions) 289 | 290 | Enhancements to vardump.. 291 | 292 | - Added display variable type 293 | - If no value display No Value / False 294 | - Added this readme file 295 | 296 | 1.02 - Update (mySQL version) 297 | 298 | - Added $db->insert_id to 299 | 300 | 1.01 - New Version 301 | 302 | - Oracle 8 Version as below 303 | 304 | 1.00 - Initial Release 305 | 306 | Functions.. 307 | 308 | - $db->get_results - get multiple row result set from the database (or previously cached results) 309 | - $db->get_row -- get one row from the database (or previously cached results) 310 | - $db->get_col - get one column from query (or previously cached results) based on column offset 311 | - $db->get_var -- get one variable, from one row, from the database (or previously cached results) 312 | - $db->query -- send a query to the database (and if any results, cache them) 313 | - $db->debug - print last sql query and returned results (if any) 314 | - $db->vardump - print the contents and structure of any variable 315 | - $db->select -- select a new database to work with 316 | - $db->get_col_info - get information about one or all columns such as column name or type 317 | - $db = new db -- Initiate new db object. -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | **ezsql** *Contributors* 2 | ============================================ 3 | 4 | * **[Justin Vincent](http://twitter.com/justinvincent)** 5 | > jv@jvmultimedia.com 6 | * Author: ezsql class - *ez_SQL_core, mySQL, PDO, PostgreSQL, Cubrid, Oracle8_9* 7 | Contact Info : 8 | * Follow me on twitter: 9 | http://twitter.com/justinvincent 10 | * Check out my podcast TechZing where we talk about tech and tech startups: 11 | http://techzinglive.com 12 | 13 | * **[Stefanie Janine Stoelting](https://stefanie-stoelting.de)** 14 | > mail@stefanie-stoelting.de 15 | * Author: 16 | * *ezsql version 3.00* 17 | * *oracleTNS* 18 | * *phpunit tests* 19 | * *RecordSet - for working with query results* 20 | 21 | * **davisjw** 22 | > davisjw@gmail.com 23 | * Author: ezsql class - *Sqlserver* 24 | 25 | * **Silvio Wanka** 26 | * Author: ezsql class - *sqlite3* 27 | 28 | ---- 29 | 30 | ____L. Stubbs____ 31 | 32 | > lstubbs@techno.express 33 | 34 | * Author/Maintainer: 35 | * ezsql version 3 36 | * In Development version *4.0* 37 | * *ezQuery, ezFunctions, ezSchema* 38 | 39 | ---- 40 | 41 | **[Full contributors list.](https://github.com/ezsql/ezsql/contributors)** 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **ezsql** 2 | 3 | [![Windows](https://github.com/ezSQL/ezsql/workflows/Windows/badge.svg)](https://github.com/ezSQL/ezsql/actions?query=workflow%3AWindows) 4 | [![Linux](https://github.com/ezSQL/ezsql/workflows/Linux/badge.svg)](https://github.com/ezSQL/ezsql/actions?query=workflow%3ALinux) 5 | [![macOS](https://github.com/ezSQL/ezsql/workflows/macOS/badge.svg)](https://github.com/ezSQL/ezsql/actions?query=workflow%3AmacOS) 6 | [![codecov](https://codecov.io/gh/ezSQL/ezSQL/branch/master/graph/badge.svg)](https://codecov.io/gh/ezSQL/ezSQL) 7 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/aad1f6aaaaa14f60933e75615da900b8)](https://www.codacy.com/app/techno-express/ezsql?utm_source=github.com&utm_medium=referral&utm_content=ezSQL/ezsql&utm_campaign=Badge_Grade) 8 | [![Maintainability](https://api.codeclimate.com/v1/badges/6f6107f25e9de7bf4272/maintainability)](https://codeclimate.com/github/ezSQL/ezsql/maintainability) 9 | [![Total Downloads](https://poser.pugx.org/ezsql/ezsql/downloads)](https://packagist.org/packages/ezsql/ezsql) 10 | 11 | ***A class to make it very easy to deal with database connections.*** 12 | *An universal interchangeable **CRUD** system.* 13 | 14 | This is [__Version 5__](https://github.com/ezSQL/ezsql/tree/v5) which will break users of **version 4**. 15 | 16 | Mainly by: 17 | 18 | - The use of `namespace` in the `global` functions **ezFunctions.php** file. 19 | Usage of the **global** functions will require the user to begin a `.php` file something like: 20 | 21 | ```php 22 | use function ezsql\functions\where; 23 | // Or 24 | use function ezsql\functions\{ 25 | getInstance, 26 | selecting, 27 | inserting, 28 | }; 29 | ``` 30 | 31 | - Class properties that was accessible by magic methods `get/set`, now PSR 1 camelCase. 32 | - Renamed `select` of `ez_mysqli` to `dbSelect`. 33 | - Renamed class method and behavior of `selecting` to `select`. 34 | - `selecting`, and new `inserting` methods, can be called without table name, only the other necessary parameters: 35 | - The table *name* with *prefix*, can be preset/stored with methods `tableSetup(name, prefix), or setTable(name), setPrefix(append)`, if called without presetting, `false` is returned. 36 | - This **feature** will be added to **all** database *CRUD* access methods , each method name will have an `ing` ending added. 37 | - Removed global functions where `table` name passed in, use functions using preset table names ending with `ing`. 38 | - renamed cleanInput to clean_string 39 | - renamed createCertificate to create_certificate 40 | - added global get_results to return result sets in different formats 41 | 42 | [__Version 4__](https://github.com/ezSQL/ezsql/tree/v4) has many modern programming practices in which will break users of version 3. 43 | 44 | [__Version 3__](https://github.com/ezSQL/ezsql/tree/v3) broke version 2.1.7 in one major way, it required *PHP 5.6*. Which drop mysql extension support, other than that, nothing as far using the library was changed, only additional features. 45 | 46 | This library has an `Database` class, an combination of the [Factory](https://en.wikipedia.org/wiki/Factory_method_pattern) pattern with an [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) container hosting. This library now is following many OOP principles, one in which, the methods properties public access has been removed. This library also following PSR-2, PSR-4, PSR-11 conventions, and mostly PSR-1, that's still an work in progress. 47 | 48 | * More Todo... 49 | 50 | For an full overview see [documentation Wiki](https://github.com/ezSQL/ezsql/wiki/Documentation), which is not completely finish. 51 | 52 | ## Installation 53 | 54 | composer require ezsql/ezsql 55 | 56 | ## Usage 57 | 58 | ```php 59 | require 'vendor/autoload.php'; 60 | 61 | // **** is one of mysqli, pgsql, sqlsrv, sqlite3, or Pdo. 62 | use ezsql\Database; 63 | 64 | $db = Database::initialize('****', [$dsn_path_user, $password, $database, $other_settings], $optional_tag); 65 | 66 | // Is same as: 67 | use ezsql\Config; 68 | use ezsql\Database\ez_****; 69 | 70 | $settings = new Config('****', [$dsn_path_user, $password, $database, $other_settings]); 71 | 72 | $db = new ez_****($settings); 73 | ``` 74 | 75 | This library will assume the developer is using some sort of IDE with intellisense enabled. The comments/doc-block area will hold any missing documentations. For additional examples see __phpunit__ tests, The tests are fully functional integration tests, meaning the are live database tests, no mocks. 76 | 77 | The following has been added since version 2.1.7. 78 | 79 | ___General Methods___ 80 | 81 | to_string($arrays, $separation = ','); 82 | clean($string); 83 | create_cache(string $path = null); 84 | secureSetup(string $key = 'certificate.key', 85 | string $cert = 'certificate.crt', 86 | string $ca = 'cacert.pem', 87 | string $path = '.'._DS 88 | ); 89 | secureReset(); 90 | create_certificate(string $privatekeyFile = certificate.key, 91 | string $certificateFile = certificate.crt, 92 | string $signingFile = certificate.csr, 93 | string $ssl_path = null, array $details = [commonName => localhost] 94 | ); 95 | 96 | ___Shortcut Table Methods___ 97 | 98 | create(string $table = null, ...$schemas);// $schemas requires... column() 99 | column(string $column = null, string $type = null, ...$args); 100 | primary(string $primaryName, ...$primaryKeys); 101 | index(string $indexName, ...$indexKeys); 102 | drop(string $table); 103 | 104 | Example 105 | 106 | ```php 107 | // Creates an database table 108 | create('profile', 109 | // and with database column name, datatype 110 | // data types are global CONSTANTS 111 | // SEQUENCE|AUTO is placeholder tag, to be replaced with the proper SQL drivers auto number sequencer word. 112 | column('id', INTR, 11, AUTO, PRIMARY), // mysqli 113 | column('name', VARCHAR, 50, notNULL), 114 | column('email', CHAR, 25, NULLS), 115 | column('phone', TINYINT) 116 | ); 117 | ``` 118 | 119 | --- 120 | 121 | innerJoin(string $leftTable = null, string $rightTable = null, 122 | string $leftColumn = null, string $rightColumn = null, string $tableAs = null, $condition = EQ); 123 | 124 | leftJoin(string $leftTable = null, string $rightTable = null, 125 | string $leftColumn = null, string $rightColumn = null, string $tableAs = null, $condition = EQ); 126 | 127 | rightJoin(string $leftTable = null, string $rightTable = null, 128 | string $leftColumn = null, string $rightColumn = null, string $tableAs = null, $condition = EQ); 129 | 130 | fullJoin(string $leftTable = null, string $rightTable = null, 131 | string $leftColumn = null, string $rightColumn = null, string $tableAs = null, $condition = EQ); 132 | --- 133 | 134 | ```php 135 | prepareOn(); // When activated will use prepare statements for all shortcut SQL Methods calls. 136 | prepareOff(); // When off shortcut SQL Methods calls will use vendors escape routine instead. This is the default behavior. 137 | ``` 138 | 139 | ### Shortcut SQL Methods 140 | 141 | * `having(...$having);` 142 | * `groupBy($groupBy);` 143 | * `union(string $table = null, $columnFields = '*', ...$conditions);` 144 | * `unionAll(string $table = null, $columnFields = '*', ...$conditions);` 145 | * `orderBy($orderBy, $order);` 146 | * `limit($numberOf, $offset = null)` 147 | * `where( ...$whereConditions);` 148 | * `select(string $table = null, $columnFields = '*', ...$conditions);` 149 | * `create_select(string $newTable, $fromColumns, $oldTable = null, ...$conditions);` 150 | * `select_into(string $newTable, $fromColumns, $oldTable = null, ...$conditions);` 151 | * `update(string $table = null, $keyAndValue, ...$whereConditions);` 152 | * `delete(string $table = null, ...$whereConditions);` 153 | * `replace(string $table = null, $keyAndValue);` 154 | * `insert(string $table = null, $keyAndValue);` 155 | * `create(string $table = null, ...$schemas);` 156 | * `drop(string $table = null);` 157 | * `alter(string $table = null, ...$alteringSchema);` 158 | * `insert_select(string $toTable = null, $toColumns = '*', $fromTable = null, $fromColumns = '*', ...$conditions);` 159 | 160 | ```php 161 | // The variadic ...$whereConditions, and ...$conditions parameters, 162 | // represent the following global functions. 163 | // They are comparison expressions returning an array with the given arguments, 164 | // the last arguments of _AND, _OR, _NOT, _andNOT will combine expressions 165 | eq('column', $value, _AND), // combine next expression 166 | neq('column', $value, _OR), // will combine next expression again 167 | ne('column', $value), // the default is _AND so will combine next expression 168 | lt('column', $value) 169 | lte('column', $value) 170 | gt('column', $value) 171 | gte('column', $value) 172 | isNull('column') 173 | isNotNull('column') 174 | like('column', '_%?') 175 | notLike('column', '_%?') 176 | in('column', ...$value) 177 | notIn('column', ...$value) 178 | between('column', $value, $value2) 179 | notBetween('column', $value, $value2) 180 | // The above should be used within the where( ...$whereConditions) clause 181 | // $value will protected by either using escape or prepare statement 182 | ``` 183 | 184 | ```php 185 | // To allow simple grouping of basic $whereConditions, 186 | // wrap the following around a group of the above comparison 187 | // expressions within the where( ...$whereConditions) clause 188 | grouping( eq(key, value, combiner ), eq(key, value, combiner ) ) 189 | // The above will wrap beginning and end grouping in a where statement 190 | // where required to break down your where clause. 191 | ``` 192 | 193 | ```php 194 | // Note: The usage of this method will require the user/developer to check 195 | // if `query_string` or `param_array` is valid. 196 | // 197 | // This is really an `private` internal method for other shortcut methods, 198 | // it's made public for `class development` usage only. 199 | // 200 | // 201 | // Supply the the whole `query` string, and placing '?' within, with the same number of arguments in an array. 202 | // It will then determine arguments type, execute, and return results. 203 | query_prepared(string $query_string, array $param_array); 204 | // You will need to call this method to get last successful query result. 205 | // It wll return an object array. 206 | queryResult(); 207 | ``` 208 | 209 | #### Example for using prepare statements indirectly, with above shortcut SQL methods 210 | 211 | ```php 212 | // To get all shortcut SQL methods calls to use prepare statements 213 | $db->prepareOn(); // This needs to be called at least once at instance creation 214 | 215 | $values = []; 216 | $values['name'] = $user; 217 | $values['email'] = $address; 218 | $values['phone'] = $number; 219 | $db->insert('profile', $values); 220 | $db->insert('profile', ['name' => 'john john', 'email' => 'john@email', 'phone' => 123456]); 221 | 222 | // returns result set given the table name, column fields, and ...conditions 223 | $result = $db->select('profile', 'phone', eq('email', $email), between('id', 1, $values)); 224 | 225 | foreach ($result as $row) { 226 | echo $row->phone; 227 | } 228 | 229 | $result = $db->select('profile', 'name, email', 230 | // Conditionals can also be called, stacked with other functions like: 231 | // innerJoin(), leftJoin(), rightJoin(), fullJoin() 232 | // as (leftTable, rightTable, leftColumn, rightColumn, tableAs, equal condition), 233 | // where( eq( columns, values, _AND ), like( columns, _d ) ), 234 | // groupBy( columns ), 235 | // having( between( columns, values1, values2 ) ), 236 | // orderBy( columns, desc ), 237 | // limit( numberOfRecords, offset ), 238 | // union(table, columnFields, conditions), 239 | // unionAll(table, columnFields, conditions) 240 | $db->where( eq('phone', $number, _OR), neq('id', 5) ), 241 | // another way: where( array(key, operator, value, combine, combineShifted) ); 242 | // or as strings double spaced: where( "key operator value combine combineShifted" ); 243 | $db->orderBy('name'), 244 | $db->limit(1) 245 | ); 246 | 247 | foreach ($result as $row) { 248 | echo $row->name.' '.$row->email; 249 | } 250 | 251 | // To get results in `JSON` format 252 | $json = get_results(JSON, $db); 253 | ``` 254 | 255 | #### Example for using prepare statements directly, no shortcut SQL methods used 256 | 257 | ```php 258 | $db->query_prepared('INSERT INTO profile( name, email, phone) VALUES( ?, ?, ? );', [$user, $address, $number]); 259 | 260 | $db->query_prepared('SELECT name, email FROM profile WHERE phone = ? OR id != ?', [$number, 5]); 261 | $result = $db->queryResult(); // the last query that has results are stored in `lastResult` protected property 262 | // Or for results in other formats use the global function, will use global database instance if no `$db` supplied 263 | $result = get_results(/* OBJECT|ARRAY_A|ARRAY_N|JSON */, $db); // Defaults to `OBJECT` 264 | 265 | foreach ($result as $row) { 266 | echo $row->name.' '.$row->email; 267 | } 268 | ``` 269 | 270 | Most of shortcut methods have counter **global** _functions_ available. 271 | They can only be access by beginning your `.php` file like: 272 | 273 | ```php 274 | use function ezsql\functions\functionBelow; 275 | // Or as here, a complete list. 276 | use function ezsql\functions\{ 277 | database, 278 | mysqlInstance, 279 | pgsqlInstance, 280 | mssqlInstance, 281 | sqliteInstance, 282 | pdoInstance, 283 | tagInstance, 284 | setInstance, 285 | getInstance, 286 | clearInstance, 287 | get_vendor, 288 | /// 289 | to_string, 290 | clean_string, 291 | is_traversal, 292 | sanitize_path, 293 | create_certificate, 294 | /// 295 | column, 296 | primary, 297 | foreign, 298 | unique, 299 | index, 300 | addColumn, 301 | dropColumn, 302 | changingColumn, 303 | /// 304 | eq, 305 | neq, 306 | ne, 307 | lt, 308 | lte, 309 | gt, 310 | gte, 311 | isNull, 312 | isNotNull, 313 | like, 314 | in, 315 | notLike, 316 | notIn, 317 | between, 318 | notBetween, 319 | /// 320 | where, 321 | grouping, 322 | groupBy, 323 | having, 324 | orderBy, 325 | limit, 326 | innerJoin, 327 | leftJoin, 328 | rightJoin, 329 | fullJoin, 330 | union, 331 | unionAll, 332 | /// 333 | creating, 334 | deleting, 335 | dropping, 336 | replacing, 337 | selecting, 338 | inserting, 339 | altering, 340 | get_results, 341 | table_setup, 342 | set_table, 343 | set_prefix, 344 | select_into, 345 | insert_select, 346 | create_select, 347 | }; 348 | ``` 349 | 350 | For the functions **usage/docs** see [ezFunctions.php](https://github.com/ezSQL/ezsql/blob/v5/lib/ezFunctions.php). 351 | 352 | ## For Authors and **[Contributors](https://github.com/ezSQL/ezsql/blob/master/CONTRIBUTORS.md)** 353 | 354 | ## Contributing 355 | 356 | Contributions are encouraged and welcome; I am always happy to get feedback or pull requests on Github :) Create [Github Issues](https://github.com/ezSQL/ezsql/issues) for bugs and new features and comment on the ones you are interested in. 357 | 358 | ## License 359 | 360 | **ezsql** is open-sourced software licensed originally under (LGPL-3.0), and the addon parts under (MIT). 361 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | - jekyll-relative-links 3 | relative_links: 4 | enabled: true 5 | collections: true 6 | include: 7 | - WIKI.md 8 | - README.md 9 | - CONTRIBUTORS.md 10 | - LICENSE.md 11 | - CODE_OF_CONDUCT.md 12 | - ISSUE_TEMPLATE.md 13 | - PULL_REQUEST_TEMPLATE.md 14 | 15 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ezsql/ezsql", 3 | "description": "Advance database access library. Make interacting with a database ridiculously easy. An universal interchangeable CRUD system.", 4 | "keywords": [ 5 | "crud", 6 | "dba", 7 | "mysql", 8 | "mysqli", 9 | "postgresql", 10 | "mssql", 11 | "sqlsrv", 12 | "sqlserver", 13 | "pdo", 14 | "sqlite", 15 | "sqlite3", 16 | "database", 17 | "abstraction", 18 | "sql" 19 | ], 20 | "license": [ 21 | "LGPL-3.0-or-later", 22 | "MIT" 23 | ], 24 | "authors": [ 25 | { 26 | "name": "Justin Vincent", 27 | "email": "webmaster@justinvincent.com" 28 | }, 29 | { 30 | "name": "Stefanie Janine Stoelting", 31 | "email": "mail@stefanie-stoelting.de" 32 | }, 33 | { 34 | "name": "l. stubbs", 35 | "email": "lstubbs@techno.express" 36 | } 37 | ], 38 | "support": { 39 | "issues": "https://github.com/ezSQL/ezSQL/issues" 40 | }, 41 | "require": { 42 | "php": ">7.1", 43 | "psr/container": "^1.0" 44 | }, 45 | "provide": { 46 | "psr/container-implementation": "1.0" 47 | }, 48 | "autoload": { 49 | "files": [ 50 | "lib/Constants.php", 51 | "lib/ezFunctions.php" 52 | ], 53 | "psr-4": { 54 | "ezsql\\": "lib/" 55 | } 56 | }, 57 | "require-dev": { 58 | "phpunit/phpunit": "^6 | ^7 | ^8" 59 | }, 60 | "autoload-dev": { 61 | "psr-4": { 62 | "ezsql\\Tests\\": "tests/" 63 | } 64 | }, 65 | "scripts": { 66 | "test": "phpunit --bootstrap vendor/autoload.php tests" 67 | }, 68 | "minimum-stability": "stable" 69 | } 70 | -------------------------------------------------------------------------------- /lib/Config.php: -------------------------------------------------------------------------------- 1 | setDriver($sql); 20 | if ($sql == \Pdo) { 21 | $this->setupPdo($arguments); 22 | } elseif ($sql == \POSTGRESQL) { 23 | $this->setupPgsql($arguments); 24 | } elseif ($sql == \SQLSRV) { 25 | $this->setupSqlsrv($arguments); 26 | } elseif ($sql == \MYSQLI) { 27 | $this->setupMysqli($arguments); 28 | } elseif ($sql == \SQLITE3) { 29 | $this->setupSqlite3($arguments); 30 | } 31 | } 32 | } 33 | 34 | public static function initialize(string $driver = '', array $arguments = null) 35 | { 36 | return new self($driver, $arguments); 37 | } 38 | 39 | private function setupMysqli($args) 40 | { 41 | if (!\function_exists('mysqli_connect')) 42 | throw new Exception('Fatal Error: ez_mysql requires mySQLi Lib to be compiled and or linked in to the PHP engine'); 43 | 44 | if (\count($args) >= 3) { 45 | $this->setUser($args[0]); 46 | $this->setPassword($args[1]); 47 | $this->setName($args[2]); 48 | $this->setHost(empty($args[3]) ? $this->getHost() : $args[3]); 49 | $this->setPort(empty($args[4]) ? '3306' : $args[4]); 50 | $charset = !empty($args[5]) ? $args[5] : ''; 51 | $this->setCharset(empty($charset) ? $this->getCharset() : \strtolower(\str_replace('-', '', $charset))); 52 | } else 53 | throw new Exception(\MISSING_CONFIGURATION); 54 | } 55 | 56 | private function setupPdo($args) 57 | { 58 | if (!\class_exists('PDO')) 59 | throw new Exception('Fatal Error: ez_pdo requires PDO Lib to be compiled and or linked in to the PHP engine'); 60 | if (\count($args) >= 3) { 61 | $this->setDsn($args[0]); 62 | $this->setUser($args[1]); 63 | $this->setPassword($args[2]); 64 | $this->setOptions(empty($args[3]) ? $this->getOptions() : $args[3]); 65 | $this->setIsFile(empty($args[4]) ? $this->getIsFile() : $args[4]); 66 | } else 67 | throw new Exception(\MISSING_CONFIGURATION); 68 | } 69 | 70 | private function setupSqlsrv($args) 71 | { 72 | if (!\function_exists('sqlsrv_connect')) 73 | throw new Exception('Fatal Error: ez_sqlsrv requires the php_sqlsrv.dll or php_pdo_sqlsrv.dll to be installed. Also enable MS-SQL extension in PHP.ini file '); 74 | 75 | if (\count($args) >= 3) { 76 | $this->setUser($args[0]); 77 | $this->setPassword($args[1]); 78 | $this->setName($args[2]); 79 | $this->setHost(empty($args[3]) ? $this->getHost() : $args[3]); 80 | $this->setToMssql(empty($args[4]) ? $this->getToMssql() : $args[4]); 81 | } else 82 | throw new Exception(\MISSING_CONFIGURATION); 83 | } 84 | 85 | private function setupPgsql($args) 86 | { 87 | if (!\function_exists('pg_connect')) 88 | throw new Exception('Fatal Error: ez_pgsql requires PostgreSQL Lib to be compiled and or linked in to the PHP engine'); 89 | 90 | if (count($args) >= 3) { 91 | $this->setUser($args[0]); 92 | $this->setPassword($args[1]); 93 | $this->setName($args[2]); 94 | $this->setHost(empty($args[3]) ? $this->getHost() : $args[3]); 95 | $this->setPort(empty($args[4]) ? '5432' : $args[4]); 96 | } else 97 | throw new Exception(\MISSING_CONFIGURATION); 98 | } 99 | 100 | private function setupSqlite3($args) 101 | { 102 | if (!\class_exists('SQLite3')) 103 | throw new Exception('Fatal Error: ez_sqlite3 requires SQLite3 Lib to be compiled and or linked in to the PHP engine'); 104 | 105 | if (\count($args) == 2) { 106 | $this->setPath($args[0]); 107 | $this->setName($args[1]); 108 | } else 109 | throw new Exception(\MISSING_CONFIGURATION); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /lib/ConfigAbstract.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 7 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 8 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 9 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 10 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 12 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 13 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 14 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 15 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 16 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 | * 18 | * This software consists of voluntary contributions made by many individuals 19 | * and is licensed under the MIT license. 20 | */ 21 | 22 | declare(strict_types=1); 23 | 24 | namespace ezsql; 25 | 26 | /** 27 | * 28 | * @method void setDriver($args); 29 | * Database Sql driver name 30 | * @method void setDsn($args); 31 | * The PDO connection parameter string, database server in the DSN parameters 32 | * @method void setUser($args); 33 | * Database user name 34 | * @method void setPassword($args); 35 | * Database password for the given user 36 | * @method void setName($args); 37 | * Database name 38 | * @method void setHost($args); 39 | * Host name or IP address 40 | * @method void setPort($args); 41 | * TCP/IP port of PostgreSQL/MySQL 42 | * @method void setCharset($args); 43 | * Database charset 44 | * @method void setOptions($args); 45 | * The PDO array for connection options, MySQL connection charset, for example 46 | * @method void setIsFile($args); 47 | * Check PDO for whether it is a file based database connection, for example to a SQLite 48 | * database file, or not 49 | * @method void setToMssql($args); 50 | * If we want to convert Queries in MySql syntax to MS-SQL syntax. 51 | * Yes, there are some differences in query syntax. 52 | * @method void setToMysql($args); 53 | * If we want to convert Queries in MySql syntax to MS-SQL syntax. 54 | * Yes, there are some differences in query syntax. 55 | * @method void setPath($args); 56 | * The path to open an SQLite database 57 | * 58 | * @method string getDriver(); 59 | * Database Sql driver name 60 | * @method string getDsn(); 61 | * The PDO connection parameter string, database server in the DSN parameters 62 | * @method string getUser(); 63 | * Database user name 64 | * @method string getPassword() 65 | * Database password for the given user 66 | * @method string getName(); 67 | * Database name 68 | * @method string getHost(); 69 | * Host name or IP address 70 | * @method string getPort(); 71 | * TCP/IP port of PostgreSQL/MySQL 72 | * @method string getCharset(); 73 | * Database charset 74 | * @method string getOptions(); 75 | * The PDO array for connection options, MySQL connection charset, for example 76 | * @method string getToMysql(); 77 | * If we want to convert Queries in MySql syntax to MS-SQL syntax. 78 | * Yes, there are some differences in query syntax. 79 | * @method bool getIsFile(); 80 | * Check PDO for whether it is a file based database connection, for example to a SQLite 81 | * database file, or not 82 | * @method bool getToMssql(); 83 | * If we want to convert Queries in MySql syntax to MS-SQL syntax. 84 | * Yes, there are some differences in query syntax. 85 | * @method string getPath(); 86 | * The path to open an SQLite database 87 | */ 88 | abstract class ConfigAbstract 89 | { 90 | /** 91 | * Database Sql driver name 92 | * @var string 93 | */ 94 | private $driver; 95 | 96 | /** 97 | * Database user name 98 | * @var string 99 | */ 100 | private $user = ''; 101 | 102 | /** 103 | * Database password for the given user 104 | * @var string 105 | */ 106 | private $password = ''; 107 | 108 | /** 109 | * Database name 110 | * @var string 111 | */ 112 | private $name = ''; 113 | 114 | /** 115 | * Host name or IP address 116 | * @var string 117 | */ 118 | private $host = 'localhost'; 119 | 120 | /** 121 | * Database charset 122 | * @var string Default is utf8 123 | */ 124 | private $charset = 'utf8'; 125 | 126 | /** 127 | * The PDO connection parameter string, database server in the DSN parameters 128 | * @var string Default is empty string 129 | */ 130 | private $dsn = ''; 131 | 132 | /** 133 | * The PDO array for connection options, MySQL connection charset, for example 134 | * @var array 135 | */ 136 | private $options = array(); 137 | 138 | /** 139 | * Check PDO for whether it is a file based database connection, for example to a SQLite 140 | * database file, or not 141 | * @var boolean Default is false 142 | */ 143 | private $isfile = false; 144 | 145 | /** 146 | * TCP/IP port of PostgreSQL 147 | * @var string Default is port 5432 148 | */ 149 | private $port = '5432'; 150 | 151 | /** 152 | * If we want to convert Queries in MySql syntax to MS-SQL syntax. 153 | * Yes, there are some differences in query syntax. 154 | */ 155 | private $tomssql = true; 156 | 157 | /** 158 | * The path to open an SQLite database 159 | */ 160 | private $path = ''; 161 | 162 | /** 163 | * Use for Calling Non-Existent Functions, handling Getters and Setters 164 | * @property-read function 165 | * @property-write args 166 | * 167 | * @return mixed 168 | */ 169 | public function __call($function, $args) 170 | { 171 | $prefix = \substr($function, 0, 3); 172 | $property = \strtolower(substr($function, 3, \strlen($function))); 173 | if (($prefix == 'set') && \property_exists($this, $property)) { 174 | $this->$property = $args[0]; 175 | } elseif (($prefix == 'get') && \property_exists($this, $property)) { 176 | return $this->$property; 177 | } else { 178 | throw new \Exception("$function does not exist"); 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /lib/ConfigInterface.php: -------------------------------------------------------------------------------- 1 | Fatal Error: Missing configuration details to connect to database'); 17 | \define('CONFIGURATION_REQUIRES', 'Fatal Error: This configuration requires ezsqlModel (ezsqlModel.php) to be included/loaded before it can be used'); 18 | \define('FAILED_CONNECTION', 'Failed to make connection to database'); 19 | 20 | // ezQuery prepare placeholder/positional tag 21 | \define('_TAG', '__ez__'); 22 | 23 | /** 24 | * Operator boolean expressions. 25 | */ 26 | \define('EQ', '='); 27 | \define('NEQ', '<>'); 28 | \define('NE', '!='); 29 | \define('LT', '<'); 30 | \define('LTE', '<='); 31 | \define('GT', '>'); 32 | \define('GTE', '>='); 33 | \define('_BOOLEAN', ['<', '>', '=', '!=', '>=', '<=', '<>']); 34 | 35 | \define('_IN', 'IN'); 36 | \define('_notIN', 'NOT IN'); 37 | \define('_LIKE', 'LIKE'); 38 | \define('_notLIKE', 'NOT LIKE'); 39 | \define('_BETWEEN', 'BETWEEN'); 40 | \define('_notBETWEEN', 'NOT BETWEEN'); 41 | 42 | \define('_isNULL', 'IS NULL'); 43 | \define('_notNULL', 'IS NOT NULL'); 44 | \define('_BOOLEAN_OPERATORS', [ 45 | '<', '>', '=', '!=', '>=', '<=', '<>', 46 | 'IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'NOT BETWEEN', 'IS', 'IS NOT' 47 | ]); 48 | 49 | /** 50 | * Combine operators. 51 | */ 52 | \define('_AND', 'AND'); 53 | \define('_OR', 'OR'); 54 | \define('_NOT', 'NOT'); 55 | \define('_andNOT', 'AND NOT'); 56 | \define('_COMBINERS', ['AND', 'OR', 'NOT', 'AND NOT']); 57 | 58 | /* 59 | * for joining shortcut methods. 60 | */ 61 | \define('_INNER', 'INNER'); 62 | \define('_LEFT', 'LEFT'); 63 | \define('_RIGHT', 'RIGHT'); 64 | \define('_FULL', 'FULL'); 65 | \define('_JOINERS', ['INNER', 'LEFT', 'RIGHT', 'FULL']); 66 | 67 | /** 68 | * Associative array of supported SQL Drivers, and library 69 | * @define(array) 70 | */ 71 | \define('VENDOR', [ 72 | 'mysql' => 'ezsql\Database\ez_mysqli', 73 | 'mysqli' => 'ezsql\Database\ez_mysqli', 74 | 'pdo' => 'ezsql\Database\ez_pdo', 75 | 'postgresql' => 'ezsql\Database\ez_pgsql', 76 | 'pgsql' => 'ezsql\Database\ez_pgsql', 77 | 'sqlite' => 'ezsql\Database\ez_sqlite3', 78 | 'sqlite3' => 'ezsql\Database\ez_sqlite3', 79 | 'sqlserver' => 'ezsql\Database\ez_sqlsrv', 80 | 'mssql' => 'ezsql\Database\ez_sqlsrv', 81 | 'sqlsrv' => 'ezsql\Database\ez_sqlsrv' 82 | ]); 83 | 84 | \define('MYSQL', 'mysqli'); 85 | \define('MYSQLI', 'mysqli'); 86 | \define('Pdo', 'pdo'); 87 | \define('PGSQL', 'pgsql'); 88 | \define('POSTGRESQL', 'pgsql'); 89 | \define('SQLITE', 'sqlite3'); 90 | \define('SQLITE3', 'sqlite3'); 91 | \define('SQLSRV', 'sqlsrv'); 92 | \define('SQLSERVER', 'sqlsrv'); 93 | \define('MSSQL', 'sqlsrv'); 94 | 95 | // String SQL data types 96 | \define('CHAR', 'CHAR'); 97 | \define('VARCHAR', 'VARCHAR'); 98 | \define('CHARACTER', 'CHARACTER'); 99 | \define('TEXT', 'TEXT'); 100 | \define('TINY', 'TINYTEXT'); 101 | \define('TINYTEXT', 'TINYTEXT'); 102 | \define('MEDIUM', 'MEDIUMTEXT'); 103 | \define('MEDIUMTEXT', 'MEDIUMTEXT'); 104 | \define('LONGTEXT', 'LONGTEXT'); 105 | \define('BINARY', 'BINARY'); 106 | \define('VARBINARY', 'VARBINARY'); 107 | \define('NCHAR', 'NCHAR'); 108 | \define('NVAR', 'NVARCHAR'); 109 | \define('NVARCHAR', 'NVARCHAR'); 110 | \define('NTEXT', 'NTEXT'); 111 | \define('IMAGE', 'IMAGE'); 112 | \define('CLOB', 'CLOB'); 113 | 114 | // Numeric SQL data types 115 | \define('INTR', 'INT'); 116 | \define('INT0', 'INT'); 117 | \define('INT2', 'INT2'); 118 | \define('INT4', 'INT4'); 119 | \define('INT8', 'INT8'); 120 | \define('NUMERIC', 'NUMERIC'); 121 | \define('DECIMAL', 'DECIMAL'); 122 | \define('BIT', 'BIT'); 123 | \define('VARBIT', 'VARBIT'); 124 | \define('INTEGERS', 'INTEGER'); 125 | \define('TINYINT', 'TINYINT'); 126 | \define('SMALLINT', 'SMALLINT'); 127 | \define('MEDIUMINT', 'MEDIUMINT'); 128 | \define('BIGINT', 'BIGINT'); 129 | \define('DEC', 'DEC'); 130 | \define('FIXED', 'FIXED'); 131 | \define('FLOATS', 'FLOAT'); 132 | \define('DOUBLES', 'DOUBLE'); 133 | \define('REALS', 'REAL'); 134 | \define('BOOLS', 'BOOL'); 135 | \define('BOOLEANS', 'BOOLEAN'); 136 | \define('SMALLMONEY', 'SMALLMONEY'); 137 | \define('MONEY', 'MONEY'); 138 | 139 | // Date/Time SQL data types 140 | \define('DATES', 'DATE'); 141 | \define('TIMESTAMP', 'TIMESTAMP'); 142 | \define('TIMES', 'TIME'); 143 | \define('DATETIME', 'DATETIME'); 144 | \define('YEAR', 'YEAR'); 145 | \define('DATETIME2', 'DATETIME2'); 146 | \define('SMALLDATETIME', 'SMALLDATETIME'); 147 | \define('DATETIMEOFFSET', 'DATETIMEOFFSET'); 148 | 149 | // Large Object SQL data types 150 | \define('TINYBLOB', 'TINYBLOB'); 151 | \define('BLOB', 'BLOB'); 152 | \define('MEDIUMBLOB', 'MEDIUMBLOB'); 153 | 154 | \define('NULLS', 'NULL'); 155 | \define('notNULL', 'NOT NULL'); 156 | 157 | \define('CONSTRAINT', 'CONSTRAINT'); 158 | \define('PRIMARY', 'PRIMARY KEY'); 159 | \define('FOREIGN', 'FOREIGN KEY'); 160 | \define('UNIQUE', 'UNIQUE'); 161 | \define('INDEX', 'INDEX'); 162 | \define('REFERENCES', 'REFERENCES'); 163 | 164 | \define('AUTO', '__autoNumbers__'); 165 | \define('SEQUENCE', '__autoNumbers__'); 166 | \define('AUTO_INCREMENT', 'AUTO_INCREMENT'); 167 | \define('AUTOINCREMENT', 'AUTOINCREMENT'); 168 | \define('IDENTITY', 'IDENTITY'); 169 | \define('SERIAL', 'SERIAL'); 170 | \define('SMALLSERIAL', 'SMALLSERIAL'); 171 | \define('BIGSERIAL', 'BIGSERIAL'); 172 | 173 | \define('ADD', 'ADD'); 174 | \define('DROP', 'DROP COLUMN'); 175 | \define('CHANGE', 'CHANGE COLUMN'); 176 | \define('ALTER', 'ALTER COLUMN'); 177 | \define('MODIFY', 'MODIFY COLUMN'); 178 | \define('RENAME', 'RENAME TO'); 179 | \define('CHANGER', '__modifyingColumns__'); 180 | 181 | if (!\defined('_DS')) 182 | \define('_DS', \DIRECTORY_SEPARATOR); 183 | 184 | \define('CONSTANTS', true); 185 | } 186 | -------------------------------------------------------------------------------- /lib/DInjector.php: -------------------------------------------------------------------------------- 1 | instances[$abstract] = $concrete; 36 | } 37 | 38 | /** 39 | * @param $abstract 40 | * 41 | * @return null|object 42 | * @throws NotFoundException 43 | */ 44 | public function get($abstract, $values = []) 45 | { 46 | if (!$this->has($abstract)) { 47 | throw new NotFoundException("{$abstract} does not exists"); 48 | } 49 | 50 | return $this->resolve($this->instances[$abstract], $values); 51 | } 52 | 53 | /** 54 | * Auto setup, execute, or resolve any dependencies. 55 | * 56 | * @param $abstract 57 | * @param array $values 58 | * 59 | * @return mixed|null|object 60 | * @throws ContainerException 61 | */ 62 | public function autoWire($abstract, $values = []) 63 | { 64 | // if we don't have it, just register it 65 | if (!$this->has($abstract)) { 66 | $this->set($abstract); 67 | } 68 | 69 | return $this->resolve($this->instances[$abstract], $values); 70 | } 71 | 72 | /** 73 | * Do we have dependence 74 | * @param $abstract 75 | * @return bool 76 | */ 77 | public function has($abstract): bool 78 | { 79 | return isset($this->instances[$abstract]); 80 | } 81 | 82 | /** 83 | * resolve single dependence 84 | * 85 | * @param $concrete 86 | * @param $values 87 | * 88 | * @return mixed|object 89 | * @throws ContainerException 90 | */ 91 | protected function resolve($concrete, $values = []) 92 | { 93 | if ($concrete instanceof \Closure) { 94 | return $concrete($this, $values); 95 | } 96 | 97 | $reflector = new \ReflectionClass($concrete); 98 | // check if class is instantiable 99 | if (!$reflector->isInstantiable()) { 100 | throw new ContainerException("Class {$concrete} is not instantiable"); 101 | } 102 | 103 | // get class constructor 104 | $constructor = $reflector->getConstructor(); 105 | if (\is_null($constructor)) { 106 | // get new instance from class 107 | return $reflector->newInstance(); 108 | } 109 | 110 | // get constructor params 111 | $parameters = $constructor->getParameters(); 112 | $dependencies = $this->getDependencies($parameters, $values); 113 | 114 | // get new instance with dependencies resolved 115 | return $reflector->newInstanceArgs($dependencies); 116 | } 117 | 118 | /** 119 | * get all dependencies resolved 120 | * 121 | * @param $parameters 122 | * 123 | * @return array 124 | * @throws ContainerException 125 | */ 126 | protected function getDependencies($parameters, $values = null) 127 | { 128 | $dependencies = []; 129 | if (\is_array($parameters)) { 130 | foreach ($parameters as $parameter) { 131 | // get the type hinted class 132 | $dependency = $parameter->getType() && !$parameter->getType()->isBuiltin() 133 | ? new \ReflectionClass($parameter->getType()->getName()) 134 | : NULL; 135 | if ($dependency === NULL) { 136 | // check if the constructor parameter name exists as a key in the values array 137 | if (\array_key_exists($parameter->getName(), $values)) { 138 | // get default value of parameter 139 | $dependencies[] = $values[$parameter->getName()]; 140 | } else { 141 | // check if default value for a parameter is available 142 | if ($parameter->isDefaultValueAvailable()) { 143 | // get default value of parameter 144 | $dependencies[] = $parameter->getDefaultValue(); 145 | } else { 146 | throw new ContainerException("Can not resolve class dependency {$parameter->name}"); 147 | } 148 | } 149 | } else { 150 | // get dependency resolved 151 | $dependencies[] = $this->autoWire($dependency->name, $values); 152 | } 153 | } 154 | } 155 | 156 | return $dependencies; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /lib/Database.php: -------------------------------------------------------------------------------- 1 | set($key, $value); 88 | $di->set('ezsql\ConfigInterface', 'ezsql\Config'); 89 | $instance = $di->get($key, ['driver' => $key, 'arguments' => $setting]); 90 | if (!empty($tag)) { 91 | self::$instances[$tag] = $instance; 92 | return $instance; 93 | } 94 | } 95 | 96 | $db = Db::get('ez' . $key); 97 | Db::set('global', $db); 98 | return $db; 99 | } 100 | } 101 | 102 | /** 103 | * Print-out a memory used benchmark. 104 | * 105 | * @return array|float time elapsed, memory usage. 106 | */ 107 | public static function benchmark() 108 | { 109 | return [ 110 | 'start' => self::$_ts, 111 | 'elapse' => \microtime(true) - self::$_ts, 112 | 'memory' => \memory_get_usage(true), 113 | ]; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/Database/ez_pdo.php: -------------------------------------------------------------------------------- 1 | database = $settings; 46 | 47 | // Turn on track errors 48 | ini_set('track_errors', '1'); 49 | 50 | if (!Db::has('ez' . \Pdo)) 51 | Db::set('ez' . \Pdo, $this); 52 | Db::set('global', $this); 53 | } // __construct 54 | 55 | public function settings() 56 | { 57 | return $this->database; 58 | } 59 | 60 | /** 61 | * Try to connect to the database server in the DSN parameters 62 | * 63 | * @param string $dsn The connection parameter string 64 | * Default is empty string 65 | * @param string $user The database user name 66 | * Default is empty string 67 | * @param string $password The database password 68 | * Default is empty string 69 | * @param array $options Array for setting connection options 70 | * Default is an empty array 71 | * @param boolean $isFileBased File based databases like SQLite don't need user and password, 72 | * Default is false 73 | * @return boolean 74 | */ 75 | public function connect( 76 | $dsn = '', 77 | $user = '', 78 | $password = '', 79 | $options = array(), 80 | $isFile = false 81 | ) { 82 | $this->_connected = false; 83 | $key = $this->sslKey; 84 | $cert = $this->sslCert; 85 | $ca = $this->sslCa; 86 | $path = $this->sslPath; 87 | 88 | $vendor = $this->database->getDsn(); 89 | if ($this->isSecure) { 90 | if (\strpos($vendor, \PGSQL) !== false) { 91 | $this->secureOptions = 'sslmode=require;sslcert=' . $path . $cert . ';sslkey=' . $path . $key . ';sslrootcert=' . $path . $ca . ';'; 92 | } elseif (\strpos($vendor, 'mysql') !== false) { 93 | $this->secureOptions = array( 94 | \PDO::MYSQL_ATTR_SSL_KEY => $path . $key, 95 | \PDO::MYSQL_ATTR_SSL_CERT => $path . $cert, 96 | \PDO::MYSQL_ATTR_SSL_CA => $path . $ca, 97 | \PDO::MYSQL_ATTR_SSL_CAPATH => $path, 98 | \PDO::MYSQL_ATTR_SSL_CIPHER => 'DHE-RSA-AES256-SHA', 99 | \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false 100 | ); 101 | } elseif (\strpos($vendor, \MSSQL) !== false) { 102 | $this->secureOptions = ';Encrypt=true;TrustServerCertificate=true'; 103 | } 104 | } 105 | 106 | if ($this->isSecure && \is_string($this->secureOptions)) 107 | $dsn = empty($dsn) ? $vendor . $this->secureOptions : $dsn . $this->secureOptions; 108 | else 109 | $dsn = empty($dsn) ? $vendor : $dsn; 110 | 111 | if ($this->isSecure && \is_array($this->secureOptions)) 112 | $options = $this->secureOptions; 113 | else 114 | $options = empty($options) ? $this->database->getOptions() : $options; 115 | 116 | $user = empty($user) ? $this->database->getUser() : $user; 117 | $password = empty($password) ? $this->database->getPassword() : $password; 118 | $isFile = empty($isFile) ? $this->database->getIsFile() : $isFile; 119 | 120 | // Establish PDO connection 121 | try { 122 | if ($isFile) { 123 | $this->dbh = new \PDO($dsn, null, null, null); 124 | $this->_connected = true; 125 | } else { 126 | $this->dbh = new \PDO($dsn, $user, $password, $options); 127 | $this->_connected = true; 128 | } 129 | } catch (\PDOException $e) { 130 | $this->register_error($e->getMessage() . '- $dsn: ' . $dsn); 131 | } 132 | 133 | return $this->_connected; 134 | } // connect 135 | 136 | /** 137 | * With PDO it is only an alias for the connect method 138 | * 139 | * @param string $dsn The connection parameter string 140 | * - Default is empty string 141 | * @param string $user The database user name 142 | * - Default is empty string 143 | * @param string $password The database password 144 | * - Default is empty string 145 | * @param array $options Array for setting connection options 146 | * - Default is an empty array 147 | * @param boolean $isFileBased File based databases 148 | * like SQLite don't need user and password, they work with path in the dsn parameter 149 | * - Default is false 150 | * @return boolean 151 | */ 152 | public function quick_connect( 153 | $dsn = '', 154 | $user = '', 155 | $password = '', 156 | $options = array(), 157 | $isFileBased = false 158 | ) { 159 | return $this->connect($dsn, $user, $password, $options, $isFileBased); 160 | } // quick_connect 161 | 162 | /** 163 | * Format a SQLite string correctly for safe SQLite insert 164 | * (no mater if magic quotes are on or not) 165 | */ 166 | 167 | /** 168 | * Escape a string with the PDO method 169 | * 170 | * @param string $str 171 | * @return string 172 | */ 173 | public function escape(string $str) 174 | { 175 | // If there is no existing database connection then try to connect 176 | if (!isset($this->dbh) || !$this->dbh) { 177 | $this->connect( 178 | $this->database->getDsn(), 179 | $this->database->getUser(), 180 | $this->database->getPassword(), 181 | $this->database->getOptions(), 182 | $this->database->getIsFile() 183 | ); 184 | } 185 | 186 | // pdo quote adds ' at the beginning and at the end, remove them for standard behavior 187 | $return_val = \substr($this->dbh->quote($str), 1, -1); 188 | 189 | return $return_val; 190 | } // escape 191 | 192 | /** 193 | * Return SQLite specific system date syntax 194 | * i.e. Oracle: SYSDATE Mysql: NOW() 195 | * 196 | * @return string 197 | */ 198 | public function sysDate() 199 | { 200 | return "datetime('now')"; 201 | } 202 | 203 | /** 204 | * Hooks into PDO error system and reports it to user 205 | * 206 | * @return string 207 | */ 208 | public function catch_error() 209 | { 210 | $error_str = 'No error info'; 211 | 212 | $err_array = $this->dbh->errorInfo(); 213 | 214 | // Note: Ignoring error - bind or column index out of range 215 | if (isset($err_array[1]) && $err_array[1] != 25) { 216 | 217 | $error_str = ''; 218 | foreach ($err_array as $entry) { 219 | $error_str .= $entry . ', '; 220 | } 221 | 222 | $error_str = \substr($error_str, 0, -2); 223 | 224 | $this->register_error($error_str . ' ' . $this->lastQuery); 225 | 226 | return true; 227 | } 228 | } // catch_error 229 | 230 | /** 231 | * Creates a prepared query, binds the given parameters and returns the result of the executed 232 | * 233 | * @param string $query 234 | * @param array $param 235 | * @param boolean $isSelect - return \PDOStatement, if SELECT SQL statement, otherwise int 236 | * @return bool|int|\PDOStatement 237 | */ 238 | public function query_prepared(string $query, array $param = null, $isSelect = false) 239 | { 240 | $stmt = $this->dbh->prepare($query); 241 | $result = false; 242 | if ($stmt && $stmt->execute(\array_values($param))) { 243 | $result = $stmt->rowCount(); 244 | // Store Query Results 245 | $num_rows = 0; 246 | try { 247 | while ($row = @$stmt->fetch(\PDO::FETCH_ASSOC)) { 248 | // Store results as an objects within main array 249 | $this->lastResult[$num_rows] = (object) $row; 250 | $num_rows++; 251 | } 252 | } catch (\Throwable $ex) { 253 | // 254 | } 255 | 256 | $this->numRows = $num_rows; 257 | } 258 | 259 | $return = ($isSelect) ? $stmt : $result; 260 | if ($this->shortcutUsed) 261 | return $return; 262 | 263 | $status = ((\strpos($query, 'SELECT ') !== false) || (\strpos($query, 'select ') !== false)); 264 | $prepareOnly = ($status) ? $stmt : $result; 265 | return $this->processResult($query, $prepareOnly, $status); 266 | } 267 | 268 | /** 269 | * Perform post processing on SQL query call 270 | * 271 | * @param string $query 272 | * @param mixed $result 273 | * @param bool $isSelect 274 | * @return bool|void 275 | */ 276 | private function processResult(string $query, $result = null, bool $isSelect = false) 277 | { 278 | $this->shortcutUsed = false; 279 | 280 | // If there is an error then take note of it.. 281 | if ($this->catch_error()) { 282 | return false; 283 | } 284 | 285 | if ($isSelect) { 286 | $this->is_insert = false; 287 | 288 | if (!empty($result)) { 289 | $col_count = $result->columnCount(); 290 | for ($i = 0; $i < $col_count; $i++) { 291 | // Start DEBUG by psc! 292 | $this->colInfo[$i] = new \stdClass(); 293 | // End DEBUG by psc 294 | if ($meta = $result->getColumnMeta($i)) { 295 | $this->colInfo[$i]->name = $meta['name']; 296 | $this->colInfo[$i]->type = $meta['native_type']; 297 | $this->colInfo[$i]->max_length = ''; 298 | } else { 299 | $this->colInfo[$i]->name = 'undefined'; 300 | $this->colInfo[$i]->type = 'undefined'; 301 | $this->colInfo[$i]->max_length = ''; 302 | } 303 | } 304 | 305 | // Store Query Results 306 | $num_rows = 0; 307 | try { 308 | while ($row = @$result->fetch(\PDO::FETCH_ASSOC)) { 309 | // Store results as an objects within main array 310 | $this->lastResult[$num_rows] = (object) $row; 311 | $num_rows++; 312 | } 313 | } catch (\Throwable $ex) { 314 | // 315 | } 316 | 317 | // Log number of rows the query returned 318 | $this->numRows = empty($num_rows) ? $this->numRows : $num_rows; 319 | 320 | // Return number of rows selected 321 | $this->return_val = $this->numRows; 322 | } 323 | } else { 324 | $this->is_insert = true; 325 | 326 | if (!empty($result)) 327 | $this->_affectedRows = $result; 328 | 329 | try { 330 | // Take note of the insert_id 331 | if (\preg_match("/^(insert|replace)\s+/i", $query)) { 332 | $this->insertId = @$this->dbh->lastInsertId(); 333 | } 334 | } catch (\Throwable $ex) { 335 | // 336 | } 337 | 338 | // Return number of rows affected 339 | $this->return_val = $this->_affectedRows; 340 | } 341 | 342 | return $this->return_val; 343 | } 344 | 345 | /** 346 | * Perform SQL query 347 | * 348 | * @param string $query 349 | * @param array $param 350 | * @return bool|void 351 | */ 352 | private function processQuery(string $query, array $param = null) 353 | { 354 | // Query was an insert, delete, update, replace 355 | if (\preg_match("/^(insert|delete|update|replace|drop|create)\s+/i", $query)) { 356 | // Perform the query and log number of affected rows 357 | // Perform the query via std PDO query or PDO prepare function.. 358 | if (!empty($param) && \is_array($param) && $this->isPrepareOn()) { 359 | $this->shortcutUsed = true; 360 | $this->_affectedRows = $this->query_prepared($query, $param, false); 361 | } else { 362 | try { 363 | $this->_affectedRows = $this->dbh->exec($query); 364 | } catch (\Throwable $ex) { 365 | // 366 | } 367 | } 368 | 369 | if ($this->processResult($query) === false) 370 | return false; 371 | } else { 372 | // Query was an select 373 | 374 | // Perform the query and log number of affected rows 375 | // Perform the query via std PDO query or PDO prepare function.. 376 | if (!empty($param) && \is_array($param) && $this->isPrepareOn()) { 377 | $this->shortcutUsed = true; 378 | $sth = $this->query_prepared($query, $param, true); 379 | } else 380 | try { 381 | $sth = $this->dbh->query($query); 382 | } catch (\Throwable $ex) { 383 | // 384 | } 385 | 386 | if ($this->processResult($query, $sth, true) === false) 387 | return false; 388 | } 389 | } 390 | 391 | /** 392 | * Basic Query - see docs for more detail 393 | * 394 | * @param string $query 395 | * @param bool $use_prepare 396 | * @return object 397 | */ 398 | public function query(string $query, bool $use_prepare = false) 399 | { 400 | $param = []; 401 | if ($use_prepare) 402 | $param = $this->prepareValues(); 403 | 404 | // check for ezQuery placeholder tag and replace tags with proper prepare tag 405 | $query = \str_replace(_TAG, '?', $query); 406 | 407 | // For reg expressions 408 | $query = \str_replace("/[\n\r]/", '', \trim($query)); 409 | 410 | // Initialize return 411 | $this->return_val = 0; 412 | 413 | // Flush cached values.. 414 | $this->flush(); 415 | 416 | // Log how the function was called 417 | $this->log_query("\$db->query(\"$query\")"); 418 | 419 | // Keep track of the last query for debug.. 420 | $this->lastQuery = $query; 421 | 422 | $this->numQueries++; 423 | 424 | // Start timer 425 | $this->timer_start($this->numQueries); 426 | 427 | // Use core file cache function 428 | if ($cache = $this->get_cache($query)) { 429 | // Keep tack of how long all queries have taken 430 | $this->timer_update_global($this->numQueries); 431 | 432 | // Trace all queries 433 | if ($this->useTraceLog) { 434 | $this->traceLog[] = $this->debug(false); 435 | } 436 | 437 | return $cache; 438 | } 439 | 440 | // If there is no existing database connection then try to connect 441 | if (!isset($this->dbh) || !$this->dbh) { 442 | $this->connect( 443 | $this->database->getDsn(), 444 | $this->database->getUser(), 445 | $this->database->getPassword(), 446 | $this->database->getOptions(), 447 | $this->database->getIsFile() 448 | ); 449 | } 450 | 451 | if ($this->processQuery($query, $param) === false) { 452 | if ($this->isTransactional) 453 | throw new \PDOException($this->getLastError()); 454 | 455 | return false; 456 | } 457 | 458 | // disk caching of queries 459 | $this->store_cache($query, $this->is_insert); 460 | 461 | // If debug ALL queries 462 | $this->trace || $this->debugAll ? $this->debug() : null; 463 | 464 | // Keep tack of how long all queries have taken 465 | $this->timer_update_global($this->numQueries); 466 | 467 | // Trace all queries 468 | if ($this->useTraceLog) { 469 | $this->traceLog[] = $this->debug(false); 470 | } 471 | 472 | return $this->return_val; 473 | } // query 474 | 475 | /** 476 | * Close the database connection 477 | */ 478 | public function disconnect() 479 | { 480 | if ($this->dbh) { 481 | $this->dbh = null; 482 | $this->_connected = false; 483 | } 484 | } 485 | 486 | /** 487 | * Reset database handle 488 | */ 489 | public function reset() 490 | { 491 | $this->dbh = null; 492 | } 493 | 494 | /** 495 | * Get connection handle 496 | */ 497 | public function handle() 498 | { 499 | return $this->dbh; 500 | } 501 | 502 | /** 503 | * Begin PDO Transaction 504 | */ 505 | public function beginTransaction() 506 | { 507 | $this->dbh->beginTransaction(); 508 | $this->isTransactional = true; 509 | } 510 | 511 | public function commit() 512 | { 513 | $this->dbh->commit(); 514 | $this->isTransactional = false; 515 | } 516 | 517 | public function rollback() 518 | { 519 | $this->dbh->rollback(); 520 | $this->isTransactional = false; 521 | } 522 | } // ez_pdo 523 | -------------------------------------------------------------------------------- /lib/Database/ez_pgsql.php: -------------------------------------------------------------------------------- 1 | database = $settings; 46 | 47 | if (!Db::has('ez' . \PGSQL)) 48 | Db::set('ez' . \PGSQL, $this); 49 | Db::set('global', $this); 50 | } // __construct 51 | 52 | public function settings() 53 | { 54 | return $this->database; 55 | } 56 | 57 | /** 58 | * In the case of PostgreSQL quick_connect is not really needed because std. 59 | * connect already does what quick connect does - but for the sake of 60 | * consistency it has been included 61 | * 62 | * @param string $user The database user name 63 | * @param string $password The database users password 64 | * @param string $name The name of the database 65 | * @param string $host The host name or IP address of the database server. 66 | * Default is localhost 67 | * @param string $port The database TCP/IP port 68 | * Default is PostgreSQL default port 5432 69 | * @return boolean 70 | */ 71 | public function quick_connect($user = '', $password = '', $name = '', $host = 'localhost', $port = '5432') 72 | { 73 | if (!$this->connect($user, $password, $name, $host, $port)); 74 | return $this->_connected; 75 | } // quick_connect 76 | 77 | /** 78 | * Try to connect to PostgreSQL database server 79 | * 80 | * @param string $user The database user name 81 | * @param string $password The database users password 82 | * @param string $name The name of the database 83 | * @param string $host The host name or IP address of the database server. 84 | * Default is localhost 85 | * @param string $port The database TCP/IP port 86 | * Default is PostgreSQL default port 5432 87 | * @return boolean 88 | */ 89 | public function connect( 90 | string $user = '', 91 | string $password = '', 92 | string $name = '', 93 | string $host = 'localhost', 94 | string $port = '5432' 95 | ) { 96 | $this->_connected = false; 97 | 98 | $user = empty($user) ? $this->database->getUser() : $user; 99 | $password = empty($password) ? $this->database->getPassword() : $password; 100 | $name = empty($name) ? $this->database->getName() : $name; 101 | $host = ($host != 'localhost') ? $host : $this->database->getHost(); 102 | $port = ($port != '5432') ? $port : $this->database->getPort(); 103 | 104 | $connect_string = "host=" . $host . " port=" . $port . " dbname=" . $name . " user=" . $user . " password=" . $password; 105 | 106 | // Try to establish the server database handle 107 | if (!$this->dbh = \pg_connect($connect_string, \PGSQL_CONNECT_FORCE_NEW)) { 108 | $this->register_error(\FAILED_CONNECTION . ' in ' . __FILE__ . ' on line ' . __LINE__); 109 | } else { 110 | $this->_connected = true; 111 | } 112 | 113 | return $this->_connected; 114 | } // connect 115 | 116 | /** 117 | * Format a mySQL string correctly for safe mySQL insert 118 | * (no matter if magic quotes are on or not) 119 | * 120 | * @param string $str 121 | * @return string 122 | */ 123 | public function escape(string $str) 124 | { 125 | return \pg_escape_string(\stripslashes($str)); 126 | } // escape 127 | 128 | /** 129 | * Return PostgreSQL specific system date syntax 130 | * i.e. Oracle: SYSDATE Mysql: NOW() 131 | * 132 | * @return string 133 | */ 134 | public function sysDate() 135 | { 136 | return 'NOW()'; 137 | } 138 | 139 | /** 140 | * Creates a prepared query, binds the given parameters and returns the result of the executed 141 | * 142 | * @param string $query 143 | * @param array $param 144 | * @return bool|mixed 145 | */ 146 | public function query_prepared(string $query, array $param = null) 147 | { 148 | $result = @\pg_query_params($this->dbh, $query, $param); 149 | return ($this->shortcutUsed) ? $result : $this->processQueryResult($query, $result); 150 | } 151 | 152 | /** 153 | * Perform post processing on SQL query call 154 | * 155 | * @param string $query 156 | * @param mixed $result 157 | * @return bool|void 158 | */ 159 | private function processQueryResult(string $query, $result = null) 160 | { 161 | $this->shortcutUsed = false; 162 | 163 | if (!empty($result)) 164 | $this->result = $result; 165 | 166 | try { 167 | // If there is an error then take note of it.. 168 | if ($str = @\pg_last_error($this->dbh)) { 169 | return $this->register_error($str); 170 | } 171 | } catch (\Throwable $ex) { 172 | return $this->register_error($ex->getMessage()); 173 | } 174 | 175 | // Query was an insert, delete, update, replace 176 | $this->is_insert = false; 177 | if (\preg_match("/^(insert|delete|update|replace)\s+/i", $query)) { 178 | $this->is_insert = true; 179 | 180 | if (\is_bool($this->result)) 181 | return false; 182 | 183 | $this->_affectedRows = @\pg_affected_rows($this->result); 184 | 185 | // Take note of the insert_id 186 | if (\preg_match("/^(insert|replace)\s+/i", $query)) { 187 | //$this->insert_id = @postgresql_insert_id($this->dbh); 188 | //$this->insert_id = pg_last_oid($this->result); 189 | 190 | // Thx. Rafael Bernal 191 | $insert_query = \pg_query("SELECT lastval();"); 192 | $insert_row = \pg_fetch_row($insert_query); 193 | $this->insertId = $insert_row[0]; 194 | } 195 | 196 | // Return number for rows affected 197 | $this->return_val = $this->_affectedRows; 198 | 199 | if (\preg_match("/returning/smi", $query)) { 200 | while ($row = @\pg_fetch_object($this->result)) { 201 | $return_affected[] = $row; 202 | } 203 | $this->return_val = $return_affected; 204 | } 205 | } else { 206 | // Query was a select 207 | $num_rows = 0; 208 | //may be needed but my tests did not 209 | if ($this->result) { 210 | // Take note of column info 211 | $i = 0; 212 | while ($i < @\pg_num_fields($this->result)) { 213 | $this->colInfo[$i] = new \stdClass(); 214 | $this->colInfo[$i]->name = \pg_field_name($this->result, $i); 215 | $this->colInfo[$i]->type = \pg_field_type($this->result, $i); 216 | $this->colInfo[$i]->size = \pg_field_size($this->result, $i); 217 | $i++; 218 | } 219 | 220 | /** 221 | * Store Query Results 222 | * while ( $row = @pg_fetch_object($this->result, $i, PGSQL_ASSOC) ) doesn't work? donno 223 | * while ( $row = @pg_fetch_object($this->result,$num_rows) ) does work 224 | */ 225 | while ($row = @\pg_fetch_object($this->result)) { 226 | // Store results as an objects within main array 227 | $this->lastResult[$num_rows] = $row; 228 | $num_rows++; 229 | } 230 | 231 | @\pg_free_result($this->result); 232 | } 233 | // Log number of rows the query returned 234 | $this->numRows = $num_rows; 235 | 236 | // Return number of rows selected 237 | $this->return_val = $this->numRows; 238 | } 239 | } 240 | 241 | /** 242 | * Perform PostgreSQL query and try to determine result value 243 | * 244 | * @param string 245 | * @param bool 246 | * @return bool|mixed 247 | */ 248 | public function query(string $query, bool $use_prepare = false) 249 | { 250 | $param = []; 251 | if ($use_prepare) { 252 | $param = $this->prepareValues(); 253 | } 254 | 255 | // check for ezQuery placeholder tag and replace tags with proper prepare tag 256 | if (!empty($param) && \is_array($param) && ($this->isPrepareOn()) && (\strpos($query, \_TAG) !== false)) { 257 | foreach ($param as $i => $value) { 258 | $parameterized = $i + 1; 259 | $needle = \_TAG; 260 | $pos = \strpos($query, $needle); 261 | if ($pos !== false) { 262 | $query = \substr_replace($query, '$' . $parameterized, $pos, \strlen($needle)); 263 | } 264 | } 265 | } 266 | 267 | // Initialize return 268 | $this->return_val = 0; 269 | 270 | // Flush cached values.. 271 | $this->flush(); 272 | 273 | // For reg expressions 274 | $query = \trim($query); 275 | 276 | // Log how the function was called 277 | $this->log_query("\$db->query(\"$query\")"); 278 | 279 | // Keep track of the last query for debug.. 280 | $this->lastQuery = $query; 281 | 282 | // Count how many queries there have been 283 | $this->count(true, true); 284 | 285 | // Use core file cache function 286 | if ($cache = $this->get_cache($query)) { 287 | return $cache; 288 | } 289 | 290 | // If there is no existing database connection then try to connect 291 | if (!isset($this->dbh) || !$this->dbh) { 292 | $this->connect( 293 | $this->database->getUser(), 294 | $this->database->getPassword(), 295 | $this->database->getName(), 296 | $this->database->getHost(), 297 | $this->database->getPort() 298 | ); 299 | } 300 | 301 | // Perform the query via std postgresql_query function.. 302 | if (!empty($param) && \is_array($param) && ($this->isPrepareOn())) { 303 | $this->shortcutUsed = true; 304 | $this->result = $this->query_prepared($query, $param); 305 | } else { 306 | try { 307 | $this->result = @\pg_query($this->dbh, $query); 308 | } catch (\Throwable $ex) { 309 | // 310 | } 311 | } 312 | 313 | if ($this->processQueryResult($query) === false) { 314 | if ($this->isTransactional) 315 | throw new \Exception($this->getLastError()); 316 | 317 | return false; 318 | } 319 | 320 | // disk caching of queries 321 | $this->store_cache($query, $this->is_insert); 322 | 323 | // If debug ALL queries 324 | $this->trace || $this->debugAll ? $this->debug() : null; 325 | 326 | return $this->return_val; 327 | } // query 328 | 329 | /** 330 | * Close the database connection 331 | */ 332 | public function disconnect() 333 | { 334 | if ($this->dbh) { 335 | \pg_close($this->dbh); 336 | $this->_connected = false; 337 | } 338 | } 339 | 340 | /** 341 | * Reset database handle 342 | */ 343 | public function reset() 344 | { 345 | $this->dbh = null; 346 | } 347 | 348 | /** 349 | * Get connection handle 350 | */ 351 | public function handle() 352 | { 353 | return $this->dbh; 354 | } 355 | 356 | /** 357 | * Returns the current database server host 358 | * 359 | * @return string 360 | */ 361 | public function getHost() 362 | { 363 | return $this->database->getHost(); 364 | } // getDBHost 365 | 366 | /** 367 | * Returns the current TCP/IP port 368 | * 369 | * @return string 370 | */ 371 | public function getPort() 372 | { 373 | return $this->database->getPort(); 374 | } // getPort 375 | 376 | /** 377 | * Begin Postgresql Transaction 378 | */ 379 | public function beginTransaction() 380 | { 381 | @\pg_query($this->dbh, "BEGIN"); 382 | $this->isTransactional = true; 383 | } 384 | 385 | public function commit() 386 | { 387 | @\pg_query($this->dbh, "COMMIT"); 388 | $this->isTransactional = false; 389 | } 390 | 391 | public function rollback() 392 | { 393 | @\pg_query($this->dbh, "ROLLBACK"); 394 | $this->isTransactional = false; 395 | } 396 | } // ez_pgsql 397 | -------------------------------------------------------------------------------- /lib/Database/ez_sqlite3.php: -------------------------------------------------------------------------------- 1 | database = $settings; 50 | 51 | // Turn on track errors 52 | ini_set('track_errors', '1'); 53 | 54 | if (!Db::has('ez' . \SQLITE3)) 55 | Db::set('ez' . \SQLITE3, $this); 56 | Db::set('global', $this); 57 | } 58 | 59 | public function settings() 60 | { 61 | return $this->database; 62 | } 63 | 64 | /** 65 | * Try to connect to SQLite database server 66 | */ 67 | public function connect($path = '', $name = '') 68 | { 69 | $this->_connected = false; 70 | 71 | $path = empty($path) ? $this->database->getPath() : $path; 72 | $name = empty($name) ? $this->database->getName() : $name; 73 | 74 | // Try to establish the server database handle 75 | if (!$this->dbh = @new \SQLite3($path . $name)) { 76 | //$this->register_error(\FAILED_CONNECTION); 77 | //$this->show_errors ? \trigger_error(\FAILED_CONNECTION, \E_USER_WARNING) : null; 78 | } else { 79 | $this->connQueries = 0; 80 | $this->_connected = true; 81 | } 82 | 83 | return $this->_connected; 84 | } 85 | 86 | /** 87 | * In the case of SQLite quick_connect is not really needed 88 | * because std. connect already does what quick connect does - 89 | * but for the sake of consistency it has been included 90 | */ 91 | public function quick_connect($path = '', $name = '') 92 | { 93 | return $this->connect($path, $name); 94 | } 95 | 96 | /** 97 | * Format a SQLite string correctly for safe SQLite insert 98 | * (no mater if magic quotes are on or not) 99 | * @param string $str 100 | * @return string 101 | */ 102 | public function escape(string $str) 103 | { 104 | return $this->dbh->escapeString(\stripslashes(\preg_replace("/[\r\n]/", '', $str))); 105 | } 106 | 107 | /** 108 | * Return SQLite specific system date syntax 109 | * i.e. Oracle: SYSDATE Mysql: NOW() 110 | */ 111 | public function sysDate() 112 | { 113 | return 'now'; 114 | } 115 | 116 | // Get the data type of the value to bind. 117 | public function getArgType($arg) 118 | { 119 | switch (\gettype($arg)) { 120 | case 'double': 121 | return \SQLITE3_FLOAT; 122 | case 'integer': 123 | return \SQLITE3_INTEGER; 124 | case 'boolean': 125 | return \SQLITE3_INTEGER; 126 | case 'NULL': 127 | return \SQLITE3_NULL; 128 | case 'string': 129 | return \SQLITE3_TEXT; 130 | case 'string': 131 | return \SQLITE3_TEXT; 132 | default: 133 | $type_error = 'Argument is of invalid type ' . \gettype($arg); 134 | return $this->register_error($type_error); 135 | } 136 | } 137 | 138 | /** 139 | * Creates a prepared query, binds the given parameters and returns the result of the executed 140 | * 141 | * @param string $query 142 | * @param array $param 143 | * @return bool \SQLite3Result 144 | */ 145 | public function query_prepared(string $query, array $param = null) 146 | { 147 | $stmt = $this->dbh->prepare($query); 148 | if (!$stmt instanceof \SQLite3Stmt) { 149 | if ($this->isTransactional) 150 | throw new \Exception($this->getLastError()); 151 | 152 | return false; 153 | } 154 | 155 | foreach ($param as $index => $val) { 156 | // indexing start from 1 in Sqlite3 statement 157 | if (\is_array($val)) { 158 | $ok = $stmt->bindParam($index + 1, $val); 159 | } else { 160 | $ok = $stmt->bindValue($index + 1, $val, $this->getArgType($val)); 161 | } 162 | 163 | if (!$ok) { 164 | $type_error = "Unable to bind param: $val"; 165 | return $this->register_error($type_error); 166 | } 167 | } 168 | 169 | $result = $stmt->execute(); 170 | if ($this->shortcutUsed) 171 | return $result; 172 | 173 | $this->processQueryResult($query, $result); 174 | if ((\strpos($query, 'SELECT ') !== false) || (\strpos($query, 'select ') !== false)) 175 | $this->result->finalize(); 176 | 177 | return $this->return_val; 178 | } 179 | 180 | /** 181 | * Perform post processing on SQL query call 182 | * 183 | * @param string $query 184 | * @param mixed $result 185 | * @param array $param 186 | * @return bool|void 187 | */ 188 | private function processQueryResult(string $query, $result = null) 189 | { 190 | $this->shortcutUsed = false; 191 | 192 | if (!empty($result)) 193 | $this->result = $result; 194 | 195 | $this->count(true, true); 196 | 197 | // If there is an error then take note of it.. 198 | if (@$this->dbh->lastErrorCode()) { 199 | $err_str = $this->dbh->lastErrorMsg(); 200 | return $this->register_error($err_str); 201 | } 202 | 203 | // Query was an insert, delete, update, replace 204 | if (\preg_match("/^(insert|delete|update|replace)\s+/i", $query)) { 205 | $this->_affectedRows = @$this->dbh->changes(); 206 | 207 | // Take note of the insert id 208 | if (\preg_match("/^(insert|replace)\s+/i", $query)) { 209 | $this->insertId = @$this->dbh->lastInsertRowID(); 210 | } 211 | 212 | // Return number of rows affected 213 | $this->return_val = $this->_affectedRows; 214 | 215 | // Query was an select 216 | } else { 217 | // Take note of column info 218 | $i = 0; 219 | $this->colInfo = array(); 220 | while ($i < @$this->result->numColumns()) { 221 | $this->colInfo[$i] = new \stdClass; 222 | $this->colInfo[$i]->name = $this->result->columnName($i); 223 | $this->colInfo[$i]->type = null; 224 | $this->colInfo[$i]->max_length = null; 225 | $i++; 226 | } 227 | 228 | // Store Query Results 229 | $num_rows = 0; 230 | while ($row = @$this->result->fetchArray(\SQLITE3_ASSOC)) { 231 | // Store result as an objects within main array 232 | $obj = (object) $row; //convert to object 233 | $this->lastResult[$num_rows] = $obj; 234 | $num_rows++; 235 | } 236 | 237 | // Log number of rows the query returned 238 | $this->numRows = $num_rows; 239 | 240 | // Return number of rows selected 241 | $this->return_val = $this->numRows; 242 | } 243 | } 244 | 245 | /** 246 | * Perform SQLite query and try to determine result value 247 | * Basic Query - see docs for more detail 248 | * @param string 249 | * @param bool 250 | * @return bool|mixed 251 | */ 252 | public function query(string $query, bool $use_prepare = false) 253 | { 254 | $param = []; 255 | if ($use_prepare) { 256 | $param = $this->prepareValues(); 257 | } 258 | 259 | // check for ezQuery placeholder tag and replace tags with proper prepare tag 260 | $query = \str_replace(\_TAG, '?', $query); 261 | 262 | // For reg expressions 263 | $query = \str_replace("/[\n\r]/", '', \trim($query)); 264 | 265 | // initialize return 266 | $this->return_val = 0; 267 | 268 | // Flush cached values.. 269 | $this->flush(); 270 | 271 | // Log how the function was called 272 | $this->log_query("\$db->query(\"$query\")"); 273 | 274 | // Keep track of the last query for debug.. 275 | $this->lastQuery = $query; 276 | 277 | // If there is no existing database connection then try to connect 278 | if (!isset($this->dbh) || !$this->dbh) { 279 | $this->connect($this->database->getPath(), $this->database->getName()); 280 | } 281 | 282 | // Perform the query via std SQLite3 query or SQLite3 prepare function.. 283 | if (!empty($param) && \is_array($param) && ($this->isPrepareOn())) { 284 | $this->shortcutUsed = true; 285 | $this->result = $this->query_prepared($query, $param); 286 | } else { 287 | $this->result = $this->dbh->query($query); 288 | } 289 | 290 | if ($this->processQueryResult($query) === false) { 291 | if ($this->isTransactional) 292 | throw new \Exception($this->getLastError()); 293 | 294 | return false; 295 | } 296 | 297 | if (!empty($param) && \is_array($param) && $this->isPrepareOn()) 298 | $this->result->finalize(); 299 | 300 | // If debug ALL queries 301 | $this->trace || $this->debugAll ? $this->debug() : null; 302 | 303 | return $this->return_val; 304 | } 305 | 306 | /** 307 | * Close the database connection 308 | */ 309 | public function disconnect() 310 | { 311 | if ($this->dbh) { 312 | $this->dbh = null; 313 | $this->_connected = false; 314 | } 315 | } 316 | 317 | /** 318 | * Reset database handle 319 | */ 320 | public function reset() 321 | { 322 | $this->dbh = null; 323 | } 324 | 325 | /** 326 | * Get connection handle 327 | */ 328 | public function handle() 329 | { 330 | return $this->dbh; 331 | } 332 | 333 | /** 334 | * Begin sqlite3 Transaction 335 | */ 336 | public function beginTransaction() 337 | { 338 | $this->dbh->exec('BEGIN;'); 339 | $this->isTransactional = true; 340 | } 341 | 342 | public function commit() 343 | { 344 | $this->dbh->exec('COMMIT;'); 345 | $this->isTransactional = false; 346 | } 347 | 348 | public function rollback() 349 | { 350 | $this->dbh->exec('ROLLBACK;'); 351 | $this->isTransactional = false; 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /lib/Database/ez_sqlsrv.php: -------------------------------------------------------------------------------- 1 | 'bigint', -7 => 'bit', 1 => 'char', 91 => 'date', -155 => 'datetimeoffset', 6 => 'float', -4 => 'image', 4 => 'int', -8 => 'nchar', 25 | -10 => 'ntext', 2 => 'numeric', -9 => 'nvarchar', 7 => 'real', 5 => 'smallint', -1 => 'text', -154 => 'time', -6 => 'tinyint', -151 => 'udt', 26 | -11 => 'uniqueidentifier', -3 => 'varbinary', 12 => 'varchar', -152 => 'xml', 27 | ); 28 | 29 | /** 30 | * Database connection handle 31 | * @var resource 32 | */ 33 | private $dbh; 34 | 35 | /** 36 | * Query result 37 | * @var mixed 38 | */ 39 | private $result; 40 | 41 | /** 42 | * Database configuration setting 43 | * @var ConfigInterface 44 | */ 45 | private $database; 46 | 47 | public function __construct(ConfigInterface $settings = null) 48 | { 49 | if (empty($settings)) { 50 | throw new Exception(\MISSING_CONFIGURATION); 51 | } 52 | 53 | parent::__construct(); 54 | $this->database = $settings; 55 | 56 | if (!Db::has('ez' . \SQLSRV)) 57 | Db::set('ez' . \SQLSRV, $this); 58 | Db::set('global', $this); 59 | } 60 | 61 | public function settings() 62 | { 63 | return $this->database; 64 | } 65 | 66 | /** 67 | * Short hand way to connect to sqlsrv database server 68 | * and select a sqlsrv database at the same time 69 | */ 70 | public function quick_connect($user = '', $password = '', $name = '', $host = 'localhost') 71 | { 72 | $return_val = false; 73 | $this->_connected = false; 74 | if (!$this->connect($user, $password, $name, $host)); 75 | else { 76 | $return_val = true; 77 | $this->_connected = true; 78 | } 79 | return $return_val; 80 | } 81 | 82 | /** 83 | * Try to connect to sqlsrv database server 84 | */ 85 | public function connect($user = '', $password = '', $name = '', $host = 'localhost') 86 | { 87 | $this->_connected = false; 88 | 89 | $user = empty($user) ? $this->database->getUser() : $user; 90 | $password = empty($password) ? $this->database->getPassword() : $password; 91 | $name = empty($name) ? $this->database->getName() : $name; 92 | $host = ($host != 'localhost') ? $this->database->getHost() : $host; 93 | 94 | // Blank user assumes Windows Authentication 95 | if ($this->isSecure) { 96 | $connectionOptions = array( 97 | "UID" => $user, 98 | "PWD" => $password, 99 | "Database" => $name, 100 | "ReturnDatesAsStrings" => true, 101 | "Encrypt" => true, 102 | "TrustServerCertificate" => true, 103 | ); 104 | } else { 105 | $connectionOptions = array( 106 | "UID" => $user, 107 | "PWD" => $password, 108 | "Database" => $name, 109 | "ReturnDatesAsStrings" => true, 110 | ); 111 | } 112 | 113 | // Try to establish the server database handle 114 | if (($this->dbh = @\sqlsrv_connect($host, $connectionOptions)) === false) { 115 | $this->register_error(\FAILED_CONNECTION . ' in ' . __FILE__ . ' on line ' . __LINE__); 116 | } else { 117 | $this->_connected = true; 118 | $this->connQueries = 0; 119 | } 120 | 121 | return $this->_connected; 122 | } 123 | 124 | /** 125 | * Return sqlsrv specific system date syntax 126 | * i.e. Oracle: SYSDATE sqlsrv: NOW(), MS-SQL : getDate() 127 | * 128 | * The SQLSRV drivers pull back the data into a Date class. Converted 129 | * it to a string inside of SQL in order to prevent this from occurring 130 | * ** make sure to use " AS