PHPAPIExtension
PHP API Extension
get_basename, get_dirname
if (! function_exists('get_basename')) { /** * Get the basename of a path * * PHP's basename works as * 'Page/' => 'Page', 'Page/a' => 'a', 'Page' => 'Page' * This function works as * 'Page/' => '', 'Page/a' => 'a', 'Page' => 'Page' * * @param string $path * @param string $suffix cut suffix of the basename * @return string basename */ function get_basename($path, $suffix = '') { if (($pos = strrpos($path, '/')) !== false) { $basename = substr($path, $pos + 1); } else { $basename = $path; } if (($pos = strrpos($basename, $suffix)) !== false) { $basename = substr($basename, 0, $pos); } return $basename; } }
if (! function_exists('get_dirname')) { /** * Get the dirname of a path * * PHP's dirname works as * 'Page/' => '.', 'Page/a' => 'Page', 'Page' => '.' * This function works as * 'Page/' => 'Page', 'Page/a' => 'Page', 'Page' => '' * * @param string $path * @return string dirname */ function get_dirname($path) { if (($pos = strrpos($path, '/')) !== false) { return substr($path, 0, $pos); } else { return ''; } } }
unhtmlspecialchars, glue_str, glue_url, realurl, unrealpath
if (! function_exists('unhtmlspecialchars')) { /** * Undo htmlspecialchars * * @access public * @param string * @return string Undone htmlspecialchars * @see htmlspecialchars() * @example unhtmlspecialchars.php */ function &unhtmlspecialchars($string) { $string = str_replace('&' , '&' , $string); $string = str_replace(''', '\'', $string); $string = str_replace('"', '"', $string); $string = str_replace('<' , '<' , $string); $string = str_replace('>' , '>' , $string); return $string; } }
/** * reverse parse_str * * Note: parse_str does rawurldecode and convert . into _ for keys * * @access public * @param array $queries outputs by parse_str * @return string reversed parse_str * @see parse_str() */ function glue_str($queries) { if (! is_array($queries)) return false; $url_query = array(); foreach ($queries as $key => $value) { $arg = ($value === '') ? rawurlencode($key) : rawurlencode($key) . '=' . rawurlencode($value); array_push($url_query, $arg); } return implode('&', $url_query); }
if (! function_exists('glue_url')) { /** * reverse parse_url * * @access public * @param array $parsed outputs by parse_url * @return string reversed parse_url * @see parse_url() */ function glue_url($parsed) { if (!is_array($parsed)) return false; $uri = isset($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '' : '//') : ''; $uri .= isset($parsed['user']) ? $parsed['user'].(isset($parsed['pass']) ? ':'.$parsed['pass'] : '').'@' : ''; $uri .= isset($parsed['host']) ? $parsed['host'] : ''; $uri .= isset($parsed['port']) ? ':'.$parsed['port'] : ''; if(isset($parsed['path'])) { $uri .= (substr($parsed['path'], 0, 1) == '/') ? $parsed['path'] : ('/'.$parsed['path']); } $uri .= isset($parsed['query']) ? '?'.$parsed['query'] : ''; $uri .= isset($parsed['fragment']) ? '#'.$parsed['fragment'] : ''; return $uri; } }
uses glue_url
if (! function_exists('realurl')) { /** * Get absolute URL * * @access public * @param string $base base url * @param string $url relative url * @return string absolute url * @see parse_url() * @see realpath() * @uses glue_url() */ function realurl($base, $url) { if (! strlen($base)) return $url; if (! strlen($url)) return $base; if (preg_match('!^[a-z]+:!i', $url)) return $url; $base = parse_url($base); if ($url{0} == "#") { // fragment $base['fragment'] = substr($url, 1); return glue_url($base); } unset($base['fragment']); unset($base['query']); if (substr($url, 0, 2) == "//") { // FQDN $base = array( 'scheme'=>$base['scheme'], 'path'=>substr($url,2), ); return glue_url($base); } elseif ($url{0} == "/") { // absolute path reference $base['path'] = $url; } else { // relative path reference $path = explode('/', $base['path']); $url_path = explode('/', $url); // drop file from base array_pop($path); // append url while removing "." and ".." from // the directory portion $end = array_pop($url_path); foreach ($url_path as $segment) { if ($segment == '.') { // skip } elseif ($segment == '..' && $path && $path[sizeof($path)-1] != '..') { array_pop($path); } else { $path[] = $segment; } } // remove "." and ".." from file portion if ($end == '.') { $path[] = ''; } elseif ($end == '..' && $path && $path[sizeof($path)-1] != '..') { $path[sizeof($path)-1] = ''; } else { $path[] = $end; } $base['path'] = join('/', $path); } return glue_url($base); } }
ToDo: look unrealpath http://us.php.net/manual/ja/function.realpath.php
if (! function_exists('unrealpath')) { /** * Get relative path from a source path to a target path * * @static * @param string $source * @param string $target * @return string */ function unrealpath($source, $target) { $source_dirs = explode('/', $source); $target_dirs = explode('/', $target); foreach ($source_dirs as $i => $source_dir) { if ($source_dirs[$i] == $target_dirs[$i]) { unset($source_dirs[$i]); unset($target_dirs[$i]); } else { break; } } $source = implode('/', $source_dirs); $target = implode('/', $target_dirs); $relative = str_repeat('../', substr_count($source, '/')); return $relative . $target; } }
mythrow, mycatch
/* * Error Handling in PHP4 * throw an error message * * PHP5) * function a_function_throw_inside() * { * throw(new Exception('Throw Error')); * } * try { * a_function_throw_inside(); * echo 'Never Executed'; * } catch (Exception $e) { * echo $e->getMessage() . "\n"; * } * * This) * function a_function_throw_inside() * { * sonots::mythrow('Throw Error'); return; * } * do { * a_function_throw_inside(); * if (sonots::mycatch()) break; // burdensome * echo 'Never Executed'; * } while (FALSE); * if (sonots::mycatch()) { * echo sonots::mycatch(); * } * * @param string $errmsg * @global $php_errmsg * @return void */ function mythrow($errmsg) { set_error_handler(create_function('$errno, $errstr, $errfile, $errline', '$GLOBALS["php_errmsg"] = $errstr;')); @trigger_error($errmsg, E_USER_ERROR); restore_error_handler(); } /** * Error Handling in PHP4 * catch an error message * * @return string $errmsg * @global $php_errmsg */ function mycatch() { global $php_errmsg; return $php_errmsg; }
set_members, get_members
/** * Set members into array of class objects recursively * * @access static * @param array $objects array of objects * @param string $name member name * @param array $members array of member variables, * size and keys must be same with $objects. * @return void */ function set_members(&$objects, $name, &$members) { foreach ($objects as $i => $object) { $objects[$i]->$name = $members[$i]; } }
/** * Get specific members from array of class objects * * @access static * @param array $objects array of objects * @param string $name member name * @return array array of members, keys are preserved. */ function &get_members(&$objects, $name) { $array = array(); foreach ($objects as $i => $object) { $array[$i] = $object->$name; } return $array; }
parse_interval, conv_interval
/** * Parse an interval num string * * Example) * 1:5 means 1st to 5th returns array(0, 5) * 2: means 2nd to end returns array(1, NULL) * :3 means 1st to 2rd returns array(0, 3) * 4 means 4th returns array(3, 1) * -5: means last 5th to end returns array(-5, NULL) * :-5 means 1st to last 5th returns array(0, -4) * 1+2 means 1st to 3rd returns array(0, 3) * * @access static * @param string $interval * @return mixed array($offset, $length) or NULL * @see array_slice, array_splice */ function parse_interval($interval) { $mini = 1; if (strpos($interval, ':') !== FALSE) { list($min, $max) = explode(':', $interval, 2); if (is_numeric($min)) { $min = (int)$min; } else { $min = $mini; } if (is_numeric($max)) { $max = (int)$max; $len = $max - $mini + 1; if ($len == -1) $len = NULL; if ($len < 0) $len++; } else { $len = NULL; } } elseif (strpos($interval, '+') !== FALSE) { list($min, $len) = explode("+", $interval, 2); if (is_numeric($min)) { $min = (int)$min; } else { $min = $mini; } if (is_numeric($len)) { $len = (int)$len + 1; } else { $len = NULL; } } else { if (is_numeric($interval)) { $min = (int)$interval; $len = 1; } else { return NULL; //$min = $mini; //$max = $maxi; } } if ($min > 0) $min--; return array($min, $len); } /* print_r(parse_interval('1:5')); print_r(parse_interval('2:')); print_r(parse_interval(':3')); print_r(parse_interval('4')); print_r(parse_interval('-5:')); print_r(parse_interval(':-5')); print_r(parse_interval('1+2')); list($offset, $length) = parse_interval('2:-1'); if (is_null($length)) { print_r(array_slice(range(1,10), $offset)); } else { print_r(array_slice(range(1,10), $offset, $length)); } */
/** * Convert ($offset, $length) interval form * to ($start, $end) interval form. * * Example) * Assume min = 1, max = 10 * array(0, 5) to array(1, 5) * array(1, NULL) to array(2, 10) * array(3, 1) to array(4, 4) * array(-5, NULL) to array(6, 10) * array(0, -4) to array(1, 6) * * @access static * @param int $offset * @param int $length * @param int $min * @param int $max * @return array array($start, $end) * @see range */ function conv_interval($offset, $length, $min, $max) { // minus means index from back if ($offset < 0) { $start = $offset + $max + 1; } else { $start = $offset + $min; } // minus means length from back if ($length < 0) { $end = $length + $max; } elseif ($length > 0) { $end = $length + $start - 1; } else { $end = $max; } // make sure if (! isset($start) || $start < $min) { $start = $min; } if (! isset($end) || $end > $max) { $end = $max; } return array($start, $end); } /* print_r(conv_interval(0, 5, 1, 10)); print_r(conv_interval(1, NULL, 1, 10)); print_r(conv_interval(3, 1, 1, 10)); print_r(conv_interval(-5, NULL, 1, 10)); print_r(conv_interval(0, -4, 1, 10)); */
array_to_string, string_to_array, trim_array
if (! function_exists('array_to_string')) { /** * Convert an array to a string * * Example * * $arr = array('A', 'B', 'indC' => 'C', array('D', 'E'), 'indF'=>'F'); * echo array_to_string($arr); * * Output: * A,B,indC:C,(D,E),indF:F * * @access static * @param array $array * @param string $hashsep A character to be used as a hash key and val seperator * @param string $elemsep A character to be used as a elememt separator * @param string $openarray A character to be used as an open bracket of an array * @param string $closearray A character to be used as a close bracket of an array * @return string * @see string_to_array */ function array_to_string($array, $hashsep = ':', $elemsep = ',', $openarray = '(', $closearray = ')') { $string = ""; foreach($array as $key => $value){ if(is_array($value)){ $value = self::array_to_string($value, $hashsep, $elemsep, $openarray, $closearray); $value = $openarray . $value . $closearray; } else { // escape $value = urlencode($value); } if (is_int($key)) { $string .= $elemsep . $value; } else { $string .= $elemsep . urlencode($key) . $hashsep . $value; } } $string = substr($string, 1); return $string; } }
if (! function_exists('string_to_array')) { /** * Restore a string to an array * * Example * * $string = 'A,B,indC:C,(0:D,1:E),indF:F' * $array = string_to_array($string) * * Output: * array('A', 'B', 'indC' => 'C', array('D', 'E'), 'indF'=>'F'); * * * @param string $string * @param string $hashsep A character to be used as a hash key and val seperator * @param string $elemsep A character to be used as a elememt separator * @param string $openarray A character to be used as an open bracket of an array * @param string $closearray A character to be used as a close bracket of an array * @return array * @see array_to_string */ function string_to_array($string, $hashsep = ':', $elemsep = ',', $openarray = '(', $closearray = ')') { /// parse the first element $result = array(); $hashsep_pos = strpos($string, $hashsep); $elemsep_pos = strpos($string, $elemsep); $openarray_pos = strpos($string, $openarray); // there is a key or not for the 1st element if ($hashsep_pos !== FALSE && ($elemsep_pos === FALSE || $hashsep_pos < $elemsep_pos) && ($openarray_pos === FALSE || $hashsep_pos < $openarray_pos)) { $key = urldecode(substr($string, 0, $hashsep_pos)); $string = trim(substr($string , $hashsep_pos+1)); } else { $key = NULL; } $openarray_pos = strpos($string, $openarray); if ($openarray_pos === FALSE || $openarray_pos > 0) { // hash val is not an array $elemsep_pos = strpos($string, $elemsep); if ($elemsep_pos === FALSE) { $val = urldecode($string); $string = ""; }else{ $val = urldecode(substr($string, 0, $elemsep_pos)); $string = substr($string, $elemsep_pos+1); } } elseif ($openarray_pos == 0) { // hash val is an array $string = substr($string, 1); $num_openarray = 1; // search where is a corresponding closet $string_char_array = str_split($string); for($index = 0; count($string_char_array); $index++) { if ($string_char_array[$index] == $openarray) { $num_openarray++; }else if ($string_char_array[$index] == $closearray) { $num_openarray--; } if ($num_openarray == 0) { break; } } $val = string_to_array(substr($string, 0, $index), $hashsep, $elemsep, $openarray, $closearray); $string = substr($string, $index+2); } if (is_null($key)) { $result[] = $val; } else { $result[$key] = $val; } /// next element if (strlen($string) != 0) { $result = array_merge($result, string_to_array($string, $hashsep, $elemsep, $openarray, $closearray)); } return $result; } }
/** * trim elements of array * * @access static * @param array $array * @param boolean $recursive recursively * @param boolean $trimkey trim key too * @return array */ function trim_array($array, $recursive = FALSE, $trimkey = FALSE) { $outarray = array(); foreach ($array as $key => $val) { unset($array[$key]); // save memory if ($recursive && is_array($val)) { $val = self::trim_array($val, $recursive, $trimkey); } elseif (is_string($val)) { $val = trim($val); } if ($trimkey && is_string($key)) { $key = trim($key); } $outarray[$key] = $val; } return $outarray; }
ereg_grep
if (! function_exists('ereg_grep')) { /** * Grep an array by ereg expression * * @param string $pattern * @param array $input * @param int $flags * @return array */ if (! defined('EREG_GREP_INVERT')) define('EREG_GREP_INVERT', PREG_GREP_INVERT); function &ereg_grep($pattern, $input, $flags = 0) { if ($flag & EREG_GREP_INVERT) { foreach ($input as $i => $string) { if (ereg($pattern, $string)) { unset($input[$i]); // unset rather than stack for memory saving } } } else { foreach ($input as $i => $string) { if (! ereg($pattern, $string)) { unset($input[$i]); } } } return $input; } }
deep_copy, is_ref, (array_deep_copy)
if (! function_exists('deep_copy')) { /** * Deep copy * * PHP Extension * * @param array $source * @return array */ function deep_copy($source) { return unserialize(serialize($source)); } }
if (! function_exists('is_ref')) { /** * is reference? * * PHP Extension * * @param object &$a * @param object &$b * @return boolean */ function is_ref(&$a, &$b){ if(gettype($a) !== gettype($b)) return false; $same = false; if(is_array($a)){ //Look for an unused index in $a $key = uniqid("is_ref_", true); while(isset($a[$key]))$key = uniqid("is_ref_", true); //The two variables differ in content ... They can't be the same if(isset($b[$key])) return false; //The arrays point to the same data if changes are reflected in $b $data = uniqid("is_ref_data_", true); $a[$key] =& $data; //There seems to be a modification ... $same = ((isset($b[$key])) and ($b[$key] === $data)); //Undo our changes ... unset($a[$key]); }elseif(is_object($a)){ //The same objects are required to have equal class names ;-) if(get_class($a) !== get_class($b)) return false; //Look for an unused property in $a $key = uniqid("is_ref_", true); while(isset($a->$key))$key = uniqid("is_ref_", true); //The two variables differ in content ... They can't be the same if(isset($b->$key)) return false; //The arrays point to the same data if changes are reflected in $b $data = uniqid("is_ref_data_", true); $a->$key =& $data; //There seems to be a modification ... $same = ((isset($b->$key)) and ($b->$key === $data)); //Undo our changes ... unset($a->$key); }elseif(is_resource($a)){ if(get_resource_type($a) !== get_resource_type($b))return false; $same = ((string) $var1) === ((string) $var2); }else{ if($a !== $b) return false; //To check for a reference of a variable with simple type //simply store its old value and check against modifications of the second variable ;-) $data = uniqid("is_ref_", true); while($data === $a) $data = uniqid("is_ref_", true); $save = $a; //WE NEED A COPY HERE!!! $a = $data; //Set a to the value of $data (copy) $same = ($a === $b); //Check if $var2 was modified too ... $a = $save; //Undo our changes ... } return $same; } }
old version. Use deep_copy now
if (! function_exists('array_deep_copy')) { /** * Deep copy of an array * * PHP Extension * * @param array &$source * @param array &$target * @param integer $maxdepth maxdepth to deeply copy * @param integer $depth parameter used in recursive call (you will not use) * @uses is_ref */ function array_deep_copy(&$source, &$target, $maxdepth = 50, $depth = 0) { if($depth > $maxdepth) { $target = $source; return; } if(! is_array($target)) { $target = array(); } foreach($source as $k => $v) { if(is_array($v) && ! is_ref($source, $v)) { array_deep_copy($v,$target[$k],$maxdepth,++$depth); } else { $target[$k] = $v; } } } }
Temporary copy of $GLOBALS
$GLOBALS_TMP = array(); array_deep_copy($GLOBALS, $GLOBALS_TMP); // modify $GLOBALS foreach ($GLOBALS as $key => $val) { if ($key !== 'GLOBALS') unset($GLOBALS[$key]); } array_deep_copy($GLOBALS_TMP, $GLOBALS);
No!
$GLOBALS_TMP = array(); foreach ($GLOBALS as $key => $val) { if ($key !== 'GLOBALS') $GLOBALS_TMP[$key] = $val; } // modify $GLOBALS foreach ($GLOBALS as $key => $val) { if ($key !== 'GLOBALS') unset($GLOBALS[$key]); } foreach ($GLOBALS_TMP as $key => $val) { $GLOBALS[$key] = $val; }
was enough.
r_strpos
if (! function_exists('r_strpos')) { /** * Find positions of occurrence of a string * * PHP Extension * * @param string $str * @param string $substr * @return array positions */ function r_strpos($str, $substr) { $r_pos = array(); while(true) { $pos = strpos($str, $substr); if ($pos === false) break; array_push($r_pos, $pos); $str = substr($str, $pos + 1); } return $r_pos; } }
sort_filenames
if (! function_exists('sort_filenames')) { /** * Sort filenames * * This function assures that files under a directory will be * followed by its parent directory as * Foo * Foo/Bar * FooBar * not * Foo * FooBar * Foo/Bar * This function could be useful when filenames include multi-byte words * * @param array &$filenames */ function sort_filenames(&$filenames) { $filenames = str_replace('/', "\0", $filenames); sort($filenames, SORT_STRING); $filenames = str_replace("\0", '/', $filenames); } }
ただのソートでは
$filenames = array( "Hogeほげ", 'Hoge/Hoge', 'Hoge');
が
Hoge Hogeほげ Hoge/Hoge
になってしまう(危険性がある。natsort なら上のような結果になる)。Hoge ディレクトリの次は Hoge ディレクトリ内のファイルが来て欲しい。つまり、
Hoge Hoge/Hoge Hogeほげ
になってほしい。
function sort_dirtree(&$filenames, $sort = 'sort', $sortflag = SORT_STRING) { $filenames = str_replace('/', "\0", $filenames); switch ($sort) { case 'natsort': case 'natcasesort': call_user_func($sort, $filenames); break; default: call_user_func($sort, $filenames, $sortflag); break; } $filenames = str_replace("\0", '/', $filenames); }
うーん、natsort では期待通りにいかない・・・。
$ignorecase
function sort_filenames(&$filenames, $ignorecase = FALSE) { if ($ignorecase) { $tmp = $filenames; foreach (array_keys($filenames) as $i) { if (is_callable('mb_strtolower')) { $filenames[$i] = mb_strtolower($filenames[$i]); } else { $filenames[$i] = strtolower($filenames[$i]); } } print_r($filenames); $filenames = str_replace('/', "\0", $filenames); asort($filenames, SORT_STRING); $j = 0; $ind = array_keys($filenames); $filenames = array(); foreach ($ind as $i) { $filenames[$j++] = $tmp[$i]; } } else { $filenames = str_replace('/', "\0", $filenames); sort($filenames, SORT_STRING); $filenames = str_replace("\0", '/', $filenames); } }
get_existfiles
if (! function_exists('get_existfiles')) { /** * Get list of files in a directory * * PHP Extension * * @access public * @param string $dir Directory Name * @param string $ext File Extension * @param bool $recursive Traverse Recursively * @return array array of filenames * @uses is_dir() * @uses opendir() * @uses readdir() */ function &get_existfiles($dir, $ext = '', $recursive = FALSE) { if (($dp = @opendir($dir)) == FALSE) return FALSE; $pattern = '/' . preg_quote($ext, '/') . '$/'; $dir = ($dir[strlen($dir)-1] == '/') ? $dir : $dir . '/'; $dir = ($dir == '.' . '/') ? '' : $dir; $files = array(); while (($file = readdir($dp)) !== false ) { if($file != '.' && $file != '..' && is_dir($dir . $file) && $recursive) { $files = array_merge($files, get_existfiles($dir . $file, $ext, $recursive)); } else { $matches = array(); if (preg_match($pattern, $file, $matches)) { $files[] = $dir . $file; } } } closedir($dp); return $files; } }
is_includable
if (! function_exists('is_includable')) { /** * Check if file is includable * * @param string $filename * @param boolean $returnpaths return all paths where $filename is includable * @return boolean (or array if $returnpaths is true) */ function is_includable($filename, $returnpaths = false) { $include_paths = explode(PATH_SEPARATOR, ini_get('include_path')); foreach ($include_paths as $path) { $include = $path . DIRECTORY_SEPARATOR . $filename; if (is_file($include) && is_readable($include)) { if ($returnpaths == true) { $includable_paths[] = $path; } else { return true; } } } return (isset($includeable_paths) && $returnpaths == true) ? $includeable_paths : false; } }
include や require は成功、失敗で TRUE, FALSE を返さなず、失敗すると Warning を返すだけなので事前チェックが必要(@ で Warning はとめられるが)。
fopen にだけ bool use_include_path 引数があるようだが、is_file など他にはない模様。 fopen もまた、失敗した場合 Warning を返してしまうので事前チェックが必要でなので、その機能を使った is_includable は作れない。
array_asort_key, array_sort_key
/** * sort array in the given key sequence maintaining key association * * Example) * $japanese = array('orange'=>'mikan', 'apple'=>'ringo'); * $price = array('orange'=> 100, 'apple'= 50); * asort($price, SORT_NUMERIC); // array('apple'=> 50, 'orange'= 100); * array_asort_key($favor, $price); // array('orange'=>'ringo', 'apple'=>'apple'); * * @param array $array array to be sorted * @param array $sorted array having keys in sorting sequence * keys of $array and $sorted must be all common, i.e., * count($array) == count(array_intersect_key($array, $sorted) * @param return void */ function array_asort_key(&$array, &$sorted) { $outarray = array(); foreach ($sorted as $key=> $tmp) { $outarray[$key] = $array[$key]; // change the pointer sequences unset($array[$key]); } $array = $outarray; }
/** * sort array in the given key sequence * * Example) * $fruits = array(0 => 'orange', 1 => 'apple'); * $price = array(0 => 100, 1 => 50); * asort($price, SORT_NUMERIC); // array(1 => 50, 0 => 100) * array_sort_key($favor, $price); // array(0 => 'apple', 1 => 'orange') * * @param array $array array to be sorted * @param array $sorted array having keys in sorting sequence * keys of $array and $sorted must be all common, i.e., * count($array) == count(array_intersect_key($array, $sorted) * @param return void */ function array_sort_key(&$array, &$sorted) { $outarray = array(); foreach ($sorted as $key=> $tmp) { $outarray[] = $array[$key]; // rebuild array unset($array[$key]); } $array = $outarray; }
array_serach_by, in_array_by, max_by
if (! function_exists('array_search_by')) { /** * array_search by a specific field * * @param mixed $needle * @param array $haystack * @param mixed $fieldname * @param bool $strict * @return mixed the key of detected value or false if not found */ function array_search_by($needle, $haystack, $fieldname = null, $strict = false) { if ($strict) { foreach ($haystack as $key => $val) { if ($needle === $val[$fieldname]) { return $key; } } } else { foreach ($haystack as $key => $val) { if ($needle == $val[$fieldname]) { return $key; } } } return false; } }
if (! function_exists('in_array_by')) { /** * in_array by a specific field * * @param mixed $needle * @param array $haystack * @param mixed $fieldname * @param bool $strict * @return bool */ function in_array_by($needle, $haystack, $fieldname = null, $strict = false) { if ($strict) { foreach ($haystack as $key => $val) { if ($needle === $val[$fieldname]) { return true; } } } else { foreach ($haystack as $key => $val) { if ($needle == $val[$fieldname]) { return true; } } } return false; } }
if (! function_exists('max_by')) { /** * max func by a specific field for array * * @param array $array * @param string $fieldname * @return number */ function max_by($array, $fieldname = null) { $field_array = array(); foreach ($array as $i => $befree) { $field_array[$i] = $array[$i][$fieldname]; } return max($field_array); } }
sort_by, sort_assoc_by, is_associative_array
後記:array_sort_key で充分かもしれない。
ポインタの並びだけでなく、キー値も 0, 1, 2 … におきかえる。
if (! function_exists('sort_by')) { /** * Sort an array by a specific field without maintaining key association * (replace keys into 0, 1, 2, ....) * * PHP Extension * * @access public * @param array &$array Input Array * @param string $fieldname Field Name * @param string $sort Sort Function (sort == asort or rsort == arsort or natsort or natcasesort) * @return string $sortflag Sort Flag for asort or arsort such as SORT_REGULAR * @uses asort() * @uses arsort() * @uses natsort() * @uses natcasesort() */ function sort_by(&$array, $fieldname = null, $sort, $sortflag = SORT_REGULAR) { $field_array = array(); // store the field values in a seperate array foreach ($array as $i => $befree) { $field_array[$i] = $array[$i][$fieldname]; } switch ($sort) { case 'asort' || 'sort': // sort an array and maintain index association... asort($field_array, $sortflag); break; case 'arsort' || 'rsort': // sort an array in reverse order and maintain index association arsort($field_array, $sortflag); break; case 'natsort': natsort($field_array); case 'natcasesort': // sort an array using a case insensitive "natural order" algorithm natcasesort($field_array); break; } // rebuild the array $outarray = array(); foreach ( $field_array as $i=> $befree) { $outarray[] = $array[$i]; unset($array[$i]); } $array = $outarray; } }
usort 版
フィールド名が確定しているなら、usort を使うことも可能。 usort はポインタ(配列の並び順)だけではなく、キー番号も書き換える(完璧に作り直す)ので同等。
function filetimecmp($a, $b) { $atime = $a['timestamp']; $btime = $a['timestamp']; if ($atime == $btime) { return 0; } return ($atime < $btime) ? -1 : 1; } usort( $array, 'filetimecmp' ); // array($this, 'filetimecmp');
フィールド名を変数にしたい。
function &sort_by(&$array, $fieldname = null) { function cmp($a, $b) { $a = $a[$fieldname]; $b = $a[$fieldname]; if ($a == $b) return 0; return ($a < $b) ? - 1 : 1; } usort( $array, 'cmp' ); return $array; }
しかし、関数 cmp は関数 sort_by の中だけで使用できる関数というわけではないので、だめ。
ならば、と create_function を使用したいところだが、関数から抜けたときに、create_function 用のメモリを開放するわけではないらしい。なので、呼び出すたびにたまっていき、メモリリーク発生。
よって、フィールド名が決まっている場合のみ、usort でも可能。
sort_by_multi
multisort works to sort by two fields as SQL
// Obtain a list of columns foreach ($data as $key => $row) { $volume[$key] = $row['volume']; $edition[$key] = $row['edition']; } // Sort the data with volume descending, edition ascending // Add $data as the last parameter, to sort by the common key array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
後記:array_asort_key で充分かもしれない。
/** * Sort an array by a specific field maintaining key association * * PHP Extension * * @access public * @param array &$array Input Array * @param string $fieldname Field Name * @param string $sort Sort Function (sort == asort or rsort == arsort or natsort or natcasesort) * @return string $sortflag Sort Flag for asort or arsort such as SORT_REGULAR * @uses asort() * @uses arsort() * @uses natsort() * @uses natcasesort() */ function sort_assoc_by(&$array, $fieldname = null, $sort, $sortflag = SORT_REGULAR) { $field_array = array(); # store the keyvalues in a seperate array foreach ($array as $i => $befree) { $field_array[$i] = $array[$i][$fieldname]; } switch ($sort) { case 'asort' || 'sort': # sort an array and maintain index association... asort($field_array, $sortflag); break; case 'arsort' || 'rsort': # sort an array in reverse order and maintain index association arsort($field_array, $sortflag); break; case 'natsort': natsort($field_array); case 'natcasesort': # sort an array using a case insensitive "natural order" algorithm natcasesort($field_array); break; } # rebuild the old array $outarray = array(); foreach ( $field_array as $key=> $befree) { $outarray[$key] = $array[$key]; // change the pointer sequences unset($array[$key]); } $array = $outarray; }
Example
$arr = array(); $arr['a'] = array('time'=>20); $arr['b'] = array('time'=>10); sort_assoc_by($arr, 'time', 'asort'); print_r($arr); /* Array ( [b] => Array ( [time] => 10 ) [a] => Array ( [time] => 20 ) ) */
sort_key
natsort, natcasesort にも対応した ksort (krsort)
function sort_key(&$array, $sort, $sortflag = SORT_REGULAR) { $key_array = array_keys($array); switch ($sort) { case 'asort' || 'sort': # sort an array and maintain index association... asort($key_array, $sortflag); break; case 'arsort' || 'rsort': # sort an array in reverse order and maintain index association arsort($key_array, $sortflag); break; case 'natsort': natsort($key_array); case 'natcasesort': # sort an array using a case insensitive "natural order" algorithm natcasesort($key_array); break; } # rebuild the old array $outarray = array(); foreach ( $key_array as $i => $key) { $outarray[$key] = $array[$key]; // change the pointer sequences unset($array[$key]); } $array = $outarray; }
Example
$arr = array(); $arr['b'] = 1; $arr['a'] = 2; sort_key($arr, 'sort'); print_r($arr); /* Array ( [a] => 2 [b] => 1 ) */
if (! function_exists('is_associative_array')) { /** * Check if an array is an associative array * * PHP Extension * * @param array $array * @return boolean */ function is_associative_array($array) { if (!is_array($array) || empty($array)) return false; $keys = array_keys($array); return array_keys($keys) !== $keys; // or //return is_array($array) && !is_numeric(implode(array_keys($array))); } }
move
if (! function_exists('move')) { /** * Move a file (rename does not overwrite if $newname exists on Win, but move does) * * @param string $oldname * @param string $newname * @return boolean */ function move($oldname, $newname) { if (! rename($oldname, $newname)) { if (copy ($oldname, $newname)) { unlink($oldname); return TRUE; } return FALSE; } return TRUE; } }
http_filename
未完成?
function http_filename($url) { $headers = get_headers($url, 1); static $loop = 0; while (isset($headers['Location']) && $loop++ < 4) { $url = $headers['Location']; $headers = get_headers($url, 1); } if (isset($headers['Content-Disposition'])) { $matches = array(); if (preg_match('/; ?filename="?([^"]+)"?;?/', $headers['Content-Disposition'], $matches)) { return $matches[1]; } } if (isset($headers['Content-Type'])) { $matches = array(); if (preg_match('/; ?name="?([^"]+)"?;?/', $headers['Content-Type'], $matches)) { return $matches[1]; } } $parse = parse_url($url); return basename($parse['path']); }
extract_mb
function extract_mb(&$str) { $matches = array(); preg_match_all('/[一-龠]+|[ぁ-ん]+|[ァ-ヴー]+|[a-zA-Z0-9]+|[a-zA-Z0-9]+/u', $str, $matches); return $matches; }
検索ワードをエンコードしないとだめだよな・・・
http://phpspot.org/blog/archives/2005/11/php_17.html
英語部分と日本語部分を分離して、pukiwiki の autolink の処理をわけたりすると楽しそう。 #現状は auto というページがあると <a href="xxx">auto</a>link のようになるが、英語なら部分一致ではなく、英単語単位で、とやればこんな変なオートリンクはされずにすむ。
array_minus_plus
use array_diff twice
if (! function_exists('array_minus_plus')) { /** * Get difference between two arrays (minus elements and plus elements) * * @param array $oldarray * @param array $newarray * @return array array((array)$minus, (array)$plus) */ function array_minus_plus($oldarray, $newarray) { $common = array_intersect($oldarray, $newarray); $minus = array_diff($oldarray, $common); $plus = array_diff($newarray, $common); return array($minus, $plus); } }
$minus = array_diff($oldarray, $newarray); $plus = array_diff($newarray, $oldarray);
でいいか。
file_head
from pukiwiki
if (! function_exists('file_head')) { /* * Reads heads of file into an array * * @param string $file filename * @param int $count number of executed fgets, usually equivalent to number of lines * @param boolean $lock use lock or not * @param int $buffer number of bytes to be read in one fgets * @return array */ function file_head($file, $count = 1, $lock = TRUE, $buffer = 8192) { $array = array(); $fp = @fopen($file, 'r'); if ($fp === FALSE) return FALSE; set_file_buffer($fp, 0); if ($lock) @flock($fp, LOCK_SH); rewind($fp); $index = 0; while (! feof($fp)) { $line = fgets($fp, $buffer); if ($line != FALSE) $array[] = $line; if (++$index >= $count) break; } if ($lock) @flock($fp, LOCK_UN); if (! fclose($fp)) return FALSE; return $array; } }
csv_explode, csv_implode
from pukiwiki
// Explode Comma-Separated Values to an array function csv_explode($separator, $string) { $retval = $matches = array(); $_separator = preg_quote($separator, '/'); if (! preg_match_all('/("[^"]*(?:""[^"]*)*"|[^' . $_separator . ']*)' . $_separator . '/', $string . $separator, $matches)) return array(); foreach ($matches[1] as $str) { $len = strlen($str); if ($len > 1 && $str{0} == '"' && $str{$len - 1} == '"') $str = str_replace('""', '"', substr($str, 1, -1)); $retval[] = $str; } return $retval; }
// Test... $csv_str = 'a,"b",c,"this \"should\" work","and ""also"" this"'; echo "test: <pre>".print_r( csv_explode($csv_str), true )."</pre>";
from pukiwiki
// Implode an array with CSV data format (escape double quotes) function csv_implode($glue, $pieces) { $_glue = ($glue != '') ? '\\' . $glue{0} : ''; $arr = array(); foreach ($pieces as $str) { if (ereg('[' . $_glue . '"' . "\n\r" . ']', $str)) $str = '"' . str_replace('"', '""', $str) . '"'; $arr[] = $str; } return join($glue, $arr); }
PHP Compat
MyException
hmmm? not good
if(! class_exists('MyException')){ class MyException { var $_message = ''; var $_code = 0; var $_line = 0; var $_file = ''; var $_trace = NULL; function MyException($message = 'Unknown exception', $code = 0){ $this->_message = $message; $this->_code = $code; $this->_trace = debug_backtrace(); $x = array_shift($this->_trace); $this->_file = $x['file']; $this->_line = $x['line']; } function __construct($message = 'Unknown exception', $code = 0){ $this->MyException($message, $code); } function getMessage(){ return $this->_message; } function getCode(){ return $this->_code; } function getFile(){ return $this->_file; } function getLine(){ return $this->_line; } function getTrace(){ return $this->_trace; } function getTraceAsString(){ $s = ''; foreach($this->_trace as $i=>$item){ foreach($item['args'] as $j=>$arg) $item['args'][$j] = print_r($arg, TRUE); $s .= "#$i " . (isset($item['class']) ? $item['class'] . $item['type'] : '') . $item['function'] . '(' . implode(', ', $item['args']) . ") at [$item[file]:$item[line]]\n"; } return $s; } function printStackTace(){ echo $this->getTraceAsString(); } function toString(){ return $this->getMessage(); } function __toString(){ return $this->toString(); } } } if (! function_exists('MyException_throw')) { function MyException_throw($exception) { $level = error_reporting( E_ALL ); @trigger_error( serialize($exception) ); error_reporting ( $level ); } } if (! function_exists('MyException_catch')) { function MyException_catch($classname) { global $php_errormsg; $exception = unserialize($php_errormsg); if (class_of($exception) == $classname) { return $exception; } return NULL; } }
create_clone
if (! function_exists('create_clone')) { /** * Create a clone of object * * PHP Compat * * @param object $object * @return object cloned object (has same reference/address) */ function create_clone($object) { if (version_compare(phpversion(), '5.0') < 0) { return $object; } else { return @clone($object); } } }
_
if (! function_exists('_')) { /** * i18n gettext * * PHP Compat * * @param string $str * @return string */ function _($str) { return $str; } }
file_put_contents
if (! function_exists('file_put_contents')) { if (! defined('FILE_APPEND')) define('FILE_APPEND', 8); if (! defined('FILE_USE_INCLUDE_PATH')) define('FILE_USE_INCLUDE_PATH', 1); /** * Write a string to a file (PHP5 has this function) * * PHP Compat * * @param string $filename * @param string $data * @param int $flags * @return int the amount of bytes that were written to the file, or FALSE if failure */ function file_put_contents($filename, $data, $flags = 0) { $mode = ($flags & FILE_APPEND) ? 'a' : 'w'; $fp = fopen($filename, $mode); if ($fp === false) { return false; } if (is_array($data)) $data = implode('', $data); if ($flags & LOCK_EX) flock($fp, LOCK_EX); $bytes = fwrite($fp, $data); if ($flags & LOCK_EX) flock($fp, LOCK_UN); fclose($fp); return $bytes; } }
get_headers
if(!function_exists('get_headers')) { function get_headers($url, $format = 0) { $url = parse_url($url); $end = "\r\n\r\n"; $url['port'] = empty($url['port']) ? 80 : $url['port']; if (($fp = @fsockopen($url['host'], $url['port'], $errno, $errstr, 30)) === FALSE) { return FALSE; } $req = "GET ".@$url['path']."?".@$url['query']." HTTP/1.1\r\n"; $req .= "Host: ".@$url['host'].':'.$url['port']."\r\n"; $req .= "Connection: close\r\n"; $req .= "\r\n"; $response = ''; if (fwrite($fp, $req) === FALSE) { fclose($fp); return FALSE; } while (! feof($fp)) { $response .= fgets($fp, 1280); if(strpos($response, $end)) { break; } } fclose($fp); $response = preg_replace("/\r\n\r\n.*\$/", '', $response); $response = explode("\r\n", $response); if ($format) { foreach($response as $i => $val) { if(preg_match('/^([a-zA-Z -]+): +(.*)$/', $val, $matches)) { unset($response[$i]); $response[$matches[1]] = $matches[2]; } } } return $response; } }
r_mkdir
if (! function_exists('r_mkdir')) { /** * mkdir recursively (mkdir of PHP5 has recursive flag) * * @param string $dir * @param int $mode * @return boolean success or failure */ function r_mkdir($dir, $mode = 0755) { if (is_dir($dir) || @mkdir($dir,$mode)) return TRUE; if (! r_mkdir(dirname($dir),$mode)) return FALSE; return @mkdir($dir,$mode); } }