Phalcon搭建多模块框架三十:创建单模块命令行应用

Phalcon搭建多模块框架二十九是创建多模块命令行应用,但有时候项目很小,可能命令行应用只有几个文件不需要分模块。这个时候单模块就很方便。
在开始之前还是需要用到二十九中的前两步,创建define.php文件。
这里写图片描述
1、在cli目录下创建cli.php文件

<?php
/**
 * @desc 命令行入口文件
 * @author: ZhaoYang
 * @date: 2018年6月17日 下午5:42:16
 */
use Phalcon\Cli\Console;

// 检查版本,搭建用到php7一些新特性
version_compare(PHP_VERSION, '7.0.0', '>') || exit('Require PHP > 7.0.0 !');
extension_loaded('phalcon') || exit('Please open the Phalcon extension !');

// 引入自定义常量文件
require '../config/define.php';

version_compare(PHP_VERSION, '3.0.0', '>') || exit('Require Phalcon > 3.0.0 !');

// 设置时区
date_default_timezone_set('Asia/Shanghai');

// error_reporting(E_ALL & ~E_NOTICE);

try {
    // 引入配置文件
    $config = require BASE_PATH . 'config/config_' . NOW_ENV . '.php';

    // 引入cli配置文件
    $cliConfig = require BASE_PATH . 'cli/config/config_' . NOW_ENV . '.php';

    // 引入自动加载配置
    require BASE_PATH . 'config/loader.php';

    // 通常还可能用到各模块的模型
    $registerNamespaces = [];
    foreach (MODULE_ALLOW_LIST as $v) {
        $registerNamespaces[APP_NAMESPACE . '\\' . ucfirst($v) . '\\Models'] = APP_PATH . $v . '/models' . DS;
    }

    $loader->registerNamespaces($registerNamespaces, true)->registerDirs($cliConfig['application']['register_dirs'], true)->register();

    // 引入注册服务
    require BASE_PATH . 'cli/config/services.php';

    // 处理请求
    $console = new Console($di);

    // 设置选项
    $console->setArgument($argv);

    $arguments = [];
    foreach ($argv as $k => $arg) {
        if ($k === 1) {
            $arguments['task'] = $arg;
        } elseif ($k === 2) {
            $arguments['action'] = $arg;
        } elseif ($k >= 3) {
            $arguments['params'][] = $arg;
        }
    }

    // 处理请求
    $console->handle($arguments);
} catch (\Throwable $e) {
    $previous = $e->getPrevious();
    $consoleConfig = $console->config->application;
    if ($consoleConfig->debug->state ?? false) {
        if (empty($consoleConfig->debug->path)) {
            echo 'Exception: ', PHP_EOL, '所在文件:', $e->getFile(), PHP_EOL, '所在行:', $e->getLine(), PHP_EOL, '错误码:', $e->getCode(), PHP_EOL, '错误消息:', $e->getMessage(), PHP_EOL, PHP_EOL;
            if (!is_null($previous)) {
                echo '前一个Exception: ', PHP_EOL, '所在文件:', $previous->getFile(), PHP_EOL, '所在行:', $previous->getLine(), PHP_EOL, '错误码:', $previous->getCode(), PHP_EOL, '错误消息:', $previous->getMessage(), PHP_EOL, PHP_EOL;
            }
            exit();
        }
        $errorFile = $consoleConfig->debug->path;
        $errorType = 'debug';
    } else {
        $errorFile = $consoleConfig->error->path;
        $errorType = 'error';
    }
    $errorMessage = 'Exception: [所在文件:' . $e->getFile() . '] [所在行:' . $e->getLine() . '] [错误码:' . $e->getCode() . '] [错误消息:' . $e->getMessage() . '] '/* . PHP_EOL . '[异常追踪信息:' . $e->getTraceAsString() . ']' */;
    if (!is_null($previous)) {
        $errorMessage .= ' 前一个Exception: [所在文件:' . $previous->getFile() . '] [所在行:' . $previous->getLine() . '] [错误码:' . $previous->getCode() . '] [错误消息:' . $previous->getMessage() . '] '/* . PHP_EOL . '[异常追踪信息:' . $previous->getTraceAsString() . ']' */;
    }
    $console->di->get('logger', [
        $errorFile
    ])->$errorType($errorMessage);
}

2、在cli/config下创建config_dev.php等配置文件

