百搜论坛
 
收藏文章 楼主
THINKPHP的cron任务实现
版块:后端开发   类型:普通   作者:柠檬   查看:135   回复:0   获赞:0   时间:2020-06-23 09:45:48

THINKPHP的cron计划任务的实现,利用THINKPHP自带的cli,加上数据库执行记录(记录任务的报错,成功)。

在服务器cron定时任务在网站目录(不是网站根目录)执行php cron.php,网站根目录为Public。

1.jpg

写一个cli的入口文件

cli.php

1

2

3

4

5

6

7

8

9

10

11

12

<?php

define('MODE_NAME', 'cli');

// 检测PHP环境

if(version_compare(PHP_VERSION,'5.3.0','<'))  die('require PHP > 5.3.0 !');

 

define('APP_DEBUG', true);

 

// 定义应用目录

define('APP_PATH', __DIR__ . '/Application/');

 

// 引入ThinkPHP入口文件

require __DIR__ . '/ThinkPHP/ThinkPHP.php';

写一个执行文件

cron.php

1

2

define('AUTO_CRON', true);

include __DIR__ . '/cli.php';

数据库设计

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

DROP TABLE IF EXISTS `cron`;

CREATE TABLE IF NOT EXISTS `cron` (

  `cron_id` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',

  `expression` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',

  `class` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',

  `method` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',

  `type` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',

  `status` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',

  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

  `run_at` timestamp NULL DEFAULT NULL,

  `ms` int(10) unsigned NOT NULL DEFAULT '0',

  `error` text COLLATE utf8_unicode_ci NOT NULL,

  PRIMARY KEY (`cron_id`),

  KEY `name` (`name`,`created_at`),

  KEY `cron_status_index` (`status`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

配置文件

1

2

3

4

5

6

7

8

9

10

11

<?php

return array(

    'version' => '1.0.0',

    'beastalkd' => array(

        'process_untreated_queue' => array(

            'expression' => '* * * * *',

            'class' => 'Statistics\Model\PheanstalkModel',

            'method' => 'processUntreatedQueue'

        )

    )

);

执行文件 init.php

/写个hook程序执行init.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

<?php

use Think\Log, Think\Db, Cron\Model\Cron;

$Model = new \Think\Model();

$Has = !$Model->query("SHOW TABLES LIKE 'cron'")?false:true;

 

if(defined("AUTO_CRON") && $Has){

    class CronCommand

    {

 

        protected $_initializedJobs;

        protected $_jobs;

        protected $_now;

 

        public function __construct()

        {

            $this->_now = strtotime(date('Y-n-j H:i'));

            import("Cron.Common.Cron.tdcron_entry",'','.php');

            import("Cron.Common.Cron.tdcron",'','.php');

        }

 

        /**

         * 这里是放要执行的代码

         */

        public function fire()

        {

            restore_error_handler();

            restore_exception_handler();

            $this->_initializedJobs = array();

            $jobs = M('cron')->where("status = 'initialized'")->select();

            /**

             * @var $cron Cron

             * 已存在 cron

             */

            if($jobs) {

                $cron = new Cron();

                foreach ($jobs as $data) {

                    $cron->setData($data)->isNew(false);

                    $this->_initializedJobs[$data['name']] = $cron;

                }

            }

 

            /**

             * 新 cron

             */

            foreach ($this->getCronJobs() as $name => $cronJob) {

                if (isset($cronJob['expression'])) {

                    $expression = $cronJob['expression'];

                } else {

                    Log::write('Cron expression is required for cron job "' . $name . '"',Log::WARN);

                    continue;

                }

                if ($this->_now != tdCron::getNextOccurrence($expression, $this->_now)) continue;

                $cronJob['name'] = $name;

                $cron = isset($this->_initializedJobs[$name]) ? $this->_initializedJobs[$name] : $this->_initializedJobs[$name] = new Cron();

                $cron->initialize($cronJob);

            }

 

            /* @var $cron Cron 处理*/

            foreach ($this->_initializedJobs as $cron) {

                $cron->run();

            }

 

        }

 

 

        /**

         * Get All Defined Cron Jobs

         * 获取配置

         * @return array

         */

        public function getCronJobs()

        {

            if ($this->_jobs === null) {

                $this->_jobs = C('beastalkd');

            }

            return $this->_jobs;

        }

 

    }

    $command = new CronCommand();

    $command->fire();

}

cron 模型

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

<?php

namespace Cron\Model;

use Common\Model;

use Think\Log;

 

/**

 * Class Cron

 * @method string getClass()

 * @method string getMethod()

 * @method string getName()

 * @method string getType()

 * @package Cron\Model

 */

class Cron extends Model{

 

    const STATUS_COMPLETED = 'completed';

    const STATUS_FAILED = 'failed';

    const STATUS_INITIALIZED = 'initialized';

    const STATUS_RUNNING = 'running';

 

    protected $name = 'cron';

    protected $tableName = 'cron';

    protected $pk = 'cron_id';

 

    protected $_originalData = array();

    /**

     *  保存配置信息CLASS

     */

    protected static $_cron_classes = array();

 

 

    /**

     * @param $class

     * @return mixed  获取配置的 CLASS

     */

    public function getSingleton($class)

    {

        isset(static::$_cron_classes[$class]) or static::$_cron_classes[$class] = new $class;

        return static::$_cron_classes[$class];

    }

 

 

    /**

     * @param $cronJob

     * @return $this

     * 初始化 任务状态

     */

    public function initialize($cronJob)

    {

        foreach ($cronJob as $k => $v) {

            $this->setData($k, $v);

        }

        $now = date('Y-m-d H:i:s');

        $this->setData('status',self::STATUS_INITIALIZED)->setData('created_at',$now)->setData('updated_at',$now)->save();

        return $this;

    }

 

    /**

     * @return $this  run 命令

     */

    public function run()

    {

        $this->setData('run_at',date('Y-m-d H:i:s'))->setData('status',self::STATUS_RUNNING)->save();

        Timer::start();

        try {

            $class = $this->getData('class');

            $method = $this->getData('method');

            if (!class_exists($class)) throw new \Exception(sprintf('Class "%s" not found!', $class));

            if (!method_exists($class, $method)) throw new \Exception(sprintf('Method "%s::%s()" not found!', $class, $method));

            $callback = array($this->getSingleton($class), $method);

 

            //new CLASS 使用操作方法

            // 执行配置里的 Statistics\Model\PheanstalkModel类 的 processUntreatedQueue 操作

            call_user_func($callback);

            Timer::stop();

            $this->setData('ms',round(Timer::diff() * 1000))->setData('status',self::STATUS_COMPLETED)->save();

 

        } catch (\Exception $e) {

            Timer::stop();

            $this->setData('ms',round(Timer::diff() * 1000))

                ->setData('status',self::STATUS_FAILED)

                ->setData('error',$e->getMessage() . "\nParams:\n" . var_export($this->getDbFields(), true))->save();

            Log::write($e->getMessage() . "\n" . $e->getTraceAsString(),Log::ERR);

        }

        return $this;

    }

 

}

Common\Model 模型

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79