- Enhance Redis methods (`exists`, `setEx`, `delete`, `get`, `set`) to ensure connection before execution. - Introduce short-lived caching for collected order invoices to minimize redundant processing and improve performance. - Add `pagination_helper` for dynamic WHERE clause construction in queries. - Refactor net amount calculation in `collected_order_invoices_o` for efficiency with batch processing. - Extend `listObjectsWithPaginationIfSet` to support additional WHERE clauses.
361 lines
8.6 KiB
PHP
361 lines
8.6 KiB
PHP
<?php
|
|
|
|
namespace traits;
|
|
|
|
use classes\redis;
|
|
use Exception;
|
|
use Predis\Client as PredisClient;
|
|
|
|
trait redis_t
|
|
{
|
|
/**
|
|
* The Redis scheme
|
|
* @var string
|
|
*/
|
|
protected string $redis_scheme = 'tcp';
|
|
/**
|
|
* The Redis host
|
|
* @var string
|
|
*/
|
|
protected string $redis_host = '';
|
|
/**
|
|
* The Redis port
|
|
* @var int
|
|
*/
|
|
protected int $redis_port = 6379;
|
|
/**
|
|
* The Redis password
|
|
* @var string
|
|
*/
|
|
protected string $redis_password = '';
|
|
/**
|
|
* The Redis database
|
|
* @var int
|
|
*/
|
|
protected int $redis_database = 0;
|
|
/**
|
|
* The object types that can be stored in the Redis server, this is used to prevent unauthorized objects from being stored
|
|
* @var array
|
|
*/
|
|
private array $object_types = [
|
|
'order', // The order objects (orders table in the database)
|
|
];
|
|
/**
|
|
* Get the Redis client
|
|
* @var PredisClient
|
|
*/
|
|
private PredisClient $redis;
|
|
|
|
/**
|
|
* Does the key exist in the Redis server
|
|
* @param string $key
|
|
* @return bool
|
|
*/
|
|
public function exists(string $key): bool
|
|
{
|
|
if (!self::is_connected()) {
|
|
self::connect();
|
|
}
|
|
return $this->redis->exists($key);
|
|
}
|
|
|
|
/**
|
|
* Get the Redis client
|
|
* @return PredisClient
|
|
* @throws Exception
|
|
*/
|
|
public function get_client(): PredisClient
|
|
{
|
|
if (!self::is_connected()) {
|
|
self::connect();
|
|
}
|
|
return $this->redis;
|
|
}
|
|
|
|
/**
|
|
* Check if the Redis server is connected
|
|
* @return bool
|
|
*/
|
|
public function is_connected(): bool
|
|
{
|
|
return isset($this->redis);
|
|
}
|
|
|
|
/**
|
|
* Connect to the Redis server
|
|
* @throws Exception
|
|
*/
|
|
public function connect(): self
|
|
{
|
|
|
|
$this->redis = new PredisClient([
|
|
'scheme' => $this->redis_scheme,
|
|
'host' => $this->redis_host,
|
|
'port' => $this->redis_port,
|
|
'password' => $this->redis_password,
|
|
'database' => $this->redis_database
|
|
]);
|
|
|
|
// Check if the connection was successful
|
|
if (!self::is_connected()) {
|
|
throw new Exception('Could not connect to the Redis server');
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Add a pre-defined object to the Redis server
|
|
* @param string $object_type
|
|
* @param string $key
|
|
* @param string $value
|
|
* @param int $expiration
|
|
* @return redis|redis_t
|
|
* @throws Exception
|
|
*/
|
|
public function add_object(string $object_type, string $key, string $value, int $expiration = 60): self
|
|
{
|
|
// Check if the object type is valid
|
|
if (!self::is_valid_object_type($object_type)) {
|
|
throw new Exception('Invalid object type');
|
|
}
|
|
// Set the object in the Redis server
|
|
$this->setEx($object_type . ':' . $key, $value, $expiration);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Check if the object type is valid
|
|
* @param string $key
|
|
* @return bool
|
|
*/
|
|
private function is_valid_object_type(string $key): bool
|
|
{
|
|
return in_array(self::get_object_type($key), $this->object_types);
|
|
}
|
|
|
|
/**
|
|
* Get the object type
|
|
* @param string $key
|
|
* @return string
|
|
*/
|
|
private function get_object_type(string $key): string
|
|
{
|
|
return explode(':', $key)[0];
|
|
}
|
|
|
|
/**
|
|
* Set the value in the Redis server with an expiration time
|
|
* @param string $key
|
|
* @param string $value
|
|
* @param int $expiration The expiration time in seconds
|
|
* @return redis|redis_t
|
|
*/
|
|
public function setEx(string $key, string $value, int $expiration = 60): self
|
|
{
|
|
if (!self::is_connected()) {
|
|
self::connect();
|
|
}
|
|
$this->redis->setex($key, $expiration, $value);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Delete a pre-defined object from the Redis server
|
|
* @param string $object_type
|
|
* @param string $key
|
|
* @return redis|redis_t
|
|
* @throws Exception
|
|
*/
|
|
public function delete_object(string $object_type, string $key): self
|
|
{
|
|
// Check if the object type is valid
|
|
if (!self::is_valid_object_type($object_type)) {
|
|
throw new Exception('Invalid object type');
|
|
}
|
|
// Delete the object from the Redis server
|
|
$this->delete($object_type . ':' . $key);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Delete the value from the Redis server
|
|
* @param string $key
|
|
* @return redis|redis_t
|
|
*/
|
|
public function delete(string $key): self
|
|
{
|
|
if (!self::is_connected()) {
|
|
self::connect();
|
|
}
|
|
$this->redis->del($key);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get a pre-defined object from the Redis server
|
|
* @param string $object_type
|
|
* @param string $key
|
|
* @return string|null
|
|
* @throws Exception
|
|
*/
|
|
public function get_object(string $object_type, string $key): string|null
|
|
{
|
|
// Check if the object type is valid
|
|
if (!self::is_valid_object_type($object_type)) {
|
|
throw new Exception('Invalid object type');
|
|
}
|
|
return $this->get($object_type . ':' . $key);
|
|
}
|
|
|
|
/**
|
|
* Get the value from the Redis server
|
|
* @param string $key
|
|
* @return string|null
|
|
*/
|
|
public function get(string $key): string|null
|
|
{
|
|
if (!self::is_connected()) {
|
|
self::connect();
|
|
}
|
|
return $this->redis->get($key);
|
|
}
|
|
|
|
/**
|
|
* Disconnect from the Redis server when the object is destroyed
|
|
*/
|
|
public function __destruct()
|
|
{
|
|
if (self::is_connected()) {
|
|
self::disconnect();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disconnect from the Redis server
|
|
*/
|
|
public function disconnect(): void
|
|
{
|
|
$this->redis->disconnect();
|
|
}
|
|
|
|
/**
|
|
* Set array key in Redis
|
|
* @param string $key
|
|
* @param array $value
|
|
* @return redis|redis_t
|
|
*/
|
|
public function set_array(string $key, array $value): self
|
|
{
|
|
$this->set($key, json_encode($value));
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the value in the Redis server
|
|
* @param string $key
|
|
* @param string $value
|
|
* @return redis|redis_t
|
|
*/
|
|
public function set(string $key, string $value): self
|
|
{
|
|
if (!self::is_connected()) {
|
|
self::connect();
|
|
}
|
|
$this->redis->set($key, $value);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Clear keys from Redis
|
|
* @param string|array $keys
|
|
* @return redis|redis_t
|
|
*/
|
|
public function clear_keys(array|string $keys): self
|
|
{
|
|
if (!is_array($keys)) {
|
|
// Remove all keys matching the pattern
|
|
$keys = $this->get_keys($keys);
|
|
}
|
|
foreach ( $keys as $key ) {
|
|
$this->delete($key);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get keys from Redis
|
|
* @param string $key The key to search for (supports wildcards)
|
|
* @return array
|
|
*/
|
|
public function get_keys(string $key): array
|
|
{
|
|
// Get all keys from the cache
|
|
return $this->redis->keys($key);
|
|
}
|
|
|
|
/**
|
|
* Get all keys from the Redis server
|
|
* @return array
|
|
*/
|
|
public function keys(): array
|
|
{
|
|
return $this->redis->keys('*');
|
|
}
|
|
|
|
/**
|
|
* Get arrays from Redis
|
|
* @param string $key The key to search for (supports wildcards)
|
|
* @return array|null
|
|
*/
|
|
public function get_arrays(string $key): array|null
|
|
{
|
|
$keys = $this->get_keys($key);
|
|
$arrays = [];
|
|
foreach ( $keys as $key ) {
|
|
$arrays[] = $this->get_array($key);
|
|
}
|
|
return $arrays;
|
|
}
|
|
|
|
/**
|
|
* Get array key from Redis
|
|
* @param string $key
|
|
* @return array|null
|
|
*/
|
|
public function get_array(string $key): array|null
|
|
{
|
|
// Get the array from the cache
|
|
$value = $this->get($key);
|
|
// Check if the value is not null
|
|
if ($value === null) {
|
|
return null;
|
|
}
|
|
// Check if the value is not a valid JSON
|
|
if (!self::is_json($value)) {
|
|
return null;
|
|
}
|
|
return json_decode($value, true);
|
|
}
|
|
|
|
/**
|
|
* Check if the value is a valid JSON
|
|
* @param string $value
|
|
* @return bool
|
|
*/
|
|
private function is_json(string $value): bool
|
|
{
|
|
json_decode($value);
|
|
return json_last_error() === JSON_ERROR_NONE;
|
|
}
|
|
|
|
/**
|
|
* Get the count of matching keys
|
|
* @param string $key The key to search for (supports wildcards)
|
|
* @return int
|
|
*/
|
|
public function count_keys(string $key): int
|
|
{
|
|
return count($this->get_keys($key));
|
|
}
|
|
} |