美文网首页PHP经验分享程序员技术栈PHP实战
给thinkphp5增加同时生成model和附属服务文件功能

给thinkphp5增加同时生成model和附属服务文件功能

作者: 日落之国 | 来源:发表于2018-12-07 08:31 被阅读14次

    使用Eloquent ORM是tp官方最为推荐的,不过每次手动复制文件非常麻烦,而虽然框架提供生成空文件的脚本命令,不过在具体定制项目里意义不大,而且为了规范和减少耦合,需要在model和controller之间在加入一个过渡层,这也是tp官方以及其它包括lavarel在内主流框架开发者的看法,项目大中间文件需要做成接口模式以规范开发,如果项目中等或者小,则无需这么麻烦,直接生成一个service服务继承指定的model就可以了。
    1.先准备model模板
    因为model直接和表映射,因此可以通过传表名直接生成,按照框架规划,直接把命令放在make模块下

     <?php
    
    namespace {%namespace%};
    
    use think\Model;
    
    class {%className%} extends Model
    {
        protected $table = '{%tablename%}';
    }
    

    2.在准备文件生成类

    <?php 
    
    namespace think\console\command\make;
    
    use think\console\command\Make;
    use think\App;
    use think\Config;
    use think\console\Command;
    use think\console\Input;
    use think\console\input\Argument;
    use think\console\Output;
    
    /**
     * 生成model和service
     */
    class Ms extends Make
    {
       const SERVICEERROR = '<error>this service already exists!</error>';
        const MODELERROR = '<error>this model already exists!</error>';
        const SERVICESUCCSESS = '<info>this service already successfully!</info>';
        const MODELSUCCSESS = '<info>this model already successfully!</info>';
    
        protected $tablename = '';
        /**
         * 命令备注
         * Typecho Blog Platform
         * @copyright [copyright]
         * @license   [license]
         * @version   [version]
         * @return    [type]      [description]
         */
        protected function configure()
        {
            parent::configure();
            $this->setName('make:ms')
                ->setDescription('Create a new model class and service class');
        }
    
        /**
         * 生成文件
         * Typecho Blog Platform
         * @copyright [copyright]
         * @license   [license]
         * @version   [version]
         * @param     Input       $input  [description]
         * @param     Output      $output [description]
         * @return    [type]              [description]
         */
        protected function execute(Input $input, Output $output)
        {
            $name = trim($input->getArgument('name'));
            $this->tablename = self::get_name($name);//保存数据表名称
            $this->namespace = App::$namespace.'\\'.str_replace($this->tablename,'',str_replace('/','\\',$name));//设置命名空间根路径
            $this->file = str_replace($this->tablename,'',$name);
            // $classname = $this->getClassName($name);
            $classname = self::setHump($this->tablename);//转为驼峰模式
            $this->input = $input;
            $this->output = $output;
            $this->createModel($classname);//生成model
    
            $this->createService($classname);//生成service
        }
    
        /**
         * 生成model文件
         * Typecho Blog Platform
         * @copyright [copyright]
         * @license   [license]
         * @version   [version]
         * @param     [type]      $classname [类名]
         */
        protected function createModel($classname)
        {
            if (!preg_match("/(Model|model)+$/",$classname)) {
                $classname .= "Model";
                $this->serviceusespance = $this->namespace.'model\\'.$classname;
            }
            
            $pathname = APP_PATH.$this->file.'model/'.$classname.'.php';
            if (is_file($pathname)) {
                $this->output->writeln(static::MODELERROR);
                return false;
            }
    
            if (!is_dir(dirname($pathname))) {
                mkdir(strtolower(dirname($pathname)), 0755, true);
            }
    
            file_put_contents($pathname, $this->buildClassModel($classname));
    
            $this->output->writeln(static::MODELSUCCSESS);
        }
    
        /**
         * 生成service
         * Typecho Blog Platform
         * @copyright [copyright]
         * @license   [license]
         * @version   [version]
         * @param     [type]      $classname [类名]
         */
        protected function createService($classname)
        {
            if (!preg_match("/(Service|service)+$/",$classname)) {
                $classname .= "Service";
            }
            $pathname = APP_PATH.$this->file.'service/'.$classname.'.php';
    
            if (is_file($pathname)) {
                $this->output->writeln(static::SERVICEERROR);
                return false;
            }
            if (!is_dir(dirname($pathname))) {
                mkdir(strtolower(dirname($pathname)), 0755, true);
            }
            file_put_contents($pathname, $this->buildClassService($classname));
    
            $this->output->writeln(static::SERVICESUCCSESS);
        }
    
        /**
         * 读取model模板
         * Typecho Blog Platform
         * @copyright [copyright]
         * @license   [license]
         * @version   [version]
         */
        protected function getStub()
        {
            return __DIR__ . '/stubs/model2.stub';
        }
    
        /**
         * 读取service模板
         * Typecho Blog Platform
         * @copyright [copyright]
         * @license   [license]
         * @version   [version]
         */
        protected function getServiceStub()
        {
            return __DIR__ . '/stubs/service.stub';
        }
    
        /**
         * 生成model
         */
        protected function buildClassModel($name)
        {
            $stub = file_get_contents($this->getStub());
    
            $namespace = $this->namespace.'model';
    
            return str_replace(['{%className%}', '{%namespace%}', '{%tablename%}'], [
                $name,
                $namespace,
                $this->tablename
            ], $stub);
            
        }
    
        /**
         * 生成service专属,生成model的时候顺便生成附属service服务
         */
        protected function buildClassService($name)
        {
            $stub = file_get_contents($this->getServiceStub());
    
            $namespace = $this->namespace.'service';
            
            return str_replace(['{%className%}', '{%namespace%}', '{%usenamespace%}'], [
                $name,
                $namespace,
                $this->serviceusespance
            ], $stub);
            
        }
    
        //将字符串转为驼峰模式
        private static function setHump($str)
        {
            if (false === stripos($str,'_')) {
                $str = ucfirst($str);
            } else {
                $strList = explode('_',$str);
                $newStr = '';
                foreach ($strList as $value) {
                    $newStr .= ucfirst($value);
                }
                $str  = $newStr;
            }
            return $str;
        }
    
        /**
         * 截取文件名称
         */
        private static function get_name($str)
        {
            return substr($str,strrpos($str,'/')+1,(strlen($str)-strrpos($str,'/')));
        }
    }
    

    3.在配置命令调用,加上生成ms的命令

    private static $defaultCommands = [
            "think\\console\\command\\Help",
            "think\\console\\command\\Lists",
            "think\\console\\command\\Build",
            "think\\console\\command\\Clear",
            "think\\console\\command\\make\\Ms",
            "think\\console\\command\\make\\Controller",
            "think\\console\\command\\make\\Model",
            "think\\console\\command\\optimize\\Autoload",
            "think\\console\\command\\optimize\\Config",
            "think\\console\\command\\optimize\\Route",
            "think\\console\\command\\optimize\\Schema",
        ];
    

    这样就可以使用这个行命令了


    TIM截图20181207083916.png

    使用方式如下php think make:ms job/table_name,job为app模块下子模块名,table_name为表名。

    相关文章

      网友评论

        本文标题:给thinkphp5增加同时生成model和附属服务文件功能

        本文链接:https://www.haomeiwen.com/subject/azyzcqtx.html