Programing

명령 줄에서 Zend Framework 작업 실행

lottogame 2020. 11. 27. 07:37
반응형

명령 줄에서 Zend Framework 작업 실행


Zend Framework 작업을 실행하여 명령 줄에서 일부 파일을 생성하고 싶습니다. 이것이 가능하며 ZF를 사용하는 기존 웹 프로젝트를 얼마나 변경해야합니까?

감사!


실제로 생각보다 훨씬 쉽습니다. 부트 스트랩 / 애플리케이션 구성 요소 및 기존 구성을 CLI 스크립트와 함께 재사용 할 수 있으며, HTTP 요청에서 호출되는 MVC 스택 및 불필요한 가중치를 방지 할 수 있습니다. 이것은 wget을 사용하지 않는 한 가지 장점입니다.

공개 index.php처럼 스크립트를 시작합니다.

<?php

// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH',
              realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV',
              (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
                                         : 'production'));

require_once 'Zend/Application.php';
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/config.php'
);

//only load resources we need for script, in this case db and mail
$application->getBootstrap()->bootstrap(array('db', 'mail'));

그런 다음 MVC 응용 프로그램에서와 마찬가지로 ZF 리소스를 계속 사용할 수 있습니다.

$db = $application->getBootstrap()->getResource('db');

$row = $db->fetchRow('SELECT * FROM something');

CLI 스크립트에 구성 가능한 인수를 추가하려면 Zend_Console_Getopt를 살펴보십시오.

MVC 응용 프로그램에서도 호출하는 공통 코드가있는 경우이를 개체로 래핑하고 MVC 및 명령 줄 응용 프로그램에서 해당 개체의 메서드를 호출하는 방법을 살펴보십시오. 이것은 일반적인 모범 사례입니다.


최신 정보

이 모든 코드를 https://github.com/akond/zf-cli 에서 ZF 1.12에 맞게 조정할 수 있습니다 .

솔루션 # 1은 괜찮지 만 때로는 더 정교한 것을 원합니다. 특히 하나 이상의 CLI 스크립트가있을 것으로 예상되는 경우. 허락하시면 다른 해결책을 제안하겠습니다.

우선, Bootstrap.php에

protected function _initRouter ()
{
    if (PHP_SAPI == 'cli')
    {
        $this->bootstrap ('frontcontroller');
        $front = $this->getResource('frontcontroller');
        $front->setRouter (new Application_Router_Cli ());
        $front->setRequest (new Zend_Controller_Request_Simple ());
    }
}

이 방법은 우리 자신의 라우터 Application_Router_Cli를 위해 기본 라우터에서 디스패치 제어를 박탈합니다.

덧붙여서, 웹 인터페이스에 대한 _initRoutes에서 자신의 경로를 정의했다면 명령 줄 모드에서이를 무력화하고 싶을 것입니다.

protected function _initRoutes ()
{
    $router = Zend_Controller_Front::getInstance ()->getRouter ();
    if ($router instanceof Zend_Controller_Router_Rewrite)
    {
        // put your web-interface routes here, so they do not interfere
    }
}

Application_Router_Cli 클래스 (애플리케이션 접두사에 대해 자동로드가 켜져 있다고 가정)는 다음과 같습니다.

class Application_Router_Cli extends Zend_Controller_Router_Abstract
{
    public function route (Zend_Controller_Request_Abstract $dispatcher)
    {
        $getopt = new Zend_Console_Getopt (array ());
        $arguments = $getopt->getRemainingArgs ();
        if ($arguments)
        {
            $command = array_shift ($arguments);
            if (! preg_match ('~\W~', $command))
            {
                $dispatcher->setControllerName ($command);
                $dispatcher->setActionName ('cli');
                unset ($_SERVER ['argv'] [1]);

                return $dispatcher;
            }

            echo "Invalid command.\n", exit;

        }

        echo "No command given.\n", exit;
    }


    public function assemble ($userParams, $name = null, $reset = false, $encode = true)
    {
        echo "Not implemented\n", exit;
    }
}

이제 다음을 실행하여 간단히 애플리케이션을 실행할 수 있습니다.

php index.php backup

이 경우 BackupController 컨트롤러의 cliAction 메서드가 호출됩니다.

class BackupController extends Zend_Controller_Action
{
    function cliAction ()
    {
        print "I'm here.\n";
    }
}

계속해서 Application_Router_Cli 클래스를 수정하여 매번 "cli"조치가 수행되지 않고 사용자가 추가 매개 변수를 통해 선택한 것을 수행 할 수 있습니다.

그리고 마지막으로. 화면에 html 코드가 표시되지 않도록 명령 줄 인터페이스에 대한 사용자 지정 오류 처리기를 정의합니다.

Bootstrap.php에서

protected function _initError ()
{
    $error = $frontcontroller->getPlugin ('Zend_Controller_Plugin_ErrorHandler');
    $error->setErrorHandlerController ('index');

    if (PHP_SAPI == 'cli')
    {
        $error->setErrorHandlerController ('error');
        $error->setErrorHandlerAction ('cli');
    }
}

ErrorController.php에서

function cliAction ()
{
    $this->_helper->viewRenderer->setNoRender (true);

    foreach ($this->_getParam ('error_handler') as $error)
    {
        if ($error instanceof Exception)
        {
            print $error->getMessage () . "\n";
        }
    }
}

방금 내 CP에 태그가 붙는 걸 봤어요. 이 게시물을 우연히 발견하고 ZF2를 사용하고 있다면 훨씬 쉬워졌습니다. module.config.php의 경로를 다음과 같이 편집하십시오.

