2008-09-27 138 views
20

我正在嘗試編寫一個cronjob控制器,因此我可以調用一個網站並執行所有模塊cronjob.php。現在我的問題是我該怎麼做?使用Zend Framework創建cronjob

捲曲是一個選項,所以我也可以算錯誤和成功?

[更新]

我想我沒有足夠的解釋。

我想要做的是有一個文件,我可以從http://server/cronjob調用,然後使其執行每個/application/modules/*/controller/CronjobController.php或有另一種方式做到這一點,因此所有的cronjobs aren不是在一個地方,而是在模塊所在的同一個地方。這會給我帶來好處,如果一個模塊不存在,它不會嘗試運行它的cronjob。

現在我的問題是,你將如何執行所有的模塊CronjobController或者你會做一個完全不同的方式,所以它仍然保持模塊化?

而且我希望能夠giveout多少cronjobs成功運行,並且有多少沒

回答

6

我要提醒把你cronjobs向公衆開放的,因爲他們可以正常的時間之外觸發,並根據他們做什麼,導致問題(我知道這不是你想要的,但是通過將它們放入實際的控制器中,它可以從瀏覽器訪問)。例如,我有一個發送電子郵件的cron。如果有人發現cron URL並剛剛開始觸發它,我會被不斷髮送垃圾郵件。

我做的是做一個cron文件夾,並在那裏創建了一個heartbeat.php,它爲我引導了Zend Framework(減去MVC)。它檢查一個數據庫,該數據庫包含所有已安裝的cron作業的列表,如果是時候運行它們,則生成一個cron作業類的實例並運行它。

的cron作業是從抽象的cron類,它具有像安裝(),運行(),停止()方法等只是子類

要火了我的工作,我只是有一個簡單的crontab條目每5分鐘運行一次heartbeat.php。到目前爲止,它在兩個不同的網站上工作得很好。

+0

我思考濫用的東西,但已經到了一個簡單的解決方案。通過只允許一些IP運行cronjob(在我的情況下只是127.0.0.1)我得到我需要的安全.. 全球cronjob類是一個interessting想法:) – Thomaschaaf 2008-09-27 14:23:01

2

前幾天有人提到this blog entry上fw-general(我建議您在使用Zend Framework時閱讀mailinglist)。

還有一個建議Zend_Controller_Request_Cli,應該遲早解決這個問題。

+0

我也喜歡這個解決方案。在我的博客上查看此腳本的更新版本:http://webdevbyjoss.blogspot.com/2010/09/running-zend-framework-application-from.html – webdevbyjoss 2011-09-22 15:11:52

0

你有文件系統訪問模塊的目錄嗎?您可以迭代目錄並確定CronjobController.php的可用位置。然後,您可以使用Zend_Http_Client通過HTTP訪問控制器,也可以使用類似Zend_Test_PHPUnit的方法:在本地模擬實際調度過程。

0

您可以設置一個數據庫表來保存對cronjob腳本的引用(在您的模塊中),然後在通過/失敗時使用帶有返回值的exec命令。

+0

我正在尋找一些可以在windows和linux上工作的東西改變,所以一切都必須在PHP中 – Thomaschaaf 2008-09-28 08:00:35

1

爲什麼不只是創造一個crontab.php,包括,或要求的index.php引導文件?

考慮到引導正在執行Zend_Loader::registerAutoload(),你就可以開始直接與模塊的工作,例如,myModules_MyClass::doSomething();

你跳過控制器的方式。控制器作業是通過http控制訪問。在這種情況下,您不需要控制器方法,因爲您正在本地訪問。

12

一些研究,我來簡單的結論,你的Zend Framework應用程序一個ZF-美化版的cron腳本應該包含所有的功能,很多拖延之後 - 沒有所有的觀點的東西。我通過在我的應用程序目錄中創建一個新的cronjobfoo.php文件來完成此任務。然後,我把最起碼的: -My前端控制器(index.php文件) -My bootstrap.php中

我拿出所有的視圖的東西,專注於保持環境的設置,DB設置,自動加載機,&註冊表建立。我不得不花一點時間來糾正文檔根變量,並刪除從引導程序複製的一些OO功能。

之後,我只是編碼的路程。在我的情況下,它被編譯並通過電子郵件發送出去夜間報告。使用Zend_Mail真是太棒了。當我確信我的腳本以我想要的方式工作時,我只是將它添加到了我的crontab中。

祝你好運!

9

對於Zend框架我目前使用的波紋管中列出的代碼。該腳本只包含門戶文件index.php,其中所有路徑,環境和其他Zendy代碼都被引導。通過在cron腳本中定義一個常量,我們取消了運行應用程序的最後一步。

