Overview

Namespaces

  • None
  • PHP

Classes

  • AbstractTest
  • AMysql
  • AMysql_Abstract
  • AMysql_Expr
  • AMysql_Iterator
  • AMysql_Profiler
  • AMysql_Select
  • AMysql_Statement
  • AMysql_TestCase
  • ExceptionTest
  • ExprTest
  • IteratorTest
  • SelectTest
  • StatementTest

Exceptions

  • AMysql_Exception
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php /* vim: set expandtab : */
  2: /**
  3:  * Class for making custom expressions for AMysql value binding.
  4:  * This is what you should use to be able to add specific kinds
  5:  * of purposely unquoted, non-numeric values into prepared
  6:  * statements, such as being able to call mysql functions to
  7:  * set values.
  8:  *
  9:  * This class can be extended and is recommended to do so if you want
 10:  * custom expressions; in which case you would have to manually
 11:  * instatiate that class each time, rather than using AMysql::expr()
 12:  *
 13:  * Expression codes 0-999 should be considered reserved to this class;
 14:  * if you extend this class, please use at least 1000 as expression code ints.
 15:  *
 16:  * Visit https://github.com/amcsi/amysql
 17:  * @author Szerémi Attila
 18:  * @created 2011.06.10. 13:26:56  
 19:  * @license     MIT License; http://www.opensource.org/licenses/mit-license.php
 20:  **/ 
 21: class AMysql_Expr
 22: {
 23: 
 24:     public $prepared;
 25: 
 26:     public $amysql;
 27: 
 28:     /**
 29:      * Literal string
 30:      *
 31:      * e.g. $currentTimestampBind = new AMysql_Expr(
 32:      *      AMysql_Expr::LITERAL, 'CURRENT_TIMESPAMP'
 33:      *  );
 34:      *  // or
 35:      *  $currentTimestampBind = new AMysql_Expr('CURRENT_TIMESTAMP');
 36:      **/         
 37:     const LITERAL = 0;
 38:     const EXPR_LITERAL = 0;
 39: 
 40:     /**
 41:      * IN() function. In this case, the 2nd parameter is the table name, the
 42:      * third is the array of values
 43:      *
 44:      * e.g.
 45:      *  $idIn = new AMysql_Expr(AMysql_Expr::COLUMN_IN, 'id', array (
 46:      *      '3', '4', '6'
 47:      *  ));
 48:      **/         
 49:     const COLUMN_IN = 1;
 50:     const EXPR_COLUMN_IN = 1;
 51: 
 52:     /**
 53:      * Escapes wildcards for a LIKE statement.
 54:      * The second parameter has to be the string to escape, and
 55:      * the third is optional, and is the sprintf format of the string,
 56:      * where literal wildcards should appear. The default is %%%s%%,
 57:      * where the input of "something" will result in:
 58:      *  "'%something%' ESCAPE '='"
 59:      **/         
 60:     const ESCAPE_LIKE = 2;
 61: 
 62:     /**
 63:      * Escapes a table name and encloses it in quotes. The second parameter is the table name. 
 64:      */
 65:     const ESCAPE_TABLE = 3;
 66:     const EXPR_TABLE = 3;
 67: 
 68:     /**
 69:      * Escapes a column name and encloses it in quotes. The second parameter is the column name. 
 70:      */
 71:     const ESCAPE_COLUMN = 4;
 72:     const EXPR_COLUMN = 4;
 73: 
 74:     /**
 75:      * @constructor
 76:      * This constructor accepts different parameters in different cases.
 77:      * Before everything, if the first parameter is an AMysql instance, it
 78:      * is saved, and is shifted from the arguments array, and the following
 79:      * applies in either case:
 80:      * The first parameter is mandatory: the one that gives the type of
 81:      * expression. The types of expressions can be found as constants on this
 82:      * class, and their documentation can be found above each constant type
 83:      * declaration.
 84:      *
 85:      * @params ...$variadic
 86:      * 
 87:      * In case of a literal string, you can just pass the literal string as
 88:      * the only parameter.
 89:      **/         
 90:     public function __construct(/* args */)
 91:     {
 92:         $args = func_get_args();
 93:         if ($args[0] instanceof AMysql_Abstract) {
 94:             $this->amysql = array_shift($args);
 95:         }
 96:         if ($args) {
 97:             call_user_func_array(array($this, 'set'), $args);
 98:         }
 99:     }
100: 
101:     public function set()
102:     {
103:         $args = func_get_args();
104:         // literal
105:         if (is_string($args[0])) {
106:             $prepared = $args[0];
107:         } else {
108:             $prepared = $this->setByArray($args);
109:         }
110:         $this->prepared = $prepared;
111:     }
112: 
113:     /**
114:      * This method performs the logic of determining what the
115:      * expression should result in.
116:      * When extending this class, it is recommended that you
117:      * override this method, determine whether the expression code
118:      * is something that you want to handle, otherwise call and return
119:      * the parent's setByArray() method
120:      * 
121:      * @param array $args           The first index should contain the type
122:      *                              of expression to use, the rest depends on
123:      *                              the type of expression. See the class
124:      *                              constants for available types.
125:      * @access protected
126:      * @return string               The literal string to use
127:      */
128:     protected function setByArray(array $args)
129:     {
130:         switch ($args[0]) {
131:             case self::EXPR_LITERAL:
132:                 $prepared = $args[1];
133:                 break;
134:             case self::EXPR_COLUMN_IN:
135:                 $prepared = '';
136:                 if ($args[2]) {
137:                     foreach ($args[2] as &$val) {
138:                         $val = $this->amysql->escape($val);
139:                     }
140:                     $prepared = ' ' . $this->escapeColumn($args[1]) . ' IN ' .
141:                         '(' . join(', ', $args[2]) . ') ';
142:                 } else {
143:                     // If the array is empty, don't break the WHERE syntax
144:                     $prepared = 0;
145:                 }
146:                 break;
147:             case self::ESCAPE_LIKE:
148:                 $format = '%%%s%%';
149:                 if (!empty($args[2])) {
150:                     $format = $args[2];
151:                 }
152:                 $likeEscaped = AMysql_Abstract::escapeLike($args[1]);
153:                 $formatted = sprintf($format, $likeEscaped);
154:                 if ($this->amysql) {
155:                     if ('mysqli' == $this->amysql->isMysqli) {
156:                         $escaped = $this->amysql->link->real_escape_string(
157:                             $formatted
158:                         );
159:                     } else {
160:                         $escaped = mysql_real_escape_string(
161:                             $formatted,
162:                             $this->amysql->link
163:                         );
164:                     }
165:                 } else {
166:                     $escaped = mysql_real_escape_string($formatted);
167:                 }
168:                 $prepared = "'$escaped'";
169:                 $prepared .= " ESCAPE '='";
170:                 break;
171:             case self::ESCAPE_TABLE:
172:                 $prepared = $this->amysql->escapeTable($args[1]);
173:                 break;
174:             case self::ESCAPE_COLUMN:
175:                 $prepared = $this->amysql->escapeColumn($args[1]);
176:                 break;
177:             default:
178:                 throw new Exception("No such expression type: `$args[0]`.");
179:                 break;
180:         }
181:         return $prepared;
182:     }
183: 
184:     public function escapeTable($table)
185:     {
186:         if ($this->amysql instanceof AMysql_Abstract) {
187:             return $this->amysql->escapeTable($table);
188:         }
189:         return AMysql_Abstract::escapeIdentifier($table);
190:     }
191: 
192:     public function escapeColumn($column)
193:     {
194:         if ($this->amysql instanceof AMysql_Abstract) {
195:             return $this->amysql->escapeColumn($column);
196:         }
197:         return AMysql_Abstract::escapeIdentifier($column);
198:     }
199: 
200:     public function toString()
201:     {
202:         if (!isset($this->prepared)) {
203:             throw new Exception("No prepared string for mysql expression.");
204:         }
205:         return (string) $this->prepared;
206:     }
207: 
208:     /**
209:      * Returns the literal string this expression should resolve to.
210:      * 
211:      * @access public
212:      * @return string
213:      */
214:     public function __toString()
215:     {
216:         return (string) $this->toString();
217:     }
218: } 
219: 
API documentation generated by ApiGen 2.8.0