Рубрики
Uncategorized

Вводный учебник Think-swool 3.0 (thinkphp 6.0) анализ архитектуры 2

Автор оригинала: David Wong.

ThinkPHP вот – вот выпустит последнюю версию 6.0. В ответ на растущую популярность Вулфа ThinkPHP также запустил новейшее расширение think-swool 3.0.

Песочница

В этой статье в основном представлена технология песочницы, используемая в ThinkPHP-swool 3.0. Песочница – Как следует из названия, все программы выполняются в закрытом контейнере, благодаря лучшей технологии контейнеров песочница может сыграть важную роль в расширении 3.0.

Во-первых, посмотрите, как используются песочницы, см. Swool. PHP в расширении, где функция onRequest

 public function onRequest($req, $res)
    {
        $this->app->event->trigger('swoole.request');
        
        $this->resetOnRequest();
        
        /** @var Sandbox $sandbox */
        $sandbox = $this->app->make(Sandbox::class);
        $request = $this->prepareRequest($req);
        
        try {
            $sandbox->setRequest($request);
            
            $sandbox->init();
            
            $response = $sandbox->run($request);
            
            $this->sendResponse($sandbox, $response, $res);
        } catch (Throwable $e) {
            try {
                $exceptionResponse = $this->app
                    ->make(Handle::class)
                    ->render($request, $e);
                
                $this->sendResponse($sandbox, $exceptionResponse, $res);
            } catch (Throwable $e) {
                $this->logServerError($e);
            }
        } finally {
            $sandbox->clear();
        }
    }

В коде песочница удаляется из контейнера, затем запрос вводится в песочницу, а результат вычисляется и возвращается в песочницу. Наконец, песочница очищена, так как же Песочница играет роль песочницы?

 //$sandbox->setRequest($request);

    public function setRequest(Request $request)
    {
        Context::setData('_request', $request);
        
        return $this;
    }

Приведенный выше код вводит запрос в песочницу, и там есть другой контекст, так что же делает этот класс? Почему бы не хранить все имущество в песочнице? В конце этой статьи мы представляем песочницу.

//$sandbox->init();
     public function init()
    {
        if (!$this->config instanceof Config) {
            throw new RuntimeException('Please initialize after setting base app.');
        }
        
        $this->setInstance($app = $this->getApplication());
        $this->resetApp($app);
    }

Самое важное звено находится здесь. Видя это, мы можем понять, почему песочницы называются песочницами. Поскольку tp6 основан на создании и уничтожении ресурсов контейнерами, контейнеры относительно изолированы. Затем посмотрите на код.

//$this->setInstance($app = $this->getApplication());
 public function getApplication()
    {
        $snapshot = $this->getSnapshot();
        if ($snapshot instanceof Container) {
            return $snapshot;
        }
        
        $snapshot = clone $this->getBaseApp();
        $this->setSnapshot($snapshot);
        
        return $snapshot;
    }

Ты что-нибудь видел? Клонируй, копируй. Здесь копируется объект контейнера, то есть исходный объект контейнера, и новый контейнер также имеет. То есть каждый запрос создает новую среду для выполнения и анализа. Из-за изоляции контейнера каждый запрос не будет мешать другим запросам. Что касается следующего кода, смотрите здесь, я думаю, вы поняли.

$this->resetApp($app);

Наконец, $песочница – > очистить (), очистить данные текущего протокола, хранящиеся в классе контекста, и инициализировать контейнер текущей песочницы

public function clear()
    {
        Context::clear();
        $this->setInstance($this->getBaseApp());
    }

Внешняя глава

Зачем вам нужны контекстные классы в песочницах? Когда вы посмотрите на этот класс, вы поймете, что static:: getCoroutineId () предназначен для получения текущего идентификатора протокола, каждый протокол будет иметь уникальный идентификатор, так что некоторые специальные данные или объекты могут храниться в контексте, не вызывая путаницы в данных. Потому что только текущий протокол может считывать данные.

php

namespace think\swoole\coroutine;

use Swoole\Coroutine;
use think\Container;

class Context
{
    /**
     * The app containers in different coroutine environment.
     *
     * @var array
     */
    protected static $apps = [];

    /**
     * The data in different coroutine environment.
     *
     * @var array
     */
    protected static $data = [];

    /**
     * Get app container by current coroutine id.
     */
    public static function getApp()
    {
        return static::$apps[static::getCoroutineId()] ?? null;
    }

    /**
     * Set app container by current coroutine id.
     *
     * @param Container $app
     */
    public static function setApp(Container $app)
    {
        static::$apps[static::getCoroutineId()] = $app;
    }

    /**
     * Get data by current coroutine id.
     *
     * @param string $key
     *
     * @return mixed|null
     */
    public static function getData(string $key)
    {
        return static::$data[static::getCoroutineId()][$key] ?? null;
    }

    /**
     * Set data by current coroutine id.
     *
     * @param string $key
     * @param        $value
     */
    public static function setData(string $key, $value)
    {
        static::$data[static::getCoroutineId()][$key] = $value;
    }

    /**
     * Remove data by current coroutine id.
     *
     * @param string $key
     */
    public static function removeData(string $key)
    {
        unset(static::$data[static::getCoroutineId()][$key]);
    }

    /**
     * Get data keys by current coroutine id.
     */
    public static function getDataKeys()
    {
        return array_keys(static::$data[static::getCoroutineId()] ?? []);
    }

    /**
     * Clear data by current coroutine id.
     */
    public static function clear()
    {
        unset(static::$apps[static::getCoroutineId()]);
        unset(static::$data[static::getCoroutineId()]);
    }

    /**
     * Get current coroutine id.
     */
    public static function getCoroutineId()
    {
        return Coroutine::getuid();
    }
}