Tyrant文件夹里的文件
Common.php
<?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>* @license http://www.opensource.org/licenses/mit-license.php MIT License* @link http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/../Tyrant.php';require_once dirname(__FILE__).'/Exception.php';/*** Abstract base class for all types of database connections** This base class is mostly here to avoid duplication of code since * databases share common functions. It** @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>*/abstract class Tyrant_Common implements ArrayAccess, Countable, Iterator{ protected $socket; abstract function put($key, $value); abstract function get($key); public function __construct(&$socket) { $this->socket =& $socket; } /** * Close the connection to TokyoTyrant */ public function disconnect() { if (is_resource($this->socket)) { socket_close($this->socket); $this->socket = null; } } /** * Returns the connection socket * @return resource Connection socket */ public function &socket() { return $this->socket; } /** * Removes a record * * @param string Specifies the primary key * @return bool True when successful, false otherwise */ public function out($key) { $cmd = pack('CCN', 0xC8, 0x20, strlen($key)) . $key; $code = $this->_send($cmd); if ($code !== 0) { return false; } return true; } /** * Gets the size of the value of a record * * @param string Specifies the key * @return int|false Number with size or false otherwise */ public function vsiz($key) { $cmd = pack("CCN", 0xC8, 0x38, strlen($key)) . $key; $code = $this->_send($cmd); if ($code !== 0) { return false; } return $this->_recvInt32(); } /** * Initializes the iterator * * The iterator is used in order to access the key of every record * stored in a database. * * @return bool True when successful, false otherwise */ public function iterinit() { $cmd = pack("CC", 0xC8, 0x50); $code = $this->_send($cmd); if ($code !== 0) { return false; } return true; } /** * Gets the next key of the iterator * * It is possible to access every record by iteration of * calling this method. It is allowed to update or remove * records whose keys are fetched while the iteration. * However, it is not assured if updating the database is * occurred while the iteration. Besides, the order of this * traversal access method is arbitrary, so it is not assured * that the order of storing matches the one of the traversal * access. * * @return mixed Either the next key when successful, false if no more records are available */ public function iternext() { $cmd = pack("CC", 0xC8, 0x51); $code = $this->_send($cmd); if ($code !== 0) { return false; } $ksiz = $this->_recvInt32(); if ($ksiz === false) { return false; } $kref = $this->_recv($ksiz); return $kref; } /** * Gets forward matching keys * * The return value is an array of the keys of the * corresponding records. This method does never fail and return * an empty array even if no record corresponds. Note that this * method may be very slow because every key in the database is * scanned. * * @param string Prefix of the corresponding keys * @param int Maximum number of keys to be fetched. If it * is not defined or negative, no limit is specified. * @return array An array of found primary keys */ public function fwmkeys($prefix, $max = null) { $keys = array(); if (empty($max) || $max < 0) { $max = (1<<31); } $cmd = pack("CCNN", 0xC8, 0x58, strlen($prefix), $max) . $prefix; $code = $this->_send($cmd); if ($code !== 0) { return $keys; } $knum = $this->_recvInt32(); if ($knum === false) { return $keys; } for ($i = 0; $i < $knum; $i++) { $ksiz = $this->_recvInt32(); if ($ksiz === false) { return $keys; } $kref = $this->_recv($ksiz); $keys[] = $kref; } return $keys; } /** * Synchronizes updated contents with the file and the device * @return bool True when successful, false otherwise */ public function sync() { $cmd = pack('CC', 0xC8, 0x70); $code = $this->_send($cmd); if ($code !== 0) { return false; } return true; } /** * Optimize the database file * @return bool True when successful, false otherwise */ public function optimize($params = "") { $cmd = pack('CCN', 0xC8, 0x71, strlen($params)) . $params; $code = $this->_send($cmd); if ($code !== 0) { return false; } return true; } /** * Remove all records * @return bool True when successful, false otherwise */ public function vanish() { $cmd = pack('CC', 0xC8, 0x72); $code = $this->_send($cmd); if ($code !== 0) { return false; } return true; } /** * Copy the database file * * The database file is assured to be kept synchronized and not modified * while the copying or executing operation is in progress. * So, this method is useful to create a backup file of the database file. * * @param string Specifies the path of the destination file. * If it begins with `@', the trailing substring * is executed as a command line. * @return True if successful, false otherwise. */ public function copy($path) { $cmd = pack('CCN', 0xC8, 0x73, strlen($path)) . $path; $code = $this->_send($cmd); if ($code !== 0) { return false; } return true; } /** * Restore the database with update log * * @param Specifies the path of the update log directory * @param Specifies the beginning time stamp in microseconds * @param Specifies options by bitwise-or: * - Tyrant::ROCHKCON for consistency checking * @return True if successful, false otherwise. */ public function restore($path, $msec, $opts = 0) { $cmd = pack('CCN', 0xC8, 0x74, strlen($path)) . $this->_pack64($msec) . $opts . $path; $code = $this->_send($cmd); if ($code !== 0) { return false; } return true; } /** * Get the number of records * @return int|false Number of records or false if something goes wrong */ public function rnum() { $cmd = pack('CC', 0xC8, 0x80); $code = $this->_send($cmd); if ($code !== 0) { return false; } return $this->_recvInt64(); } /** * Get the size of the database * @return mixed Database size or false if something goes wrong */ public function size() { $cmd = pack('CC', 0xC8, 0x81); $code = $this->_send($cmd); if ($code !== 0) { return false; } return $this->_recvInt64(); } /** * Get some statistics about the database * @return array Array of statistics about the database */ public function stat() { $cmd = pack('CC', 0xC8, 0x88); $code = $this->_send($cmd); if ($code !== 0) { return false; } $value = $this->_recv(); $value = explode("\n", trim($value)); $stats = array(); foreach ($value as $v) { $v = explode("\t", $v); $stats[$v[0]] = $v[1]; } return $stats; } /** * Call a versatile function for miscellaneous operations * * All databases support "putlist", "outlist", and "getlist". * - putlist is to store records. It receives keys and values one * after the other, and returns an empty list. * - outlist is to remove records. It receives keys, and returns * an empty list. * - getlist is to retrieve records. It receives keys, and returns * values. * * Table database supports "setindex", "search", "genuid". * * @param string Specifies the name of the function * @param array Specifies an array containing arguments * @param int Specifies options by bitwise-or * bitflag that can be Tyrant::MONOULOG to prevent * writing to the update log * @return array|false Values or false if something goes wrong */ public function misc($name, Array $args = array(), $opts = 0) { $cmd = pack('CCNNN', 0xC8, 0x90, strlen($name), $opts, count($args)) . $name; foreach ($args as $arg) { $cmd .= pack('N', strlen($arg)) . $arg; } $code = $this->_send($cmd); if ($code !== 0) { return false; } $rnum = $this->_recvInt32(); $res = array(); for ($i = 0; $i < $rnum; $i++) { $esiz = $this->_recvInt32(); if ($esiz === false) { return false; } $eref = $this->_recv($esiz); if ($eref === false) { return false; } $res[] = $eref; } return $res; } /** * Call a function of the script language extension * * @param string Specifies the function name * @param string Specifies the key. Defaults to an empty string. * @param string Specifies the value. Defaults to an empty string. * @param int Specifies options by bitwise-or: * - Tyrant::XOLCKREC for record locking * - Tyrant::XOLCKGLB for global locking * Defaults to no option. * @return mixed Value of the response or false on failure */ public function ext($name, $key = '', $value = '', $opts = 0) { $cmd = pack('CCNNNN', 0xC8, 0x68, strlen($name), $opts, strlen($key), strlen($value)) . $name . $key . $value; $code = $this->_send($cmd); if ($code !== 0) { return false; } $vsiz = $this->_recvInt32(); if ($vsiz < 0) { return false; } $vbuf = $this->_recv($vsiz); return $vbuf; } protected function _socketWrite($cmd) { $len = strlen($cmd); $offset = 0; while ($offset < $len) { $sent = socket_write($this->socket, substr($cmd, $offset), $len-$offset); if ($sent === false) { return false; } $offset += $sent; } return ($offset < $len) ? false : true; } protected function _send($cmd) { $status = $this->_socketWrite($cmd); if ($status === false) { return false; } $code = $this->_recvCode(); if ($code === false) { return false; } return $code; } protected function _recv($len = null) { if (is_null($len)) { $len = $this->_recvInt32(); if ($len === false) { return false; } } if ($len < 1) { return ""; } $str = ""; if (($rec = socket_recv($this->socket, $str, $len, 0)) <= 0) { return false; } if (strlen($str) == $len) { return $str; } $len -= strlen($str); while ($len > 0) { $tstr = ""; if (($rec = socket_recv($this->socket, $tstr, $len, 0)) <= 0) { return false; } $len -= strlen($tstr); $str .= $tstr; } return $str; } protected function _recvCode() { if (($rbuf = $this->_recv(1)) !== false) { $c = unpack("C", $rbuf); if (!isset($c[1])) { return false; } return $c[1]; } return false; } protected function _recvInt32() { if (($rbuf = $this->_recv(4)) !== false) { $num = unpack("N", $rbuf); if (!isset($num[1])) { return false; } $size = unpack("l", pack("l", $num[1])); return $size[1]; } return false; } protected function _recvInt64() { if (($rbuf = $this->_recv(8)) !== false) { return $this->_unpack64($rbuf); } return false; } /** * Portability function to pack a x64 value with PHP limitations * @return mixed Packed number */ protected function _pack64($v) { // x64 if (PHP_INT_SIZE >= 8) { $v = (int)$v; return pack ("NN", $v>>32, $v&0xFFFFFFFF); } // x32, int if (is_int($v)) { return pack("NN", $v < 0 ? -1 : 0, $v); } // x32, bcmath if (function_exists("bcmul")) { if (bccomp($v, 0) == -1) { $v = bcadd("18446744073709551616", $v); } $h = bcdiv($v, "4294967296", 0); $l = bcmod($v, "4294967296"); return pack ("NN", (float)$h, (float)$l); // conversion to float is intentional; int would lose 31st bit } // x32, no-bcmath $p = max(0, strlen($v) - 13); $lo = abs((float)substr($v, $p)); $hi = abs((float)substr($v, 0, $p)); $m = $lo + $hi*1316134912.0; // (10 ^ 13) % (1 << 32) = 1316134912 $q = floor($m/4294967296.0); $l = $m - ($q*4294967296.0); $h = $hi*2328.0 + $q; // (10 ^ 13) / (1 << 32) = 2328 if ($v < 0) { if ($l == 0) { $h = 4294967296.0 - $h; } else { $h = 4294967295.0 - $h; $l = 4294967296.0 - $l; } } return pack("NN", $h, $l); } /** * Portability function to unpack a x64 value with PHP limitations * @return mixed Might return a string of numbers or the actual value */ protected function _unpack64($v) { list($hi, $lo) = array_values (unpack("N*N*", $v)); // x64 if (PHP_INT_SIZE >= 8) { if ($hi < 0) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again if ($lo < 0) $lo += (1<<32); return ($hi<<32) + $lo; } // x32, int if ($hi == 0) { if ($lo > 0) { return $lo; } return sprintf("%u", $lo); } elseif ($hi == -1) { // x32, int if ($lo < 0) { return $lo; } return sprintf("%.0f", $lo - 4294967296.0); } $neg = ""; $c = 0; if ($hi < 0) { $hi = ~$hi; $lo = ~$lo; $c = 1; $neg = "-"; } $hi = sprintf ("%u", $hi); $lo = sprintf ("%u", $lo); // x32, bcmath if (function_exists("bcmul")) { return $neg . bcadd(bcadd($lo, bcmul($hi, "4294967296")), $c); } // x32, no-bcmath $hi = (float)$hi; $lo = (float)$lo; $q = floor($hi/10000000.0); $r = $hi - $q*10000000.0; $m = $lo + $r*4967296.0; $mq = floor($m/10000000.0); $l = $m - $mq*10000000.0 + $c; $h = $q*4294967296.0 + $r*429.0 + $mq; $h = sprintf("%.0f", $h); $l = sprintf("%07.0f", $l); if ($h == "0") { return $neg . sprintf("%.0f", (float)$l); } return $neg . $h . $l; } /** * Store the current iterator key or false if no key is available * @var string */ protected $_current; /** * Rewind the Iterator to the first element. * Similar to the reset() function for arrays in PHP * @return void */ public function rewind() { $this->iterinit(); $this->_current = $this->iternext(); } /** * Return the current element. * Similar to the current() function for arrays in PHP * @return mixed current element from the collection */ public function current() { return $this->get($this->_current); } /** * Return the identifying key of the current element. * Similar to the key() function for arrays in PHP * @return mixed either an integer or a string */ public function key() { return $this->_current; } /** * Move forward to next element. * Similar to the next() function for arrays in PHP * @return void */ public function next() { $this->_current = $this->iternext(); } /** * Check if there is a current element after calls to rewind() or next(). * Used to check if we've iterated to the end of the collection * @return boolean FALSE if there's nothing more to iterate over */ public function valid() { return $this->_current !== false; } /** * Returns whether the key exists * @return boolean */ public function offsetExists($offset) { return $this->vsiz($offset) !== false; } /** * Returns the value associated with the key * @return mixed */ public function offsetGet($offset) { return $this->get($offset); } /** * Sets a value for the key * @return boolean True if value was set successfully */ public function offsetSet($offset, $value) { return $this->put($offset, $value); } /** * Removes the value for the key * @return void */ public function offsetUnset($offset) { $this->out($offset); } /** * Returns the number of records in the database * @return int Number of records */ public function count() { return $this->rnum(); }}
Exception.php
<?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>* @license http://www.opensource.org/licenses/mit-license.php MIT License* @link http://mamasam.indefero.net/p/tyrant/*//*** Base class for Exceptions in Tyrant package** @package Tyrant*/class Tyrant_Exception extends Exception { }
Query.php
<?php/*** Tokyo Tyrant network API for PHP** Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.** @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>* @license http://www.opensource.org/licenses/mit-license.php MIT License* @link http://mamasam.indefero.net/p/tyrant/*//*** Query class for the RDBTable database queries** @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>*/class Tyrant_Query{ /** * Query arguments * @var array */ protected $args = array(); /** * Query condition: string is equal to */ const QCSTREQ = 0; /** * Query condition: string is included in */ const QCSTRINC = 1; /** * Query condition: string begins with */ const QCSTRBW = 2; /** * Query condition: string ends with */ const QCSTREW = 3; /** * Query condition: string includes all tokens in */ const QCSTRAND = 4; /** * Query condition: string includes at least one token in */ const QCSTROR = 5; /** * Query condition: string is equal to at least one token in */ const QCSTROREQ = 6; /** * Query condition: string matches regular expressions of */ const QCSTRRX = 7; /** * Query condition: number is equal to */ const QCNUMEQ = 8; /** * Query condition: number is greater than */ const QCNUMGT = 9; /** * Query condition: number is greater than or equal to */ const QCNUMGE = 10; /** * Query condition: number is less than */ const QCNUMLT = 11; /** * Query condition: number is less than or equal to */ const QCNUMLE = 12; /** * Query condition: number is between two tokens of */ const QCNUMBT = 13; /** * Query condition: number is equal to at least one token in */ const QCNUMOREQ = 14; /** * Query condition: full-text search with the phrase of the expression */ const QCFTSPH = 15; /** * Query condition: full-text search with all tokens in the expression */ const QCFTSAND = 16; /** * Query condition: full-text search with at least one token in the expression */ const QCFTSOR = 17; /** * Query condition: full-text search with the compound expression */ const QCFTSEX = 18; /** * Query condition: negation flag */ const QCNEGATE = 16777216; /** * Query condition: no index flag */ const QCNOIDX = 33554432; /** * Order type: string ascending */ const QOSTRASC = 0; /** * Order type: string descending */ const QOSTRDESC = 1; /** * Order type: number ascending */ const QONUMASC = 2; /** * Order type: number descending */ const QONUMDESC = 3; /** * Add a query argument for "string is equal to column" * @param string Column to query upon * @param string Value to search */ public function is($name, $expr) { $this->addCond($name, self::QCSTREQ, $expr); } /** * Add a query argument for "string is included in column" * @param string Column to query upon * @param string Value to search */ public function like($name, $expr) { $this->addCond($name, self::QCSTRINC, $expr); } /** * Add a query argument for "string includes at least one token from column" * @param string Column to query upon * @param string Value to search */ public function has($name, $expr) { $this->addCond($name, self::QCSTROR, $expr); } /** * Add a query argument for "string includes all tokens from column" * @param string Column to query upon * @param string Value to search */ public function hasAll($name, $expr) { $this->addCond($name, self::QCSTRAND, $expr); } /** * Add a query argument for "string is equal to at least one token from column" * @param string Column to query upon * @param string Value to search */ public function isOne($name, $expr) { $this->addCond($name, self::QCSTROREQ, $expr); } /** * Add a query argument for "string begins with" * @param string Column to query upon * @param string Value to search */ public function starts($name, $expr) { $this->addCond($name, self::QCSTRBW, $expr); } /** * Add a query argument for "string ends with" * @param string Column to query upon * @param string Value to search */ public function ends($name, $expr) { $this->addCond($name, self::QCSTREW, $expr); } /** * Add a query argument for "string matches regular expressions of" * @param string Column to query upon * @param string Value to search */ public function matches($name, $expr) { $this->addCond($name, self::QCSTRRX, $expr); } /** * Add a query argument for "number is equal to" * @param string Column to query upon * @param string Value to search */ public function eq($name, $expr) { $this->addCond($name, self::QCNUMEQ, $expr); } /** * Add a query argument for "number is greater than" * @param string Column to query upon * @param string Value to search */ public function gt($name, $expr) { $this->addCond($name, self::QCNUMGT, $expr); } /** * Add a query argument for "number is greater than or equal to" * @param string Column to query upon * @param string Value to search */ public function gte($name, $expr) { $this->addCond($name, self::QCNUMGE, $expr); } /** * Add a query argument for "number is less than" * @param string Column to query upon * @param string Value to search */ public function lt($name, $expr) { $this->addCond($name, self::QCNUMLT, $expr); } /** * Add a query argument for "number is less than or equal to" * @param string Column to query upon * @param string Value to search */ public function lte($name, $expr) { $this->addCond($name, self::QCNUMLE, $expr); } /** * Add a query argument for "number is between two tokens of" * @param string Column to query upon * @param string Value to search */ public function between($name, $expr) { $this->addCond($name, self::QCNUMBT, $expr); } /** * Add a query argument for "number is equal to at least one token in" * @param string Column to query upon * @param string Value to search */ public function eqOne($name, $expr) { $this->addCond($name, self::QCNUMOREQ, $expr); } /** * Add a sort parameter for the query * @param string Column to sort * @param string 'numeric' or 'literal' * @param string 'asc' or 'desc' */ public function sortBy($name, $type = 'numeric', $direction = 'asc') { if ($type != 'numeric') { $type = $direction != 'asc' ? self::QOSTRDESC : self::QOSTRASC; } else { $type = $direction != 'asc' ? self::QONUMDESC : self::QONUMASC; } $this->setOrder($name, $type); } /** * Add a narrowing condition for the query. * @param string Name of a column. An empty string means the primary key. * @param int Operation type, see class constants. * @param mixed Operand exression. */ public function addCond($name, $op, $expr) { $this->args[] = "addcond\0" . $name . "\0" . $op . "\0" . $expr; } /** * Add a sort parameter for the query * @param string Name of a column. * @param int Sort type, see class constants. */ public function setOrder($name, $type) { $this->args['order'] = "setorder\0" . $name . "\0" . $type; } /** * Limit the number of records returned by the query * @param int Maximum number of records returned * @param int Number of records to skip */ public function setLimit($max = -1, $skip = -1) { $this->args['limit'] = "setlimit\0" . $max . "\0" . $skip; } /** * Return the query arguments * @return array Query arguments */ public function args() { return $this->args; }}
RDB.php
<?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>* @license http://www.opensource.org/licenses/mit-license.php MIT License* @link http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/Common.php';/*** Hash and other types of database connection, all except the Table type** @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>*/class Tyrant_RDB extends Tyrant_Common{ /** * Unconditionally set key to value * If a record with the same key exists in the database, * it is overwritten. * * @param string|int Specifies the key. * @param mixed A scalar value (or an object with __toString) * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function put($key, $value) { $cmd = pack('CCNN', 0xC8, 0x10, strlen($key), strlen($value)) . $key . $value; $code = $this->_send($cmd); if ($code !== 0) { throw new Tyrant_Exception("Put error"); } return true; } /** * Store a new record * If a record with the same key exists in the database, * this method has no effect. * * @param string|int Specifies the key. * @param mixed A scalar value (or an object with __toString) * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function putkeep($key, $value) { $cmd = pack('CCNN', 0xC8, 0x11, strlen($key), strlen($value)) . $key . $value; $code = $this->_send($cmd); if ($code !== 0) { throw new Tyrant_Exception("Put error"); } return true; } /** * Append value to the existing value for key, or set key to * value if it does not already exist. * * @param string|int Specifies the key. * @param mixed A scalar value (or an object with __toString) * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function putcat($key, $value) { $cmd = pack('CCNN', 0xC8, 0x12, strlen($key), strlen($value)) . $key . $value; $code = $this->_send($cmd); if ($code !== 0) { throw new Tyrant_Exception("Put error"); } return true; } /** * Concatenate a value at the end of the existing record and * shift it to the left * * @param string|int Specifies the key. * @param mixed A scalar value (or an object with __toString) * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function putshl($key, $value, $width) { $width = $width < 0 ? 0 : (int)$width; $cmd = pack('CCNNN', 0xC8, 0x13, strlen($key), strlen($value), $width) . $key . $value; $code = $this->_send($cmd); if ($code !== 0) { throw new Tyrant_Exception("Put error"); } return true; } /** * Set key to value without waiting for a server response * * @param string|int Specifies the key. * @param mixed A scalar value (or an object with __toString) * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function putnr($key, $value) { $cmd = pack('CCNN', 0xC8, 0x18, strlen($key), strlen($value)) . $key . $value; $status = $this->_socketWrite($cmd); if ($status === false) { throw new Tyrant_Exception("Put error"); } return true; } /** * Get the value of a key from the server * * @param string|int Specifies the key. * @return string|null The value */ public function get($key) { $cmd = pack('CCN', 0xC8, 0x30, strlen($key)) . $key; $code = $this->_send($cmd); if ($code !== 0) { return null; } $value = $this->_recv(); return $value; } /** * Retrieve records * As a result of this method, keys existing in the database have * the corresponding values and keys not existing in the database * are removed. * * @param array Associative array containing the retrieval keys * The array is given by reference so it will be * filled with the values found. * @return int|false Number of retrieved records or false on failure. */ public function mget(&$recs) { $rnum = 0; $cmd = ""; foreach ($recs as $key => $value) { $cmd .= pack("N", strlen($key)) . $key; $rnum++; } $cmd = pack("CCN", 0xC8, 0x31, $rnum) . $cmd; $code = $this->_send($cmd); if ($code !== 0) { return false; } $rnum = $this->_recvInt32(); if ($rnum === false) { return false; } $recs = array(); for ($i = 0; $i < $rnum; $i++) { $ksiz = $this->_recvInt32(); $vsiz = $this->_recvInt32(); if ($ksiz === false || $vsiz === false) { return false; } $kref = $this->_recv($ksiz); $vref = $this->_recv($vsiz); $recs[$kref] = $vref; } return $rnum; } /** * Add an integer to a record * If the corresponding record exists, the value is treated as * an integer and is added to the existing value. If no record exists, * a new record is created with the value. * * @param string The key * @param int The additional value * @return int|false The summation value or false * @throws Tyrant_Exception */ public function addInt($key, $num = 0) { $cmd = pack("CCNN", 0xC8, 0x60, strlen($key), (int)$num) . $key; $code = $this->_send($cmd); if ($code !== 0) { throw new Tyrant_Exception("Could not addInt to ".$key); } return $this->_recvInt32(); } /** * Add a real number to a record * If the corresponding record exists, the value is treated as * a real number and is added to the existing value. If no record exists, * a new record is created with the value. * * @param string The key * @param int The additional value * @return int|false The summation value or false * @throws Tyrant_Exception */ public function addDouble($key, $num = 0) { $integ = substr($num, 0, strpos($num, '.')); $fract = (abs($num) - floor(abs($num)))*1000000000000; $cmd = pack('CCN', 0xC8, 0x61, strlen($key)) . $this->_pack64($integ) . $this->_pack64($fract) . $key; $code = $this->_send($cmd); if ($code !== 0) { throw new Tyrant_Exception("AddDouble error"); } $integ = $this->_recvint64(); $fract = $this->_recvint64(); return $integ + ($fract / 1000000000000); }}
RDBTable.php
<?php/*** Tokyo Tyrant network API for PHP** Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.** @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>* @license http://www.opensource.org/licenses/mit-license.php MIT License* @link http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/Common.php';require_once dirname(__FILE__).'/Query.php';/*** Table type database connection** @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>*/class Tyrant_RDBTable extends Tyrant_Common{ /** * index type: lexical string */ const ITLEXICAL = 0; /** * index type: decimal string */ const ITDECIMAL = 1; /** * index type: token inverted index */ const ITTOKEN = 2; /** * index type: q-gram inverted index */ const ITQGRAM = 3; /** * index type: optimize */ const ITOPT = 9998; /** * index type: void */ const ITVOID = 9999; /** * index type: keep existing index */ const ITKEEP = 16777216; // 1 << 24 /** * Store a record * If a record with the same key exists in the database, * it is overwritten. * * @param string|int Specifies the primary key. * @param array Associative array containing key/values. * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function put($key, $value) { $args = array($key); foreach ($value as $ckey => $cvalue) { $args[] = $ckey; $args[] = $cvalue; } $rv = $this->misc('put', $args, 0); if ($rv === false) { throw new Tyrant_Exception("Put error"); } return true; } /** * Store a new record * If a record with the same key exists in the database, * this method has no effect. * * @param string|int Specifies the primary key. * @param array Associative array containing key/values. * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function putkeep($key, Array $values) { $args = array($key); foreach ($values as $ckey => $cvalue) { $args[] = $ckey; $args[] = $cvalue; } $rv = $this->misc('putkeep', $args, 0); if ($rv === false) { throw new Tyrant_Exception("Put error"); } return true; } /** * Concatenate columns of the existing record * If there is no corresponding record, a new record is created. * * @param string|int Specifies the primary key. * @param array Associative array containing key/values. * @return bool True if successful, false otherwise * @throws Tyrant_Exception */ public function putcat($key, Array $values) { $args = array($key); foreach ($values as $ckey => $cvalue) { $args[] = $ckey; $args[] = $cvalue; } $rv = $this->misc('putcat', $args, 0); if ($rv === false) { throw new Tyrant_Exception("Put error"); } return true; } /** * Retrieve a record * @param int|string Specifies the primary key. * @return array|false If successful, the return value is an * associative array, false if no record were found. */ public function get($key) { $args = array($key); $rv = $this->misc('get', $args, Tyrant::MONOULOG); if ($rv === false) { $rnum = $this->_recvInt32(); return null; } $cols = array(); $cnum = count($rv) - 1; $i = 0; while ($i < $cnum) { $cols[$rv[$i]] = $rv[$i+1]; $i += 2; } return $cols; } /** * Retrieve records * Due to the protocol restriction, this method can not handle records * with binary columns including the "\0" chracter. * * @param array Associative array containing the primary keys. * As a result of this method, keys existing in the * database have the corresponding columns and keys * not existing in the database are removed. * @return int|false If successful, the return value is the number of * records found. False if none found. */ public function mget(Array &$recs) { $rnum = 0; $cmd = ""; foreach ($recs as $key => $value) { $cmd .= pack("N", strlen($key)) . $key; $rnum++; } $cmd = pack("CCN", 0xC8, 0x31, $rnum) . $cmd; $code = $this->_send($cmd); if ($code !== 0) { return false; } $rnum = $this->_recvInt32(); if ($rnum === false) { return false; } $recs = array(); for ($i = 0; $i < $rnum; $i++) { $ksiz = $this->_recvInt32(); $vsiz = $this->_recvInt32(); if ($ksiz === false || $vsiz === false) { return false; } $cols = array(); $kref = $this->_recv($ksiz); $vref = $this->_recv($vsiz); $cary = explode("\0", $vref); $cnum = count($cary) - 1; $j = 0; while ($j < $cnum) { $cols[$cary[$j]] = $cary[$j+1]; $j += 2; } $recs[$kref] = $cols; } return $rnum; } /** * Set a column index * @param string Name of a column. * If the name of an existing index is specified, * the index is rebuilt. An empty string means the * primary key. * @param int Specifies the index type: * - Tyrant_RDBTable::ITLEXICAL for lexical string * - Tyrant_RDBTable::ITDECIMAL for decimal string * - Tyrant::ITOPT for optimizing the index * - tyrant_RDBTable::ITVOID for removing the index * If Tyrant_RDBTable::ITKEEP is added by bitwise-or and * the index exists, this method merely returns failure. * * @return bool True if successful * @throws Tyrant_Exception */ public function setindex($name, $type) { $args = array($name, $type); $rv = $this->misc('setindex', $args, 0); if ($rv === false) { throw new Tyrant_Exception("Could not set index on ".$name); } return true; } /** * Generate a unique ID number * @return int The new unique ID number * @throws Tyrant_Exception */ public function genuid() { $rv = $this->misc('genuid', array()); if ($rv === false) { throw new Tyrant_Exception("Could not generate a new unique ID"); } return $rv[0]; } /** * Execute a search * This method does never fail and return an empty array even * if no record corresponds. * * @param object A Tyrant_Query object * @return array Array of the primary keys of records found. */ public function search(Tyrant_Query $query) { $rv = $this->misc("search", $query->args(), Tyrant::MONOULOG); return empty($rv) ? array() : $rv; } /** * Remove each corresponding records * * @param object A Tyrant_Query object * @return bool True if successful, false otherwise */ public function searchOut(Tyrant_Query $query) { $args = $query->args(); $args[] = "out"; $rv = $this->misc("search", $args, 0); return empty($rv) ? array() : $rv; } /** * Get records corresponding to the search of a query object * The return value is an array of associative arrays with column of * the corresponding records. This method does never fail and return * an empty array even if no record corresponds. * Due to the protocol restriction, this method can not handle records * with binary columns including the "\0" chracter. * * @param object A Tyrant_Query object * @param string|array Array of column names to be fetched. * An empty string returns the primary key. * If it is left null, every column is fetched. * @return array Array of records found */ public function searchGet(Tyrant_Query $query, $names = null) { $args = $query->args(); if (is_array($names)) { $args[] = "get\0" . implode("\0", $names); } else { $args[] = "get"; } $rv = $this->misc("search", $args, Tyrant::MONOULOG); if (empty($rv)) { return array(); } foreach ($rv as $i => $v) { $cols = array(); $cary = explode("\0", $v); $cnum = count($cary) - 1; $j = 0; while ($j < $cnum) { $cols[$cary[$j]] = $cary[$j+1]; $j += 2; } $rv[$i] = $cols; } return $rv; } /** * Get the count of corresponding records * * @param object A Tyrant_Query object * @return int Count of corresponding records or 0 on failure */ public function searchCount(Tyrant_Query $query) { $args = $query->args(); $args[] = "count"; $rv = $this->misc("search", $args, Tyrant::MONOULOG); return empty($rv) ? 0 : $rv[0]; }}
与Tyrant同级目录的文件
Tyrant.php
<?php/*** Tokyo Tyrant network API for PHP* * Copyright (c) 2009 Bertrand Mansion <bmansion@mamasam.com>* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.* * @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>* @license http://www.opensource.org/licenses/mit-license.php MIT License* @link http://mamasam.indefero.net/p/tyrant/*/require_once dirname(__FILE__).'/Tyrant/Exception.php';/*** Factory for Tokyo Tyrant connections** @package Tyrant* @author Bertrand Mansion <bmansion@mamasam.com>*/class Tyrant{ /** * Scripting extension option for record locking */ const XOLCKREC = 1; /** * scripting extension option for global locking */ const XOLCKGLB = 2; /** * Misc function option for omission of the update log */ const MONOULOG = 1; /** * Restore function option for consistency checking */ const ROCHKCON = 1; /** * Keeps track of the connection objects * Makes it possible to easily reuse a connection. * @var array */ protected static $connections = array(); /** * Current connection object * @var object */ protected static $connection; /** * Opens a connection to a Tokyo Tyrant server * <code> * try { * $tt = Tyrant::connect('localhost', 1978); * } catch (Tyrant_Exception $e) { * echo $e->getMessage(); * } * </code> * * @param string Server hostname or IP address * @param string Server port * @param string Optional existing connection id * @return object Database connection */ public static function connect($host = 'localhost', $port = '1978', $id = 0) { $id = implode(':', array($host, $port, $id)); // Check if connection already exists if (isset(self::$connections[$id])) { $connection =& self::$connections[$id]; return $connection; } // Start a new connection $ip = gethostbyname($host); $addr = ip2long($ip); if (empty($addr)) { throw new Tyrant_Exception("Host not found"); } $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!is_resource($socket)){ throw new Tyrant_Exception("Connection refused"); } if (!socket_connect($socket, $addr, $port)) { throw new Tyrant_Exception("Connection refused"); } if (defined('TCP_NODELAY')) { socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1); } else { // See http://bugs.php.net/bug.php?id=46360 socket_set_option($socket, SOL_TCP, 1, 1); } // Determine the database type if (socket_write($socket, pack('CC', 0xC8, 0x88)) === false) { throw new Tyrant_Exception("Unable to get database type"); } $str = ''; if (socket_recv($socket, $str, 1, 0) === false) { throw new Tyrant_Exception("Unable to get database type"); } $c = unpack("C", $str); if (!isset($c[1]) || $c[1] !== 0) { throw new Tyrant_Exception("Unable to get database type"); } $str = ''; if (socket_recv($socket, $str, 4, 0) === false) { throw new Tyrant_Exception("Unable to get database type"); } $num = unpack("N", $str); if (!isset($num[1])) { throw new Tyrant_Exception("Unable to get database type"); } $size = unpack("l", pack("l", $num[1])); $len = $size[1]; $str = ''; if (socket_recv($socket, $str, $len, 0) === false) { throw new Tyrant_Exception("Unable to get database type"); } $value = explode("\n", trim($str)); $stats = array(); foreach ($value as $v) { $v = explode("\t", $v); $stats[$v[0]] = $v[1]; } if (!isset($stats['type'])) { throw new Tyrant_Exception("Unable to get database type"); } // Get the right interface for the database type if ($stats['type'] == 'table') { include_once dirname(__FILE__).'/Tyrant/RDBTable.php'; $conn = new Tyrant_RDBTable($socket); } else { include_once dirname(__FILE__).'/Tyrant/RDB.php'; $conn = new Tyrant_RDB($socket); } self::$connections[$id] =& $conn; self::$connection = $conn; return $conn; } /** * Return the current connection * The current connection is set using Tyrant::setConnection() and * defaults to the last connection made * * @return object|null First connection in the stack */ public function getConnection() { return self::$connection; } /** * Changes the current connection * @param string Server hostname or IP address * @param string Server port * @param string Optional existing connection id * @return object|null First connection in the stack */ public function setConnection($host = 'localhost', $port = '1978', $id = 0) { $id = implode(':', array($host, $port, $id)); self::$connection =& self::$connections[$id]; } /** * Disconnects and removes a connection * @param string Server hostname or IP address * @param string Server port * @param string Optional existing connection id */ public function disconnect($host = 'localhost', $port = '1978', $id = 0) { $id = implode(':', array($host, $port, $id)); if (isset(self::$connections[$id])) { $connection =& self::$connections[$id]; $connection->disconnect(); unset(self::$connections[$id]); return true; } return false; }}
cache的使用类
cache_ttserver.php
<?php/** * TokyoCabinet数据库操作类 */require_once EXTENTION_PATH.'ttserver/Tyrant.php';require_once EXTENTION_PATH.'ttserver/Tyrant/Query.php';class cache_ttserver { private $_conn = null; public $_query = object; /** * 构造函数-创建TTSERVER连接对象 */ public function __construct($host , $port) { $this->_conn = Tyrant::connect($host , $port); $this->_query = new Tyrant_Query; } /** * 写入一行记录 */ public function set($key , $value = null) { $args_num = func_num_args(); if(is_array($key) && $args_num == 1) { $values = $key; foreach($values AS $_key => $_val) { $this->_conn->put($_key , $_val); } } else { return $this->_conn->put($key , $value); } return $this; } /** * 读取一行记录 */ public function get($key) { if(is_array($key)) { $keys = $key; $value = array(); foreach($keys AS $_key) { $serialized_value = $this->_conn->get($_key); $value[$_key] = $serialized_value; } } else { $value = $this->_conn->get($key); } return $value; } /** * 删除一行记录 */ public function remove($key) { return $this->_conn->out($key); } /** * 删除所有记录 */ public function removeAll() { return $this->_conn->vanish(); } /** * 使用条件:TC HASH数据库 * 写入整形记录。若key存在,则更新记录,否则插入一条记录。 */ public function add($key , $increment) { return $this->_conn->addInt($key , $increment); } /** * 使用条件:TC TABLE数据库 * 获取一个连接对象遍历数据库中的所有键/值。 */ public function getIterator() { return $this->_conn; } /** * 获取记录数 */ public function rnum() { return $this->_conn->rnum(); } /** * 使用条件:TC TABLE数据库 * 检索记录集,返回key */ public function search() { return $this->_conn->search($this->_query); } /** * 使用条件:TC TABLE数据库 * 删除检索匹配的记录集 */ public function searchOut() { return $this->_conn->searchOut($this->_query); } /** * 使用条件:TC TABLE数据库 * 检索匹配的记录集,返回记录数组 */ public function searchGet($names = null) { return $this->_conn->searchGet($this->_query, $names); } /** * 使用条件:TC TABLE数据库 * 统计检索匹配的记录集个数 */ public function searchCount() { return $this->_conn->searchCount($this->_query); }}

PHP는 현대 웹 개발, 특히 컨텐츠 관리 및 전자 상거래 플랫폼에서 중요합니다. 1) PHP는 Laravel 및 Symfony와 같은 풍부한 생태계와 강력한 프레임 워크 지원을 가지고 있습니다. 2) Opcache 및 Nginx를 통해 성능 최적화를 달성 할 수 있습니다. 3) PHP8.0은 성능을 향상시키기 위해 JIT 컴파일러를 소개합니다. 4) 클라우드 네이티브 애플리케이션은 Docker 및 Kubernetes를 통해 배포되어 유연성과 확장 성을 향상시킵니다.