這意味着應用程序僅設置,甚至沒有自舉。在這一點上,我們開始的Bootstrap我們需要的資源,那就是

//public/index.php 

if(!defined('DONT_RUN_APP') || DONT_RUN_APP == false) { 
    $application->bootstrap()->run(); 
} 

// application/../cron/cronjob.php 

define("DONT_RUN_APP",true); 
require(realpath('/srv/www/project/public/index.php')); 
$application->bootstrap('config'); 
$application->bootstrap('db'); 

//cron code follows 
0

我伸出格雷戈爾答案與this post。這一下就出來了:

//public/index.php 

// Run application, only if not started from command line (cli) 
if (php_sapi_name() != 'cli' || !empty($_SERVER['REMOTE_ADDR'])) { 
    $application->run(); 
} 

感謝格雷戈爾!

0

我的解決辦法:

  • 捲曲/ cron的
  • 全球的cron方法include_once所有控制器
  • 檢查每個controllors是否有 - > cron的方法
  • 如果他們有,運行這些。

public cron url(curl)不是問題,有很多方法可以避免濫用。如上所述,檢查遠程IP是最簡單的。

2

我有權訪問專用服務器,並且最初爲cron作業有不同的引導程序。我最終討厭這個想法,只是希望我可以在現有的MVC設置中做到這一點,而不必擔心移動事物。

我創建了一個文件cron.sh,保存在我的網站根目錄(不公開),並在其中我把我想要運行的一系列命令。因爲我想一次運行許多命令,所以我像往常一樣在控制器中編寫了PHP,並將curl調用添加到cron.sh中的這些URL中。例如curl http://www.mysite.com/cron_controller/action然後在cron界面我跑bash /path/to/cron.sh

正如其他人指出的那樣,任何猜測url的人都可以解僱你的cron,所以總會有這樣的警告。您可以通過許多不同的方式找到解決方案。

0

這是我的方式來與Zend框架運行cron任務

引導我會保持環境設置,因爲它是零下MVC:

public static function setupEnvironment() 
{ 
    ... 
    self::setupFrontController(); 
    self::setupDatabase(); 
    self::setupRoutes(); 
    ... 
    if (PHP_SAPI !== 'cli') { 
      self::setupView(); 
      self::setupDbCaches(); 
    } 
    ... 
} 

此外,在引導,我將修改setupRoutes並添加自定義路由:

public function setupRoutes() 
{ 
    ... 
    if (PHP_SAPI == 'cli') { 
     self::$frontController->setRouter(new App_Router_Cli()); 
     self::$frontController->setRequest(new Zend_Controller_Request_Http());   
    } 
} 

App_Router_Cli是一種新的路由器類型,它根據這種類型的請求確定控制器,動作和可選參數:script.php controller=mail action=send。我發現這裏新的路由器:Setting up Cron with Zend Framework 1.11

class App_Router_Cli extends Zend_Controller_Router_Abstract 
{ 
    public function route (Zend_Controller_Request_Abstract $dispatcher) 
    { 
     $getopt = new Zend_Console_Getopt (array()); 
     $arguments = $getopt->getRemainingArgs(); 
     $controller = ""; 
     $action = ""; 
     $params = array(); 

     if ($arguments) { 

      foreach($arguments as $index => $command) { 

       $details = explode("=", $command); 

       if($details[0] == "controller") { 
        $controller = $details[1]; 
       } else if($details[0] == "action") { 
        $action = $details[1]; 
       } else { 
        $params[$details[0]] = $details[1]; 
       } 
      } 

      if($action == "" || $controller == "") { 
       die("Missing Controller and Action Arguments == You should have: 
        php script.php controller=[controllername] action=[action]"); 
      } 
      $dispatcher->setControllerName($controller); 
      $dispatcher->setActionName($action); 
      $dispatcher->setParams($params); 

      return $dispatcher; 
     } 
     echo "Invalid command.\n", exit; 
     echo "No command given.\n", exit; 
    } 

    public function assemble ($userParams, $name = null, $reset = false, $encode = true) 
    { 
     throw new Exception("Assemble isnt implemented ", print_r($userParams, true)); 
    } 
} 

CronController我做一個簡單的檢查:

public function sendEmailCliAction() 
{ 
    if (PHP_SAPI != 'cli' || !empty($_SERVER['REMOTE_ADDR'])) { 
     echo "Program cannot be run manually\n"; 
     exit(1); 
    } 
    // Each email sent has its status set to 0; 

crontab的運行這樣的命令:

* * * * * php /var/www/projectname/public/index.php controller=name action=send-email-cli >> /var/www/projectname/application/data/logs/cron.log