/**
 * Router
 */

'router' => array(
    'routes' => array(

        // .. these are your normal web routes, look further down
    ),
),

/**
 * Console Routes
 */
'console' => array(
    'router' => array(
        'routes' => array(

            /* Sample Route */
            'do-cli' => array(
                'options' => array(
                    'route'    => 'do cli',
                    'defaults' => array(
                        'controller' => 'Application\Controller\Index',
                        'action'     => 'do-cli',
                    ),
                ),
            ),
        ),    
    ),
),

위의 구성을 사용하여 애플리케이션 모듈 아래의 IndexController.php에서 doCliAction을 정의합니다. 명령 줄에서 실행하면 케이크입니다.

php index.php do cli

끝난! 훨씬 부드럽습니다.


위의 akond의 솔루션은 최상의 경로에 있지만 그의 스크립트가 사용자 환경에서 작동하지 않을 수있는 미묘한 부분이 있습니다. 그의 대답에 대한 다음 조정을 고려하십시오.

Bootstrap.php

protected function _initRouter()
{
    if( PHP_SAPI == 'cli' )
    {
        $this->bootstrap( 'FrontController' );
        $front = $this->getResource( 'FrontController' );
        $front->setParam('disableOutputBuffering', true);
        $front->setRouter( new Application_Router_Cli() );
        $front->setRequest( new Zend_Controller_Request_Simple() );
    }
}

Init 오류는 위에 쓰여진 것처럼 아마도 barf 일 것입니다. 기본 구성을 변경하지 않는 한 오류 처리기는 아직 인스턴스화되지 않았을 것입니다.

protected function _initError ()
{
    $this->bootstrap( 'FrontController' );
    $front = $this->getResource( 'FrontController' );
    $front->registerPlugin( new Zend_Controller_Plugin_ErrorHandler() );
    $error = $front->getPlugin ('Zend_Controller_Plugin_ErrorHandler');
    $error->setErrorHandlerController('index');

    if (PHP_SAPI == 'cli')
    {
        $error->setErrorHandlerController ('error');
        $error->setErrorHandlerAction ('cli');
    }
}

또한 명령 줄에서 둘 이상의 매개 변수를 분리하고 싶을 수도 있습니다. 다음은 기본 예입니다.

class Application_Router_Cli extends Zend_Controller_Router_Abstract
{
    public function route (Zend_Controller_Request_Abstract $dispatcher)
    {
        $getopt     = new Zend_Console_Getopt (array ());
        $arguments  = $getopt->getRemainingArgs();

        if ($arguments)
        {
            $command = array_shift( $arguments );
            $action  = array_shift( $arguments );
            if(!preg_match ('~\W~', $command) )
            {
                $dispatcher->setControllerName( $command );
                $dispatcher->setActionName( $action );
                $dispatcher->setParams( $arguments );
                return $dispatcher;
            }

            echo "Invalid command.\n", exit;

        }

        echo "No command given.\n", exit;
    }


    public function assemble ($userParams, $name = null, $reset = false, $encode = true)
    {
        echo "Not implemented\n", exit;
    }
}

Lastly, in your controller, the action that you invoke make use of the params that were orphaned by the removal of the controller and action by the CLI router:

public function echoAction()
{
    // disable rendering as required
    $database_name     = $this->getRequest()->getParam(0);        
    $udata             = array();

    if( ($udata = $this->getRequest()->getParam( 1 )) )
        $udata         = explode( ",", $udata );

    echo $database_name;
    var_dump( $udata );
}

You could then invoke your CLI command with:

php index.php Controller Action ....

For example, as above:

php index.php Controller echo database123 this,becomes,an,array

You'll want to implement a more robust filtering/escaping, but, it's a quick building block. Hope this helps!


One option is that you could fudge it by doing a wget on the URL that you use to invoke the desirable action


You cant use -O option of wget to save the output. But wget is clearly NOT the solution. Prefer using CLI instead.


akond idea works great, except the error exception isnt rendered by the error controller.

public function cliAction() {
  $this->_helper->layout->disableLayout();
  $this->_helper->viewRenderer->setNoRender(true);

  foreach ($this->_getParam('error_handler') as $error) {
    if ($error instanceof Exception) {
      print "cli-error: " . $error->getMessage() . "\n";
    }
  }
}

and In Application_Router_Cli, comment off the echo and die statement

public function assemble($userParams, $name = null, $reset = false, $encode = true) {
//echo "Not implemented\n";
}

You can just use PHP as you would normally from the command line. If you call a script from PHP and either set the action in your script you can then run whatever you want.

It would be quite simple really. Its not really the intended usage, however this is how it could work if you wanted to.

For example

 php script.php 

Read here: http://php.net/manual/en/features.commandline.php


You can use wget command if your OS is Linux. For example:

wget http://example.com/controller/action

See http://linux.about.com/od/commands/l/blcmdl1_wget.htm

UPDATE:

You could write a simple bash script like this:

if wget http://example.com/controller/action
    echo "Hello World!" > /home/wasdownloaded.txt
else
    "crap, wget timed out, let's remove the file."
    rm /home/wasdownloaded.txt
fi

Then you can do in PHP:

if (true === file_exists('/home/wasdownloaded.txt') {
    // to check that the 
}

Hope this helps.


I have used wget command

wget http://example.com/module/controller/action -O /dev/null

-O /dev/null if you dont want to save the output

참고URL : https://stackoverflow.com/questions/2325338/running-a-zend-framework-action-from-command-line

반응형