PHP는 특히 빠른 개발 및 동적 컨텐츠를 처리하는 데 웹 개발에 적합하지만 데이터 과학 및 엔터프라이즈 수준의 애플리케이션에는 적합하지 않습니다. Python과 비교할 때 PHP는 웹 개발에 더 많은 장점이 있지만 데이터 과학 분야에서는 Python만큼 좋지 않습니다. Java와 비교할 때 PHP는 엔터프라이즈 레벨 애플리케이션에서 더 나빠지지만 웹 개발에서는 더 유연합니다. JavaScript와 비교할 때 PHP는 백엔드 개발에서 더 간결하지만 프론트 엔드 개발에서는 JavaScript만큼 좋지 않습니다.

PHP와 Python은 각각 고유 한 장점이 있으며 다양한 시나리오에 적합합니다. 1.PHP는 웹 개발에 적합하며 내장 웹 서버 및 풍부한 기능 라이브러리를 제공합니다. 2. Python은 간결한 구문과 강력한 표준 라이브러리가있는 데이터 과학 및 기계 학습에 적합합니다. 선택할 때 프로젝트 요구 사항에 따라 결정해야합니다.

PHP는 서버 측에서 널리 사용되는 스크립팅 언어이며 특히 웹 개발에 적합합니다. 1.PHP는 HTML을 포함하고 HTTP 요청 및 응답을 처리 할 수 있으며 다양한 데이터베이스를 지원할 수 있습니다. 2.PHP는 강력한 커뮤니티 지원 및 오픈 소스 리소스를 통해 동적 웹 컨텐츠, 프로세스 양식 데이터, 액세스 데이터베이스 등을 생성하는 데 사용됩니다. 3. PHP는 해석 된 언어이며, 실행 프로세스에는 어휘 분석, 문법 분석, 편집 및 실행이 포함됩니다. 4. PHP는 사용자 등록 시스템과 같은 고급 응용 프로그램을 위해 MySQL과 결합 할 수 있습니다. 5. PHP를 디버깅 할 때 error_reporting () 및 var_dump ()와 같은 함수를 사용할 수 있습니다. 6. 캐싱 메커니즘을 사용하여 PHP 코드를 최적화하고 데이터베이스 쿼리를 최적화하며 내장 기능을 사용하십시오. 7

