mirror of
https://gitee.com/ShopeX/OMS
synced 2026-04-06 23:05:36 +08:00
453 lines
8.8 KiB
PHP
453 lines
8.8 KiB
PHP
<?php
|
||
/**
|
||
* Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||
* See LICENSE file for license details.
|
||
*/
|
||
class taoexlib_redis_redis
|
||
{
|
||
private $host;
|
||
private $port;
|
||
private $handle;
|
||
|
||
/**
|
||
*
|
||
* @param string $host
|
||
* @param int $port
|
||
*/
|
||
public function __construct( $host = '127.0.0.1', $port = 6379 )
|
||
{
|
||
$this->host = $host;
|
||
$this->port = $port;
|
||
}
|
||
|
||
/**
|
||
* Ping server
|
||
*
|
||
* @param int $server_index Index of the server
|
||
*/
|
||
public function ping( $server_index )
|
||
{
|
||
return $this->execute_command($this->get_connection( $server_index ), 'PING');
|
||
}
|
||
|
||
# === Scalar operations ===
|
||
|
||
/**
|
||
* @param string $key
|
||
* @param mixed $value
|
||
*/
|
||
public function set( $key, $value )
|
||
{
|
||
$value = $this->pack_value($value);
|
||
$cmd = array("SET {$key} " . strlen($value), $value);
|
||
|
||
$response = $this->execute_command( $cmd );
|
||
return $this->get_error($response);
|
||
}
|
||
|
||
/**
|
||
* @param string $key
|
||
* @return mixed
|
||
*/
|
||
public function get( $key )
|
||
{
|
||
$response = $this->execute_command( "GET {$key}" );
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
$length = (int)substr($response, 1);
|
||
if ( $length > 0 )
|
||
{
|
||
$value = $this->get_response();
|
||
return $this->unpack_value($value);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param string $key
|
||
*/
|
||
public function delete( $key )
|
||
{
|
||
return $this->execute_command( "DEL {$key}" );
|
||
}
|
||
|
||
/**
|
||
* @param string $key
|
||
* @return boolean
|
||
*/
|
||
public function exists( $key )
|
||
{
|
||
return $this->execute_command( "EXISTS {$key}" ) == ':1';
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param string $key
|
||
* @param int $by
|
||
*/
|
||
public function inc( $key, $by = 1 )
|
||
{
|
||
$response = $this->execute_command( "INCRBY {$key} {$by}" );
|
||
return substr($response, 1);
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param string $key
|
||
* @param int $by
|
||
*/
|
||
public function dec( $key, $by = 1 )
|
||
{
|
||
$response = $this->execute_command( "DECRBY {$key} {$by}" );
|
||
return substr($response, 1);
|
||
}
|
||
|
||
# === List operations ===
|
||
|
||
public function prepend( $key, $value )
|
||
{
|
||
$value = $this->pack_value($value);
|
||
$cmd = array("LPUSH {$key} " . strlen($value), $value);
|
||
|
||
$response = $this->execute_command( $cmd );
|
||
return $this->get_error($response);
|
||
}
|
||
|
||
public function append( $key, $value )
|
||
{
|
||
$value = $this->pack_value($value);
|
||
$cmd = array("RPUSH {$key} " . $value);
|
||
|
||
$response = $this->execute_command( $cmd );
|
||
return $this->get_error($response);
|
||
}
|
||
public function lpop( $key ) {
|
||
|
||
$response = $this->execute_command( "LPOP {$key}");
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
$length = (int)substr($response, 1);
|
||
if ( $length > 0 )
|
||
{
|
||
$value = $this->get_response();
|
||
return $this->unpack_value($value);
|
||
}
|
||
}
|
||
/**
|
||
* 获取_list
|
||
* @param mixed $key key
|
||
* @param mixed $limit limit
|
||
* @param mixed $offset offset
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_list($key, $limit, $offset = 0)
|
||
{
|
||
$limit--;
|
||
$start = $offset;
|
||
$end = $start + $limit;
|
||
|
||
$response = $this->execute_command( "LRANGE {$key} {$start} {$end}" );
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
$count = (int)substr($response, 1);
|
||
$list = array();
|
||
for ( $i = 0; $i < $count; $i++ )
|
||
{
|
||
$length = substr($this->get_response(), 1);
|
||
$value = $this->get_response();
|
||
$list[] = $this->unpack_value($value);
|
||
}
|
||
|
||
return $list;
|
||
}
|
||
|
||
/**
|
||
* 获取_filtered_list
|
||
* @param mixed $key key
|
||
* @param mixed $filters filters
|
||
* @param mixed $limit limit
|
||
* @param mixed $offset offset
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_filtered_list($key, $filters, $limit = 0, $offset = 0)
|
||
{
|
||
$start = 0;
|
||
$end = $this->get_list_length($key);
|
||
|
||
$response = $this->execute_command( "LRANGE {$key} {$start} {$end}" );
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
$limit = !$limit ? $end : $limit + $offset;
|
||
|
||
$list = array();
|
||
for ( $i = 0; $i < $end; $i++ )
|
||
{
|
||
$length = substr($this->get_response(), 1);
|
||
$value = $this->get_response();
|
||
$value = $this->unpack_value( $value );
|
||
if ( ( $filters == array_intersect($value, $filters) ) && ( ++$added <= $limit ) )
|
||
{
|
||
$list[] = $value;
|
||
}
|
||
}
|
||
|
||
$list = array_slice($list, $offset);
|
||
|
||
return $list;
|
||
}
|
||
|
||
/**
|
||
* 获取_list_length
|
||
* @param mixed $key key
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_list_length($key)
|
||
{
|
||
$response = $this->execute_command( "LLEN {$key}" );
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
return (int)substr($response, 1);
|
||
}
|
||
|
||
/**
|
||
* remove_from_list
|
||
* @param mixed $key key
|
||
* @param mixed $value value
|
||
* @param mixed $count count
|
||
* @return mixed 返回值
|
||
*/
|
||
public function remove_from_list($key, $value, $count = 0)
|
||
{
|
||
$value = $this->pack_value($value);
|
||
$response = $this->execute_command( array("LREM {$key} {$count} " . strlen($value), $value) );
|
||
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
return (int)substr($response, 1);
|
||
}
|
||
|
||
/**
|
||
* remove_by_filter
|
||
* @param mixed $key key
|
||
* @param mixed $filters filters
|
||
* @return mixed 返回值
|
||
*/
|
||
public function remove_by_filter($key, $filters)
|
||
{
|
||
$list = $this->get_filtered_list($key, $filters);
|
||
|
||
foreach ( $list as $item )
|
||
{
|
||
$this->remove_from_list($key, $item);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* truncate_list
|
||
* @param mixed $key key
|
||
* @param mixed $limit limit
|
||
* @param mixed $offset offset
|
||
* @return mixed 返回值
|
||
*/
|
||
public function truncate_list($key, $limit, $offset = 0)
|
||
{
|
||
$limit--;
|
||
$start = $offset;
|
||
$end = $start + $limit;
|
||
|
||
$response = $this->execute_command( "LTRIM {$key} {$start} {$end}" );
|
||
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
# === Set operations ===
|
||
|
||
/**
|
||
* 添加_member
|
||
* @param mixed $key key
|
||
* @param mixed $value value
|
||
* @return mixed 返回值
|
||
*/
|
||
public function add_member( $key, $value )
|
||
{
|
||
$value = $this->pack_value($value);
|
||
$cmd = array("SADD {$key} " . strlen($value), $value);
|
||
|
||
$response = $this->execute_command( $cmd );
|
||
return $response == ':1';
|
||
}
|
||
|
||
/**
|
||
* remove_member
|
||
* @param mixed $key key
|
||
* @param mixed $value value
|
||
* @return mixed 返回值
|
||
*/
|
||
public function remove_member( $key, $value )
|
||
{
|
||
$value = $this->pack_value($value);
|
||
$cmd = array("SREM {$key} " . strlen($value), $value);
|
||
|
||
$response = $this->execute_command( $cmd );
|
||
return $response == ':1';
|
||
}
|
||
|
||
/**
|
||
* is_member
|
||
* @param mixed $key key
|
||
* @param mixed $value value
|
||
* @return mixed 返回值
|
||
*/
|
||
public function is_member( $key, $value )
|
||
{
|
||
$value = $this->pack_value($value);
|
||
$cmd = array("SISMEMBER {$key} " . strlen($value), $value);
|
||
|
||
$response = $this->execute_command( $cmd );
|
||
return $response == ':1';
|
||
}
|
||
|
||
/**
|
||
* 获取_members
|
||
* @param mixed $key key
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_members($key)
|
||
{
|
||
$response = $this->execute_command( "SMEMBERS {$key}" );
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
$count = (int)substr($response, 1);
|
||
$list = array();
|
||
for ( $i = 0; $i < $count; $i++ )
|
||
{
|
||
$length = substr($this->get_response(), 1);
|
||
$value = $this->get_response();
|
||
$list[] = $this->unpack_value($value);
|
||
}
|
||
|
||
return $list;
|
||
}
|
||
|
||
/**
|
||
* 获取_members_count
|
||
* @param mixed $key key
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_members_count($key)
|
||
{
|
||
$response = $this->execute_command( "SCARD {$key}" );
|
||
if ( $this->get_error($response) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
return (int)substr($response, 1);
|
||
}
|
||
|
||
# === Middle tier ===
|
||
|
||
/**
|
||
* Init connection
|
||
*/
|
||
private function get_connection()
|
||
{
|
||
if ( !$this->handle )
|
||
{
|
||
if ( !$sock = fsockopen($this->host, $this->port, $errno, $errstr) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
$this->handle = $sock;
|
||
}
|
||
|
||
return $this->handle;
|
||
}
|
||
|
||
private function pack_value( $value )
|
||
{
|
||
if ( is_numeric($value) )
|
||
{
|
||
return $value;
|
||
}
|
||
else
|
||
{
|
||
return base64_encode(serialize($value));
|
||
}
|
||
}
|
||
|
||
private function unpack_value( $packed )
|
||
{
|
||
if ( is_numeric($packed) )
|
||
{
|
||
return $packed;
|
||
}
|
||
|
||
return unserialize(base64_decode($packed));
|
||
}
|
||
|
||
private function execute_command( $commands )
|
||
{
|
||
$this->get_connection();
|
||
if ( !$this->handle ) return false;
|
||
|
||
if ( is_array($commands) )
|
||
{
|
||
$commands = implode("\r\n", $commands);
|
||
}
|
||
|
||
$command = $commands . "\r\n";
|
||
|
||
for ( $written = 0; $written < strlen($command); $written += $fwrite )
|
||
{
|
||
if ( !$fwrite = fwrite($this->handle, substr($command, $written)) )
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return $this->get_response();
|
||
}
|
||
|
||
private function get_response()
|
||
{
|
||
if ( !$this->handle ) return false;
|
||
return trim(fgets($this->handle), "\r\n ");
|
||
}
|
||
|
||
private function get_error( $response )
|
||
{
|
||
if ( strpos($response, '-ERR') === 0 )
|
||
{
|
||
return substr($response, 5);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
} |