<?php
return [ 
    // 应用配置
    'application' => [ 
        'debug' => [ 
            'state' => true,
            'path' => '' 
        ],
        'error' => [ 
            'path' => BASE_PATH . 'runtime/cli/error/{YmdH}.log'
        ],
        'register_dirs' => [
            BASE_PATH . 'cli/tasks/'
        ]
    ],
    // 服务配置
    'services' => [ 
        // 过滤器设置
        'filter' => [ 
            // 过滤类型,支持string、trim、absint、int、email、float、int!、float!、alphanum、striptags、lower、upper、url、special_chars
            'default_filter' => 'string,trim'
        ],
        // 文件日志,formatter常用line,adapter常用file
        'logger' => [ 
            'line' => [ 
                'format' => '[%date%][%type%] %message%',
                'dateFormat' => 'Y-m-d H:i:s'
            ],
            'file' => [ 
                'alert' => BASE_PATH . 'runtime/cli/logs/alert/{Y/m/d}/{YmdH}.log',
                'critical' => BASE_PATH . 'runtime/cli/logs/critical/{Y/m/d}/{YmdH}.log',
                'debug' => BASE_PATH . 'runtime/cli/logs/debug/{Y/m/d}/{YmdH}.log',
                'error' => BASE_PATH . 'runtime/cli/logs/error/{Y/m/d}/{YmdH}.log',
                'emergency' => BASE_PATH . 'runtime/cli/logs/emergency/{Y/m/d}/{YmdH}.log',
                'info' => BASE_PATH . 'runtime/cli/logs/info/{Y/m/d}/{YmdH}.log',
                'notice' => BASE_PATH . 'runtime/cli/logs/notice/{Y/m/d}/{YmdH}.log',
                'warning' => BASE_PATH . 'runtime/cli/logs/warning/{Y/m/d}/{YmdH}.log'
            ]
        ],
        // 加密配置
        'crypt' => [ 
            // 加密秘钥
            'key' => 'cli',
            // 填充方式,默认是0(PADDING_DEFAULT),1(PADDING_ANSI_X_923)、2(PADDING_PKCS7)、3(PADDING_ISO_10126)、4(PADDING_ISO_IEC_7816_4)、5(PADDING_ZERO)、6(PADDING_SPACE)
            'padding' => '',
            // 加密方法,默认是"aes-256-cfb"
            'cipher' => ''
        ],
        // 缓存配置
        'cache' => [ 
            'backend' => [ 
                // 数据缓存方式,支持memcache、file、redis、mongo、apc、apcu、libmemcached、memory、xcache
                'file' => [ 
                    'cache_dir' => BASE_PATH . 'runtime/cli/cache/'
                ]
            ]
        ],
        // 模型元数据缓存配置
        'models_metadata' => [
            'options' => [
                // 适配器,默认使用memory(内存),还支持apc、apcu、files、libmemcached、memcache、redis、session、xcache
                'adapter' => 'files',
                'meta_data_dir' => BASE_PATH . 'runtime/cli/models_metadata/'
            ]
        ],
        // 模型缓存配置
        'models_cache' => [
            'frontend' => [
                'adapter' => 'data',
                'lifetime' => 86400
            ],
            'backend' => [
                'adapter' => 'memcache',
                'unique_id' => 'cli',
                'prefix' => 'cli',
                'persistent' => false,
                'lifetime' => 3600
            ]
        ],
        // 安全配置
        'security' => [
            // 设置由openssl伪随机生成器生成的字节数
            'random_bytes' => 16,
            // 设置默认hash,0=7(CRYPT_BLOWFISH_Y),1(CRYPT_STD_DES),2(CRYPT_EXT_DES),3(CRYPT_MD5),4(CRYPT_BLOWFISH),5(CRYPT_BLOWFISH_A),6(CRYPT_BLOWFISH_X),8(CRYPT_SHA256),9(CRYPT_SHA512)
            'default_hash' => 7,
            'work_factor' =>8
        ]
    ]
];

3、在cli/config下创建services.php文件

<?php
/**
 * @desc 注册cli服务
 * @author: ZhaoYang
 * @date: 2018年6月17日 下午6:51:16
 */
use Common\Common;
use Phalcon\Cache\Backend\Factory as CacheBackendFactory;
use Phalcon\Cache\Frontend\Factory as CacheFrontendFactory;
use Phalcon\Cli\Dispatcher;
use Phalcon\Config;
use Phalcon\Crypt;
use Phalcon\Db\Adapter\Pdo\Mysql;
use Phalcon\Db\Profiler;
use Phalcon\Di\FactoryDefault\Cli;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Logger\Adapter\File as LoggerAdapterFile;
use Phalcon\Logger\Formatter\Line as LoggerFormatterLine;
use Library\Plugins\DbProfilerPlugin;
use Phalcon\Text;

$di = new Cli();

/**
 * @desc 注册配置服务
 * @author: ZhaoYang
 * @date: 2018年6月17日 下午6:55:44
 */
$di->setShared('config', function () use ($config, $cliConfig) {
    $config = new Config($config);
    $config->merge(new Config($cliConfig));
    return $config;
});