PHP가 많은 웹 사이트에서 선호되는 기술 스택 인 이유에는 사용 편의성, 강력한 커뮤니티 지원 및 광범위한 사용이 포함됩니다. 1) 배우고 사용하기 쉽고 초보자에게 적합합니다. 2) 거대한 개발자 커뮤니티와 풍부한 자원이 있습니다. 3) WordPress, Drupal 및 기타 플랫폼에서 널리 사용됩니다. 4) 웹 서버와 밀접하게 통합하여 개발 배포를 단순화합니다.

PHP는 현대적인 프로그래밍, 특히 웹 개발 분야에서 강력하고 널리 사용되는 도구로 남아 있습니다. 1) PHP는 사용하기 쉽고 데이터베이스와 완벽하게 통합되며 많은 개발자에게 가장 먼저 선택됩니다. 2) 동적 컨텐츠 생성 및 객체 지향 프로그래밍을 지원하여 웹 사이트를 신속하게 작성하고 유지 관리하는 데 적합합니다. 3) 데이터베이스 쿼리를 캐싱하고 최적화함으로써 PHP의 성능을 향상시킬 수 있으며, 광범위한 커뮤니티와 풍부한 생태계는 오늘날의 기술 스택에 여전히 중요합니다.

PHP에서는 약한 참조가 약한 회의 클래스를 통해 구현되며 쓰레기 수집가가 물체를 되 찾는 것을 방해하지 않습니다. 약한 참조는 캐싱 시스템 및 이벤트 리스너와 같은 시나리오에 적합합니다. 물체의 생존을 보장 할 수 없으며 쓰레기 수집이 지연 될 수 있음에 주목해야합니다.

\ _ \ _ 호출 메소드를 사용하면 객체를 함수처럼 호출 할 수 있습니다. 1. 객체를 호출 할 수 있도록 메소드를 호출하는 \ _ \ _ 정의하십시오. 2. $ obj (...) 구문을 사용할 때 PHP는 \ _ \ _ invoke 메소드를 실행합니다. 3. 로깅 및 계산기, 코드 유연성 및 가독성 향상과 같은 시나리오에 적합합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

SublimeText3 Linux 새 버전
SublimeText3 Linux 최신 버전

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.
