Глава 45: redis

This commit is contained in:
Igor Simdyanov
2022-07-10 16:02:35 +03:00
parent 7c41cafa92
commit c0889e2420
23 changed files with 478 additions and 0 deletions

4
redis/config.php Normal file
View File

@ -0,0 +1,4 @@
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->select(1);

6
redis/keys.php Normal file
View File

@ -0,0 +1,6 @@
<?php
require_once 'config.php';
echo '<pre>';
print_r($redis->keys('*'));
echo '</pre>';

21
redis/methods.php Normal file
View File

@ -0,0 +1,21 @@
<?php
require_once 'config.php';
// Установка/извлечение ключа
$redis->set('key', 'value');
echo $redis->get('key'); // value
echo '<br />';
// Установка ключа на 10 мс
$redis->set('hello', 'world', 10);
echo $redis->get('hello'); // world
echo '<br />';
// Установка сразу нескольких ключей
$redis->mSet(['fst' => 'первый', 'snd' => 'второй']);
echo $redis->get('snd'); // второй
echo '<br />';
if ($redis->exists('fst')) {
echo $redis->get('fst'); // первый
}

8
redis/mget.php Normal file
View File

@ -0,0 +1,8 @@
<?php
require_once 'config.php';
$keys = $redis->keys('*');
echo '<pre>';
print_r($redis->mGet($keys));
echo '</pre>';

View File

