{"id":23009523,"url":"https://github.com/webfiori/cache","last_synced_at":"2025-09-22T00:00:22.351Z","repository":{"id":267128262,"uuid":"900299917","full_name":"WebFiori/cache","owner":"WebFiori","description":"A simple caching engine.","archived":false,"fork":false,"pushed_at":"2025-01-06T16:33:30.000Z","size":42,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-11T11:27:50.317Z","etag":null,"topics":["cache","cache-control","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WebFiori.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://paypal.me/IbrahimBinAlshikh","https://www.buymeacoffee.com/ibrahimdev"],"ko_fi":"ibrahimdev"}},"created_at":"2024-12-08T12:30:21.000Z","updated_at":"2025-01-06T16:32:43.000Z","dependencies_parsed_at":"2024-12-08T15:22:42.191Z","dependency_job_id":"add43472-8517-4be9-97dd-e1d11188dfc4","html_url":"https://github.com/WebFiori/cache","commit_stats":null,"previous_names":["webfiori/cache"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFiori%2Fcache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFiori%2Fcache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFiori%2Fcache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFiori%2Fcache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WebFiori","download_url":"https://codeload.github.com/WebFiori/cache/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250343909,"owners_count":21415037,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","cache-control","php"],"created_at":"2024-12-15T09:14:33.948Z","updated_at":"2025-09-22T00:00:22.320Z","avatar_url":"https://github.com/WebFiori.png","language":"PHP","readme":"# WebFiori Cache\n\nA simple, secure, and highly customizable caching engine for PHP. This library provides time-based caching with built-in encryption support, making it suitable for application-level, server-level, and database-level caching scenarios.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/WebFiori/cache/actions\"\u003e\u003cimg src=\"https://github.com/WebFiori/cache/actions/workflows/php84.yaml/badge.svg?branch=main\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/WebFiori/cache\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/WebFiori/cache/branch/main/graph/badge.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://sonarcloud.io/dashboard?id=WebFiori_cache\"\u003e\n      \u003cimg src=\"https://sonarcloud.io/api/project_badges/measure?project=WebFiori_cache\u0026metric=alert_status\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/WebFiori/cache/releases\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/release/WebFiori/cache.svg?label=latest\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://packagist.org/packages/webfiori/cache\"\u003e\n      \u003cimg src=\"https://img.shields.io/packagist/dt/webfiori/cache?color=light-green\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Features\n\n- **Time-based caching** with configurable TTL (Time-to-Live)\n- **Built-in encryption** for sensitive data protection\n- **Multiple storage backends** (File-based included, extensible via Storage interface)\n- **Static API** for backward compatibility and simple usage\n- **Key prefixing** for namespace isolation\n- **Comprehensive error handling** with custom exceptions\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Supported PHP Versions](#supported-php-versions)\n- [Quick Start](#quick-start)\n- [Usage](#usage)\n  - [Basic Operations](#basic-operations)\n  - [Advanced Usage](#advanced-usage)\n  - [Dependency Injection](#dependency-injection)\n  - [Security Configuration](#security-configuration)\n  - [Custom Storage Drivers](#custom-storage-drivers)\n- [API Reference](#api-reference)\n- [Configuration](#configuration)\n- [Security](#security)\n- [License](#license)\n\n## Installation\n\n### Using Composer\n\n```bash\ncomposer require webfiori/cache\n```\n\n### Manual Installation\n\n1. Download the latest release from [GitHub releases](https://github.com/WebFiori/cache/releases)\n2. Extract the files to your project directory\n3. Include the library in your project:\n\n```php\nrequire_once 'path/to/WebFiori/Cache/Cache.php';\n// You'll also need to manually include all dependencies\nrequire_once 'path/to/WebFiori/Cache/Storage.php';\nrequire_once 'path/to/WebFiori/Cache/Item.php';\nrequire_once 'path/to/WebFiori/Cache/FileStorage.php';\nrequire_once 'path/to/WebFiori/Cache/KeyManager.php';\nrequire_once 'path/to/WebFiori/Cache/SecurityConfig.php';\n// And all exception classes...\n```\n\n**Note:** Manual installation is not recommended. Use Composer for automatic dependency management.\n\n## Supported PHP Versions\n\nThis library requires **PHP 8.1 or higher**.\n\n|                                                                                        Build Status                                                                                        |\n|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|\n| \u003ca target=\"_blank\" href=\"https://github.com/WebFiori/cache/actions/workflows/php81.yaml\"\u003e\u003cimg src=\"https://github.com/WebFiori/cache/actions/workflows/php81.yaml/badge.svg?branch=main\"\u003e\u003c/a\u003e  |\n| \u003ca target=\"_blank\" href=\"https://github.com/WebFiori/cache/actions/workflows/php82.yaml\"\u003e\u003cimg src=\"https://github.com/WebFiori/cache/actions/workflows/php82.yaml/badge.svg?branch=main\"\u003e\u003c/a\u003e  |\n| \u003ca target=\"_blank\" href=\"https://github.com/WebFiori/cache/actions/workflows/php83.yaml\"\u003e\u003cimg src=\"https://github.com/WebFiori/cache/actions/workflows/php83.yaml/badge.svg?branch=main\"\u003e\u003c/a\u003e  |\n| \u003ca target=\"_blank\" href=\"https://github.com/WebFiori/cache/actions/workflows/php84.yaml\"\u003e\u003cimg src=\"https://github.com/WebFiori/cache/actions/workflows/php84.yaml/badge.svg?branch=main\"\u003e\u003c/a\u003e  |\n\n## Quick Start\n\n```php\n\u003c?php\nrequire_once 'vendor/autoload.php';\n\nuse WebFiori\\Cache\\Cache;\n\n// Set up encryption key (recommended for production)\n$_ENV['CACHE_ENCRYPTION_KEY'] = 'your-64-character-hex-key-here';\n\n// Simple cache usage\n$data = Cache::get('user_data', function() {\n    // This callback runs only on cache miss\n    return fetchUserDataFromDatabase();\n}, 3600); // Cache for 1 hour\n\n// Check if item exists\nif (Cache::has('user_data')) {\n    echo \"Data is cached!\";\n}\n\n// Remove specific item\nCache::delete('user_data');\n\n// Clear all cache\nCache::flush();\n```\n\n## Usage\n\n### Basic Operations\n\n#### Creating Cache Items\n\n```php\nuse WebFiori\\Cache\\Cache;\n\n// Store data with default TTL (60 seconds)\nCache::set('my_key', 'Hello World');\n\n// Store data with custom TTL (1 hour)\nCache::set('my_key', 'Hello World', 3600);\n\n// Override existing cache item\nCache::set('my_key', 'New Value', 3600, true);\n```\n\n#### Retrieving Items\n\n**Retrieve Only:**\n```php\n// Returns cached data or null if not found/expired\n$data = Cache::get('my_key');\n\nif ($data === null) {\n    echo \"Cache miss!\";\n}\n```\n\n**Retrieve or Create:**\n```php\n// Recommended approach - automatically handles cache miss\n$data = Cache::get('expensive_operation', function() {\n    // This callback only runs on cache miss\n    return performExpensiveOperation();\n}, 1800); // Cache for 30 minutes\n\n// With parameters\n$userData = Cache::get('user_profile', function($userId, $includePrefs) {\n    return fetchUserProfile($userId, $includePrefs);\n}, 3600, [123, true]); // Pass parameters to callback\n```\n\n#### Other Operations\n\n**Check Item Existence:**\n```php\nif (Cache::has('my_key')) {\n    echo \"Item exists and is not expired\";\n}\n```\n\n**Remove Single Item:**\n```php\nCache::delete('my_key');\n```\n\n**Clear All Cache:**\n```php\nCache::flush();\n```\n\n**Update TTL:**\n```php\n// Extend TTL of existing item to 2 hours\nCache::setTTL('my_key', 7200);\n```\n\n**Enable/Disable Caching:**\n```php\n// Disable caching (useful for debugging)\nCache::setEnabled(false);\n\n// Re-enable caching\nCache::setEnabled(true);\n\n// Check if caching is enabled\nif (Cache::isEnabled()) {\n    echo \"Caching is active\";\n}\n```\n\n### Advanced Usage\n\n#### Working with Cache Items\n\n```php\nuse WebFiori\\Cache\\Cache;\nuse WebFiori\\Cache\\Item;\n\n// Get detailed cache item information\n$item = Cache::getItem('my_key');\n\nif ($item !== null) {\n    echo \"Key: \" . $item-\u003egetKey() . \"\\n\";\n    echo \"Created: \" . date('Y-m-d H:i:s', $item-\u003egetCreatedAt()) . \"\\n\";\n    echo \"Expires: \" . date('Y-m-d H:i:s', $item-\u003egetExpiryTime()) . \"\\n\";\n    echo \"TTL: \" . $item-\u003egetTTL() . \" seconds\\n\";\n    echo \"Data: \" . $item-\u003egetData() . \"\\n\";\n}\n```\n\n#### Key Prefixing\n\n```php\n// Set a prefix for cache isolation\nCache::withPrefix('user_');\n\n// This will actually store with key 'user_profile_123'\nCache::set('profile_123', $userData);\n\n// Or chain the prefix setting\nCache::withPrefix('session_')-\u003eset('abc123', $sessionData);\n```\n\n### Dependency Injection\n\nFor modern applications, use dependency injection instead of static methods:\n\n```php\nuse WebFiori\\Cache\\Cache;\nuse WebFiori\\Cache\\FileStorage;\n\n// Create cache instance with custom storage\n$storage = new FileStorage('/path/to/cache/directory');\n$cache = new Cache($storage, true, 'myapp_');\n\n// Note: The Cache class currently only supports static methods\n// For dependency injection, you would need to create a wrapper class\n// or use the static methods with custom drivers:\n\n// Set custom driver globally\nCache::setDriver($storage);\n\n// Then use static methods as normal\nCache::set('key', 'value', 3600);\n$data = Cache::get('key');\n\n// Or create a factory method\n$cache = Cache::create($storage, true, 'myapp_');\n```\n\n### Security Configuration\n\n#### Environment Variables\n\nSet these environment variables for security configuration:\n\n```bash\n# Required: 64-character hexadecimal encryption key\nCACHE_ENCRYPTION_KEY=your64characterhexadecimalencryptionkeyhere1234567890abcdef\n\n# Optional: Security settings\nCACHE_ENCRYPTION_ENABLED=true\nCACHE_ENCRYPTION_ALGORITHM=aes-256-cbc\nCACHE_FILE_PERMISSIONS=600\nCACHE_DIR_PERMISSIONS=700\n```\n\n#### Programmatic Configuration\n\n```php\nuse WebFiori\\Cache\\KeyManager;\nuse WebFiori\\Cache\\SecurityConfig;\nuse WebFiori\\Cache\\Item;\n\n// Generate and set encryption key\n$key = KeyManager::generateKey();\nKeyManager::setEncryptionKey($key);\n\n// Custom security configuration\n$config = new SecurityConfig();\n$config-\u003esetEncryptionEnabled(true);\n$config-\u003esetEncryptionAlgorithm('aes-256-gcm');\n$config-\u003esetFilePermissions(0600);\n$config-\u003esetDirectoryPermissions(0700);\n\n// Apply to cache item\n$item = new Item('secure_data', $sensitiveData, 3600);\n$item-\u003esetSecurityConfig($config);\n```\n\n### Custom Storage Drivers\n\nImplement the `Storage` interface to create custom storage backends:\n\n```php\nuse WebFiori\\Cache\\Storage;\nuse WebFiori\\Cache\\Item;\n\nclass RedisStorage implements Storage {\n    private $redis;\n    \n    public function __construct($redisConnection) {\n        $this-\u003eredis = $redisConnection;\n    }\n    \n    public function store(Item $item) {\n        $key = $item-\u003egetPrefix() . $item-\u003egetKey();\n        $data = $item-\u003egetDataEncrypted();\n        $this-\u003eredis-\u003esetex($key, $item-\u003egetTTL(), $data);\n    }\n    \n    public function read(string $key, ?string $prefix) {\n        $item = $this-\u003ereadItem($key, $prefix);\n        return $item ? $item-\u003egetDataDecrypted() : null;\n    }\n    \n    public function readItem(string $key, ?string $prefix): ?Item {\n        $fullKey = $prefix . $key;\n        $data = $this-\u003eredis-\u003eget($fullKey);\n        \n        if ($data === false) {\n            return null;\n        }\n        \n        // Reconstruct Item object from stored data\n        // Implementation depends on your storage format\n        return $this-\u003ereconstructItem($key, $data);\n    }\n    \n    public function has(string $key, ?string $prefix): bool {\n        return $this-\u003eredis-\u003eexists($prefix . $key);\n    }\n    \n    public function delete(string $key) {\n        $this-\u003eredis-\u003edel($key);\n    }\n    \n    public function flush(?string $prefix) {\n        if ($prefix) {\n            $keys = $this-\u003eredis-\u003ekeys($prefix . '*');\n            if (!empty($keys)) {\n                $this-\u003eredis-\u003edel($keys);\n            }\n        } else {\n            $this-\u003eredis-\u003eflushdb();\n        }\n    }\n    \n    private function reconstructItem(string $key, $data): Item {\n        // Implementation depends on your data format\n        // This is a simplified example\n        return new Item($key, $data, 3600);\n    }\n}\n\n// Use custom storage\n$redisStorage = new RedisStorage($redisConnection);\nCache::setDriver($redisStorage);\n```\n\n## API Reference\n\n### Cache Class (Static Methods)\n\n| Method | Description | Parameters | Returns |\n|--------|-------------|------------|---------|\n| `get($key, $generator, $ttl, $params)` | Retrieve or create cache item | `string $key`, `callable $generator`, `int $ttl = 60`, `array $params = []` | `mixed` |\n| `set($key, $data, $ttl, $override)` | Store cache item | `string $key`, `mixed $data`, `int $ttl = 60`, `bool $override = false` | `bool` |\n| `has($key)` | Check if item exists | `string $key` | `bool` |\n| `delete($key)` | Remove cache item | `string $key` | `void` |\n| `flush()` | Clear all cache | - | `void` |\n| `getItem($key)` | Get detailed item info | `string $key` | `Item\\|null` |\n| `setTTL($key, $ttl)` | Update item TTL | `string $key`, `int $ttl` | `bool` |\n| `isEnabled()` | Check if caching is enabled | - | `bool` |\n| `setEnabled($enable)` | Enable/disable caching | `bool $enable` | `void` |\n| `setDriver($driver)` | Set storage driver | `Storage $driver` | `void` |\n| `getDriver()` | Get current storage driver | - | `Storage` |\n| `withPrefix($prefix)` | Set key prefix | `string $prefix` | `Cache` |\n\n### Item Class\n\n| Method | Description | Returns |\n|--------|-------------|---------|\n| `getKey()` | Get item key | `string` |\n| `getData()` | Get raw data | `mixed` |\n| `getDataDecrypted()` | Get decrypted data | `mixed` |\n| `getDataEncrypted()` | Get encrypted data | `string` |\n| `getTTL()` | Get time-to-live | `int` |\n| `getCreatedAt()` | Get creation timestamp | `int` |\n| `getExpiryTime()` | Get expiry timestamp | `int` |\n| `setTTL($ttl)` | Set time-to-live | `void` |\n| `generateKey()` | Generate encryption key (static) | `string` |\n\n### Storage Interface\n\n| Method | Description | Parameters |\n|--------|-------------|------------|\n| `store($item)` | Store cache item | `Item $item` |\n| `read($key, $prefix)` | Read item data | `string $key`, `?string $prefix` |\n| `readItem($key, $prefix)` | Read item object | `string $key`, `?string $prefix` |\n| `has($key, $prefix)` | Check item existence | `string $key`, `?string $prefix` |\n| `delete($key)` | Delete item | `string $key` |\n| `flush($prefix)` | Clear cache | `?string $prefix` |\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Description | Default | Example |\n|----------|-------------|---------|---------|\n| `CACHE_ENCRYPTION_KEY` | 64-char hex encryption key | Required | `a1b2c3d4e5f6...` |\n| `CACHE_ENCRYPTION_ENABLED` | Enable/disable encryption | `true` | `true\\|false` |\n| `CACHE_ENCRYPTION_ALGORITHM` | Encryption algorithm | `aes-256-cbc` | `aes-256-gcm` |\n| `CACHE_FILE_PERMISSIONS` | Cache file permissions | `600` | `644` |\n| `CACHE_DIR_PERMISSIONS` | Cache directory permissions | `700` | `755` |\n\n### File Storage Configuration\n\nThe default `FileStorage` class stores cache files in the `WebFiori/Cache/cache` directory. You can customize this:\n\n```php\nuse WebFiori\\Cache\\FileStorage;\nuse WebFiori\\Cache\\Cache;\n\n// Custom cache directory\n$storage = new FileStorage('/var/cache/myapp');\nCache::setDriver($storage);\n```\n\n## Security\n\n### Encryption\n\n- All cached data is encrypted by default using AES-256-CBC\n- Encryption keys should be 64-character hexadecimal strings\n- Keys are managed through environment variables or `KeyManager` class\n- Each cache item can have its own encryption configuration\n\n### File Permissions\n\n- Cache files are created with restrictive permissions (600 by default)\n- Cache directories use 700 permissions by default\n- Permissions are configurable via environment variables or `SecurityConfig`\n\n### Best Practices\n\n1. **Always set an encryption key** in production environments\n2. **Use environment variables** for sensitive configuration\n3. **Regularly rotate encryption keys** for high-security applications\n4. **Set appropriate file permissions** for your environment\n5. **Use prefixes** to isolate different application components\n6. **Implement proper error handling** for cache operations\n\n### Key Generation\n\n```php\nuse WebFiori\\Cache\\KeyManager;\n\n// Generate a new encryption key\n$key = KeyManager::generateKey();\necho \"Your new encryption key: \" . $key;\n\n// Save this key securely and set it as CACHE_ENCRYPTION_KEY\n```\n\n## Error Handling\n\nThe library provides specific exceptions for different error conditions:\n\n```php\nuse WebFiori\\Cache\\Cache;\nuse WebFiori\\Cache\\Exceptions\\InvalidCacheKeyException;\nuse WebFiori\\Cache\\Exceptions\\CacheStorageException;\nuse WebFiori\\Cache\\Exceptions\\CacheDriverException;\nuse WebFiori\\Cache\\Exceptions\\CacheException;\n\ntry {\n    Cache::set('', 'data'); // Invalid key\n} catch (InvalidCacheKeyException $e) {\n    echo \"Invalid cache key: \" . $e-\u003egetMessage();\n}\n\ntry {\n    Cache::get('some_key');\n} catch (CacheStorageException $e) {\n    echo \"Storage error: \" . $e-\u003egetMessage();\n} catch (CacheException $e) {\n    echo \"General cache error: \" . $e-\u003egetMessage();\n}\n```\n\n## Performance Tips\n\n1. **Use appropriate TTL values** - longer for stable data, shorter for frequently changing data\n2. **Implement cache warming** for critical data\n3. **Use key prefixes** to organize and manage cache efficiently\n4. **Monitor cache hit rates** to optimize your caching strategy\n5. **Consider cache size limits** when using file storage\n6. **Use dependency injection** in modern applications for better testability\n\n## Examples\n\n### Web Application Session Caching\n\n```php\nuse WebFiori\\Cache\\Cache;\n\nclass SessionManager {\n    public function __construct() {\n        // Set prefix for session isolation\n        Cache::withPrefix('session_');\n    }\n    \n    public function getSession($sessionId) {\n        return Cache::get($sessionId, function() use ($sessionId) {\n            return $this-\u003eloadSessionFromDatabase($sessionId);\n        }, 1800); // 30 minutes\n    }\n    \n    public function saveSession($sessionId, $data) {\n        Cache::set($sessionId, $data, 1800, true);\n    }\n    \n    public function destroySession($sessionId) {\n        Cache::delete($sessionId);\n    }\n    \n    private function loadSessionFromDatabase($sessionId) {\n        // Your database loading logic here\n        return [];\n    }\n}\n```\n\n### Database Query Caching\n\n```php\nuse WebFiori\\Cache\\Cache;\n\nclass UserRepository {\n    public function findUser($id) {\n        return Cache::get(\"user_{$id}\", function() use ($id) {\n            // Database query only runs on cache miss\n            return $this-\u003edatabase-\u003equery(\"SELECT * FROM users WHERE id = ?\", [$id]);\n        }, 3600); // Cache for 1 hour\n    }\n    \n    public function findUsersByRole($role) {\n        return Cache::get(\"users_by_role_{$role}\", function() use ($role) {\n            return $this-\u003edatabase-\u003equery(\"SELECT * FROM users WHERE role = ?\", [$role]);\n        }, 1800); // Cache for 30 minutes\n    }\n    \n    public function invalidateUserCache($id) {\n        Cache::delete(\"user_{$id}\");\n        // Also invalidate related caches\n        Cache::flush(); // Or more selective deletion\n    }\n}\n```\n\n### API Response Caching\n\n```php\nuse WebFiori\\Cache\\Cache;\n\nclass ApiClient {\n    public function getWeatherData($city) {\n        return Cache::get(\"weather_{$city}\", function() use ($city) {\n            // External API call only on cache miss\n            $response = file_get_contents(\"https://api.weather.com/data/{$city}\");\n            return json_decode($response, true);\n        }, 900); // Cache for 15 minutes\n    }\n    \n    public function getUserProfile($userId, $includePrivate = false) {\n        $cacheKey = \"profile_{$userId}_\" . ($includePrivate ? 'full' : 'public');\n        \n        return Cache::get($cacheKey, function() use ($userId, $includePrivate) {\n            return $this-\u003efetchUserProfile($userId, $includePrivate);\n        }, $includePrivate ? 300 : 3600); // Private data cached shorter\n    }\n}\n```\n\n## License\n\nThis library is licensed under MIT License. See [LICENSE](LICENSE) file for more details.\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Run the test suite: `composer test`\n6. Submit a pull request\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/WebFiori/cache/issues)\n- **Documentation**: This README and inline code documentation\n","funding_links":["https://paypal.me/IbrahimBinAlshikh","https://www.buymeacoffee.com/ibrahimdev","https://ko-fi.com/ibrahimdev"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfiori%2Fcache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebfiori%2Fcache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfiori%2Fcache/lists"}