/** * Generate an ID that is unique in a table * @method uniqueId * @param {string} $table The name of the table * @param {string} $field The name of the field to check for uniqueness. * You should probably have an index starting with this field. * @param {array} [$where=array()] You can indicate conditions here to limit the search for * an existing value. The result is an id that is unique within a certain partition. * @param {array} [$options=array()] Optional array used to override default options: * @param {integer} [$options.length=8] The length of the ID to generate, after the prefix. * @param {string} [$options.characters='abcdefghijklmnopqrstuvwxyz'] All the characters from which to construct the id * @param {string} [$options.prefix=''] The prefix to prepend to the unique id. * @param {callable} [$options.filter] * The name of a function that will take the generated string and * check it. The filter function can modify the string by returning another string, * or simply reject the string by returning false, in which another string will be */ function uniqueId($table, $field, $where = array(), $options = array()) { $length = 8; $characters = 'abcdefghijklmnopqrstuvwxyz'; $prefix = ''; extract($options); $count = strlen($characters); do { $id = $prefix; for ($i = 0; $i < $length; ++$i) { $id .= $characters[mt_rand(0, $count - 1)]; } if (!empty($options['filter'])) { $ret = Q::call($options['filter'], array(compact('id', 'table', 'field', 'where', 'options'))); if ($ret === false) { continue; } else { if ($ret) { $id = $ret; } } } $q = $this->select($field, $table)->where(array($field => $id)); if ($where) { $q->andWhere($where); } $rows = $q->limit(1)->fetchAll(); } while ($rows); return $id; }
/** * Gets the SQL that would be executed with the execute() method. See {{#crossLink "Db_Query_Mysql/build"}}{{/crossLink}}. * @method getSQL * @param {callable} [$callback=null] If not set, this function returns the generated SQL string. * If it is set, this function calls $callback, passing it the SQL string, and then returns $this, for chainable interface. * @param {boolean} [$template=false] * @return {string|Db_Query} Depends on whether $callback is set or not. * @throws {Exception} This function calls self::build() */ function getSQL($callback = null, $template = false) { if (!$template) { if (isset($this->db->dbname)) { $this->replacements['{$dbname}'] = $this->db->dbname; } if (isset($this->db->prefix)) { $this->replacements['{$prefix}'] = $this->db->prefix; } } $repres = $this->build(); $keys = array_keys($this->parameters); usort($keys, array(__CLASS__, 'replaceKeysCompare')); foreach ($keys as $key) { $value = $this->parameters[$key]; if ($value instanceof Db_Expression) { $value2 = $value; } else { if (!isset($value)) { $value2 = "NULL"; } else { $value2 = $this->reallyConnect()->quote($value); } } if (is_numeric($key) and intval($key) == $key) { // replace one of the question marks if (false !== ($pos = strpos($repres, '?'))) { $repres = substr($repres, 0, $pos) . (string) $value2 . substr($repres, $pos + 1); } } else { // we don't use $repres = str_replace(":$key", "$value2", $repres); // because we want to replace only one occurrence if (false !== ($pos = strpos($repres, ":{$key}"))) { $pos2 = $pos + strlen(":{$key}"); $repres = substr($repres, 0, $pos) . (string) $value2 . substr($repres, $pos2); } } } foreach ($this->replacements as $k => $v) { $repres = str_replace($k, $v, $repres); } if (isset($callback)) { $args = array($repres); Q::call($callback, $args); return $this; } return $repres; }