@ -0,0 +1,35 @@
<?php
namespace MVC\Controllers;
class Controller
{
public string $path;
public Router $router;
public object $model;
public function __construct(string $path)
{
$this->path = $path;
$this->router = Router::parse($path);
$class = 'MVC\\Models\\' . ucfirst($this->router->model);
$this->model = new $class();
if($this->router->id) {
$this->model = $this->model->collection[$this->router->id];
}
}
public function render() : string
{
$class = get_class($this->model);
$class = substr($class, strrpos($class, '\\') + 1);
$decorator = \MVC\Decorators\DecoratorFactory::create(
$class,
$this->model);
$view = \MVC\Views\ViewFactory::create(
$this->router->ext,
$class,
$decorator);
return $view->render();
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace MVC\Controllers;
class ControllerCache
{
public string $path;
private string $class;
private Router $router;
private object $model;
private object $redis;
public function __construct(string $path, object $redis)
{
$this->path = $path;
$this->redis = $redis;
}
public function render() : string
{
$cache = $this->redis->get($this->path);
if (!$cache) {
$decorator = \MVC\Decorators\DecoratorFactory::create(
$this->getClass(),
$this->getModel());
$view = \MVC\Views\ViewFactory::create(
$this->getRouter()->ext,
$this->getClass(),
$decorator);
$cache = $view->render();
$this->redis->set($this->path, $cache);
}
return $cache;
}
private function getClass() : string
{
if (empty($this->class)) {
$class = get_class($this->getModel());
$this->class = substr($class, strrpos($class, '\\') + 1);
}
return $this->class;
}
private function getRouter() : Router
{
if (empty($this->router)) {
$this->router = Router::parse($this->path);
}
return $this->router;
}
private function getModel() : object
{
if (empty($this->model)) {
$class = 'MVC\\Models\\' . ucfirst($this->getRouter()->model);
$this->model = new $class();
if ($this->getRouter()->id) {
$this->model = $this->model->collection[$this->getRouter()->id];
}
}
return $this->model;
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace MVC\Controllers;
class ControllerLazy
{
public string $path;
private string $class;
private Router $router;
private object $model;
public function __construct(string $path)
{
$this->path = $path;
}
public function render() : string
{
$decorator = \MVC\Decorators\DecoratorFactory::create(
$this->getClass(),
$this->getModel());
$view = \MVC\Views\ViewFactory::create(
$this->getRouter()->ext,
$this->getClass(),
$decorator);
return $view->render();
}
private function getClass() : string
{
if (empty($this->class)) {
$class = get_class($this->getModel());
$this->class = substr($class, strrpos($class, '\\') + 1);
}
return $this->class;
}
private function getRouter() : Router
{
if (empty($this->router)) {
$this->router = Router::parse($this->path);
}
return $this->router;
}
private function getModel() : object
{
if (empty($this->model)) {
$class = 'MVC\\Models\\' . ucfirst($this->getRouter()->model);
$this->model = new $class();
if ($this->getRouter()->id) {
$this->model = $this->model->collection[$this->getRouter()->id];
}
}
return $this->model;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace MVC\Controllers;
class Router
{
public string $model;
public ?string $ext;
public ?int $id;
public static function parse(string $path) : Router
{
list($path, $ext) = explode('.', $path);
$arr = explode('/', $path);
return new self($arr[0], $ext, count($arr) > 1 ? $arr[1] : null);
}
private function __construct(
string $model,
?string $ext = null,
?int $id = null)
{
$this->model = $model;
$this->ext = $ext;
$this->id = $id;
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace MVC\Decorators;
abstract class DecoratorFactory
{
public static function create(string $class, object $model)
{
$cls = 'MVC\\Decorators\\' . ucfirst($class) . 'Decorator';
return new $cls($model);
}
abstract public function title() : string;
abstract public function body() : string;
abstract public function items() : string;
}

View File

@ -0,0 +1,32 @@
<?php
namespace MVC\Decorators;
class UserDecorator extends DecoratorFactory
{
public $user;
public function __construct(\MVC\Models\User $user)
{
$this->user = $user;
}
public function title() : string
{
return implode(' ', [$this->user->first_name, $this->user->last_name]);
}
public function body() : string
{
return '<strong>' . htmlspecialchars($this->title()) . '</strong> '.
'(' . htmlspecialchars($this->user->email) . ')';
}
public function items() : string
{
return '<item>'.
'<title>' . htmlspecialchars($this->title()) . '</title>' .
'<email>' . htmlspecialchars($this->user->email) . '</email>'.
'</item>';
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace MVC\Decorators;
class UsersDecorator extends DecoratorFactory
{
public $users;
public function __construct(\MVC\Models\Users $users)
{
$this->users = $users;
}
public function title() : string
{
return 'Пользователи';
}
public function collection_render(
callable $call,
string $separator = '<br />') : string
{
return implode(
$separator,
array_map($call, $this->users->collection)
);
}
public function body() : string
{
return $this->collection_render(
function($item){
$decorated_item = new UserDecorator($item);
return $decorated_item->body();
});
}
public function items() : string
{
return $this->collection_render(
function($item){
$decorated_item = new UserDecorator($item);
return $decorated_item->items();
}, '');
}
}

11
redis/mvc/models/user.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace MVC\Models;
class User
{
public function __construct(
public string $email,
private string $password,
public ?string $first_name = null,
public ?string $last_name = null) {}
}

View File

@ -0,0 +1,24 @@
<?php
namespace MVC\Models;
class Users
{
public $collection;
public function __construct(public ?array $users = null)
{
$users ??= [
new User(
'dmitry.koterov@gmail.com',
'password',
'Дмитрий',
'Котеров'),
new User(
'igorsimdyanov@gmail.com',
'password',
'Игорь',
'Симдянов')
];
$this->collection = $users;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace MVC\Views;
class HtmlView extends ViewFactory
{
const LAYOUT = <<<HTML
<!DOCTYPE html>
<html lang="ru">
<head>
<title>{{{title}}}</title>
<meta charset='utf-8' />
</head>
<body>{{{body}}}</body>
</html>
HTML;
protected $replacements;
public function __construct(object $decorator)
{
$this->replacements = [
'{{{title}}}' => $decorator->title(),
'{{{body}}}' => $decorator->body()
];
}
public function render() : string
{
return str_replace(
array_keys($this->replacements),
array_values($this->replacements),
self::LAYOUT);
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace MVC\Views;
class RssView extends ViewFactory
{
const LAYOUT = <<<HTML
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" />
<channel>
<title>{{{title}}}</title>
<link>http://example.com/</link>
{{{items}}}
</channel>
</rss>
HTML;
protected $replacements;
public function __construct(object $decorator)
{
$this->replacements = [
'{{{title}}}' => $decorator->title(),
'{{{items}}}' => $decorator->items()
];
}
public function render() : string
{
return str_replace(
array_keys($this->replacements),
array_values($this->replacements),
self::LAYOUT);
}
}

View File

@ -0,0 +1,4 @@
<?php
namespace MVC\Views;
class UserHtmlView extends HtmlView {}

View File

@ -0,0 +1,4 @@
<?php
namespace MVC\Views;
class UserRssView extends RssView {}

View File

@ -0,0 +1,4 @@
<?php
namespace MVC\Views;
class UsersHtmlView extends HtmlView {}

View File

@ -0,0 +1,4 @@
<?php
namespace MVC\Views;
class UsersRssView extends RssView {}

View File

@ -0,0 +1,18 @@
<?php
namespace MVC\Views;
abstract class ViewFactory
{
abstract public function render() : string;
public static function create(
string $type,
string $class,
\MVC\Decorators\DecoratorFactory $decorator) : ViewFactory
{
$class = 'MVC\\Views\\' . ucfirst($class) . ucfirst($type) . 'View';
$obj = new $class($decorator);
return $obj;
}
}

9
redis/mvc_use.php Normal file
View File

@ -0,0 +1,9 @@
<?php
require_once 'config.php';
spl_autoload_register();
use MVC\Controllers\ControllerCache;
$obj = new ControllerCache('users/1.html', $redis);
echo $obj->render();

4
redis/ping.php Normal file
View File

@ -0,0 +1,4 @@
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo $redis->ping(); // true

9
redis/session.php Normal file
View File

@ -0,0 +1,9 @@
<?php
session_start();
if(!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
$_SESSION['count']++;
echo $_SESSION['count'];