/**
 * @desc 注册调度器服务
 * @author: ZhaoYang
 * @date: 2018年6月18日 下午4:38:04
 */
$di->setShared('dispatcher', function () {
    $dispatcher = new Dispatcher();
    return $dispatcher;
});

/**
 * @desc 注册性能分析组件
 * @author zhaoyang
 * @date 2018年5月20日 下午9:34:33
 */
$di->setShared('profiler', function () {
    $profiler = new Profiler();
    return $profiler;
});

/**
 * @desc 注册数据库(连接)服务
 * @author zhaoyang
 * @date 2018年5月14日 下午9:01:36
 */
$di->setShared('db', function () {
    $dbConfig = $this->getConfig()->services->db->toArray();
    $mysql = new Mysql($dbConfig);
    if ($dbConfig['logged'] ?? false) {
        $eventsManager = new EventsManager();
        $eventsManager->attach('db', new DbProfilerPlugin());
        $mysql->setEventsManager($eventsManager);
    }
    return $mysql;
});

/**
 * @desc 注册日志服务
 * @author zhaoyang
 * @date 2018年5月19日 下午6:20:36
 */
$di->set('logger', function (string $file = null, array $line = null) {
    $config = $this->getConfig()->services->logger;
    $linConfig = clone $config->line;
    !is_null($line) && $linConfig = $linConfig->merge(new Config($line));
    $loggerFormatterLine = new LoggerFormatterLine($linConfig->format, $linConfig->date_format);
    $fileConfig = $config->file;
    if (empty($file)) {
        $file = $fileConfig->info;
    } else if (array_key_exists($file, $fileConfig->toArray())) {
        $file = $fileConfig->$file;
    }
    $file = Common::dirFormat($file);
    $dir = dirname($file);
    $mkdirRes = Common::mkdir($dir);
    if (!$mkdirRes) {
        throw new \Exception('创建目录 ' . $dir . ' 失败');
    }
    $loggerAdapterFile = new LoggerAdapterFile($file);
    $loggerAdapterFile->setFormatter($loggerFormatterLine);
    return $loggerAdapterFile;
});

/**
 * @desc 注册加密服务
 * @author zhaoyang
 * @date 2018年5月28日 下午8:17:46
 */
$di->set('crypt', function (string $key = null, int $padding = null, string $cipher = null) {
    $cryptConfig = $this->getConfig()->services->crypt;
    $crypt = new Crypt();
    if (!empty($cryptConfig->key) || !empty($padding)) {
        $crypt->setKey($key ?? $cryptConfig->key);
    }
    if (!empty($cryptConfig->padding) || !empty($key)) {
        $crypt->setPadding($padding ?? $cryptConfig->padding);
    }
    if (!empty($cryptConfig->cipher) || !empty($cipher)) {
        $crypt->setCipher($cipher ?? $cryptConfig->cipher);
    }
    return $crypt;
});

/**
 * @desc 注册缓存
 * @author zhaoyang
 * @date 2018年5月30日 下午10:30:29
 */
$di->set('cache', function (array $options = []) {
    $cacheConfig = $this->getConfig()->services->cache;
    $frontendConfig = $cacheConfig->frontend;
    if (isset($options['frontend']['adapter'])) {
        $frontendOption = new Config($options['frontend']);
        if (array_key_exists($options['frontend']['adapter'], $frontendConfig->toArray())) {
            $frontendOptionClone = clone $frontendConfig->{$options['frontend']['adapter']};
            $frontendOptionClone->merge($frontendOption);
            $frontendOption = $frontendOptionClone;
        }
    } else {
        $frontendOption = clone $frontendConfig->data;
        $frontendOption->adapter = 'data';
    }
    $frontendOption = Common::convertArrKeyUnderline($frontendOption->toArray());
    if (version_compare(PHALCON_VERSION, '3.2.0', '>')) {
        $frontendCache = CacheFrontendFactory::load($frontendOption);
    } else {
        $frontendClassName = 'Phalcon\\Cache\\Frontend\\' . Text::camelize($frontendOption['adapter']);
        $frontendCache = new $frontendClassName($frontendOption);
    }
    $backendConfig = $cacheConfig->backend;
    if (isset($options['backend']['adapter'])) {
        $backendOption = new Config($options['backend']);
        if (array_key_exists($options['backend']['adapter'], $backendConfig->toArray())) {
            $backendOptionClone = clone $backendConfig->{$options['backend']['adapter']};
            $backendOptionClone->merge($backendOption);
            $backendOption = $backendOptionClone;
        }
    } else {
        $backendOption = clone $backendConfig->file;
        $backendOption->adapter = 'file';
    }
    if ($backendOption->adapter == 'file') {
        if (empty($dir = $backendOption->cache_dir)) {
            throw new \Exception('缓存目录不能为空');
        }
        $dir = Common::dirFormat($dir);
        $mkdirRes = Common::mkdir($dir);
        if (!$mkdirRes) {
            throw new \Exception('创建目录 ' . $dir . ' 失败');
        }
    }
    $backendOption = Common::convertArrKeyUnderline($backendOption->toArray());
    if (version_compare(PHALCON_VERSION, '3.2.0', '>')) {
        $backendOption['frontend'] = $frontendCache;
        $backendCache = CacheBackendFactory::load($backendOption);
    } else {
        $backendClassName = 'Phalcon\\Cache\\Backend\\' . Text::camelize($backendOption['adapter']);
        $backendCache = new $backendClassName($frontendCache, $backendOption);
    }
    return $backendCache;
});

/**
 * @desc 注册 modelsMetadata服务
 * @author zhaoyang
 * @date 2018年6月2日 下午10:39:43
 */
$di->setShared('modelsMetadata', function () {
    $modelsMetadataConfig = $this->getConfig()->services->models_metadata;
    $backendConfig = $this->getConfig()->services->cache->backend;
    $optionsArr = $modelsMetadataConfig->options->toArray();
    if (!isset($optionsArr['adapter'])) {
        throw new \Exception('modelsMetadata必须设置adapter');
    }
    if (array_key_exists($optionsArr['adapter'], $backendConfig->toArray())) {
        $backendOption = clone $backendConfig->{$optionsArr['adapter']};
        $optionsArr = $backendOption->merge(new Config($optionsArr))->toArray();
    }
    if ($optionsArr['adapter'] == 'files') {
        if (empty($optionsArr['meta_data_dir'])) {
            throw new \Exception('缓存目录不能为空');
        }
        $dir = Common::dirFormat($optionsArr['meta_data_dir']);
        $mkdirRes = Common::mkdir($dir);
        if (!$mkdirRes) {
            throw new \Exception('创建目录 ' . $dir . ' 失败');
        }
    }
    $optionsArr = Common::convertArrKeyUnderline($optionsArr);
    $modelsMetadataClassName = 'Phalcon\\Mvc\\Model\\MetaData\\' . Text::camelize($optionsArr['adapter']);
    $modelsMetadata = new $modelsMetadataClassName($optionsArr);
    return $modelsMetadata;
});

/**
 * @desc 注册modelsCache服务
 * @author zhaoyang
 * @date 2018年6月3日 下午6:22:31
 */
$di->set('modelsCache', function (array $options = []) {
    $modelsCacheConfig = clone $this->getConfig()->services->models_cache;
    !empty($options) && $modelsCacheConfig->merge(new Config($options));
    $options = $modelsCacheConfig->toArray();
    $modelsCache = $this->get('cache', [
        $options
    ]);
    return $modelsCache;
});

4、在cli下创建tasks目录存放任务文件,并创建MainTask.php

<?php
use Phalcon\Cli\Task;
use App\Home\Models\Robots;

class MainTask extends Task
{
    public function mainAction()
    {
        echo "This is the cli main task and the main action" . PHP_EOL;
        var_dump($this->dispatcher->getParams());
    }

    public function testAction()
    {
        echo "This is the cli main task and the test action" . PHP_EOL;
        var_dump($this->dispatcher->getParams());
    }

    public function mysqlAction(){
        $robotsList = Robots::find();
        foreach ($robotsList as $robot){
            echo $robot->id,' ',$robot->name,' ',$robot->type,' ',$robot->weight,PHP_EOL;
        }
    }

    public function loggerAction(){
        $this->logger->info('This is an info message2');

        $this->di->getLogger()->info('This is an info message3');

        $this->getDi()->getLogger()->info('This is an info message4');

        $this->di['logger']->info('This is an info message5');

        $this->di->get('logger')->info('This is an info message6');
    }
}

5、在cli/tasks下创建TestTask.php文件

<?php
use Phalcon\Cli\Task;

class TestTask extends Task
{
    public function mainAction()
    {
        echo "This is the cli test task and the main action" . PHP_EOL;
        var_dump($this->dispatcher->getParams());
    }

    public function testAction()
    {
        echo "This is the cli test task and the test action" . PHP_EOL;
        var_dump($this->dispatcher->getParams());
    }
}

6、开始测试
进入cli目录下

php cli.php

这里写图片描述

php cli.php test

这里写图片描述

 php cli.php test test

这里写图片描述

php cli.php test test 'aaa bbb'

这里写图片描述

php cli.php main mysql

这里写图片描述
测试完成

猜你喜欢

转载自blog.csdn.net/u014691098/article/details/80727007
今日推荐