Nette a PHP-CLI

před 10 lety

Ondrej
Člen | 110
+
0
-

Chcete nette aplikaci spustit z příkazové řádky např. cronem?

Udělal jsem routu do Nette, která nepracuje s HTTP požadavkem, ale s parametry předané z příkazové řádky.

Prvně je nutné patchnout Application.php (pokud oprava již není v distribuci)
https://forum.nette.org/cs/2014-php-cli?…

Do bootstrap jako první routu přiřadit

$router[] = new PHPCLIRoute();

syntaxe PHP CLI volání:

$ php document_root/index.php Module:Presenter:Action param1=value param2=value

PHPCLIRoute.php

/**
 * Route for PHP CLI
 *
 * Copyright (c) 2009 Ondrej Novak
 *
 */
class PHPCLIRoute extends Object implements IRouter
{
    /**
     * @param  IHttpRequest - interface parameter. We dont use in this method.
     * @return PresenterRequest|NULL
     */
    public function match(IHttpRequest $httpRequest)
        {

        if(!Environment::isConsole()) return NULL;
        $argv = $GLOBALS['argv'];
        if(count($argv) < 2) throw new InvalidStateException('Missing presenter in arguments definition.');

        // module:presenter:action parser
        $arr = explode(':', $argv[1]);
        $action = end($arr);
        unset($arr[count($arr)-1]);
        $presenter = join(':', $arr);

        $params = array();
        $params['action'] = $action;

        // process script arguments
        for($i = 2; $i < count($argv); $i++) {
            $p = explode('=', $argv[$i], 2); // $p[0] - variable, $p[1] - value
            $params[$p[0]] = $p[1];
        }

    return new PresenterRequest(
            $presenter,
            NULL,
                    $params,
            array(),
            array(),
            array()
        );
    }



    /**
     * Constructs absolute URL from PresenterRequest object.
         * Empty method for PHP CLI.
     * @param  IHttpRequest
     * @param  PresenterRequest
     * @return string|NULL
     */
    public function constructUrl(PresenterRequest $appRequest, IHttpRequest $httpRequest)
    {
        return NULL;
    }

}

Editoval Ondrej (6. 7. 2009 20:04)

před 10 lety

David Grudl
Nette Core | 6798
+
0
-

Vyloženě mě nikdy nenapadlo pod Nette dělat CLI aplikace, ale takových požadavků se sešlo víc, tak jsem experimentálně CliRouter přidal, podobný tvému.

$application = Environment::getApplication();
$application->allowedMethods = NULL;
$application->router[] = new CliRouter;

Parsování parametrů by mělo rozumět zápisu třeba:

php.exe index.phpc homepage:default --verbose -user "john doe" "-pass=se cret" /wait

jde na Homepage:default s parametry:
'verbose' => TRUE,
'user' => 'john doe',
'pass' => 'se cret',
'wait' => TRUE

před 9 lety

mcmatak
Člen | 492
+
0
-

sory za blbý dotaz, ale k čemu je potřeba to spouštět z příkazové řádky? nevyjde to stejně jako cronem volat http požadavek?

před 9 lety

JakubKohout
Člen | 101
+
0
-

nevyjde protože když bys to pouštěl přes http požadavek například pomocí WGET, tak máš několik omezení.

  1. Musel by jsi spřístupnit tyto skripty z venku, a tudíž řešit autentizaci serveru
  2. Jsi omezem časem pro běh php skriptu, u CLI tomu tak není.
  3. a zbytečně vytěžuješ apachovský vlákno

před 9 lety

mcmatak
Člen | 492
+
0
-

ok, chápu

  1. jasně to řeším nějakým hashem v url, ale ok máš pravdu, na druhou stranu mi to dovoluje ručně spouštět ty skripty, když se třeba z n ějakého důvodu neprovede nebo ho potřebuji provést mimo stanovený čas
  2. ok rozumím, sice mám povolený set_time_limit ale chápu, že to může být problém
  3. vytěžuješ apachovský vlákno… asi jedině tady moc nevidím tu výhodu, co to v praxi znamená? je to nějak měřitelné? jestli to zpracovává apache nebo cli?

před 9 lety

JakubKohout
Člen | 101
+
0
-

Vždyť ty je můžeš pouštět ručně. Stačí dát ./nazev_skriptu.php

No ten dotaz musí jít skrz apache kterej ho musí zpracovat. Například problém když se pokusíš odeslat email a nastane prodleva u odesílání (problém například na u postfixu), tak to sestřelí celej virtualhost (aspoň tohle se mi děje teď na serveru pokud se pokusím odeslat email)

před 9 lety

mcmatak
Člen | 492
+
0
-

Ručně jsem myslel, administrátor nějakého systému, ne ten kdo má přístup na konzoli. Takže právě přes http.

Ale jinak to chápu, nicméně asi stále zůstanu u http cronu…

před 9 lety

iguana007
Člen | 988
+
0
-

dRaGen napsal(a):

  1. Jsi omezem časem pro běh php skriptu, u CLI tomu tak není.

Tak toto jsem netušil, to je pro mne novinka a určitě příjemná :)

před 9 lety

edke
Člen | 198
+
0
-

David Grudl wrote:

Vyloženě mě nikdy nenapadlo pod Nette dělat CLI aplikace, ale takových požadavků se sešlo víc, tak jsem experimentálně CliRouter přidal, podobný tvému.

$application = Environment::getApplication();
$application->allowedMethods = NULL;
$application->router[] = new CliRouter;

Parsování parametrů by mělo rozumět zápisu třeba:

php.exe index.phpc homepage:default --verbose -user "john doe" "-pass=se cret" /wait

jde na Homepage:default s parametry:
'verbose' => TRUE,
'user' => 'john doe',
'pass' => 'se cret',
'wait' => TRUE

Je mozne pre CliRouter predat nejake defaults ? Podla API konstruktor vyzaduje pole, ale mam pocit, ze kod

$application->router[] = new CliRouter(array(
    'module' => 'Console',
    'presenter' => 'Action',
    ));

nebude mat ziaden vplyv.

Rad by som totiz mal CLI related presenteri oddelene v samostatnom Module v aplikacii a spustal skript ako

./script.php syncdb --confirm

a nie

./script.php Console:Action:syncdb --confirm

před 9 lety

edke
Člen | 198
+
0
-

Pomohla by uprava CliRouter napriklad takto:

const PRESENTER_KEY = 'presenter';


/**
 * Maps command line arguments to a PresenterRequest object.
 * @param  IHttpRequest
 * @return PresenterRequest|NULL
 */
public function match(IHttpRequest $httpRequest)
{
    ....

    $presenter = $params[self::PRESENTER_KEY];
    if ($a = strrpos($presenter, ':')) {
        $params[self::PRESENTER_KEY] = substr($presenter, $a + 1);
        $presenter = substr($presenter, 0, $a);
    }

    if ( isset($params['module']))
    {
        $presenter= $params['module'].':'.ucfirst($presenter);
    }

    return new PresenterRequest(
        $presenter,
        'CLI',
        $params
    );

V cli skripte by sa CliRouter potom nastavil takto:

$application->router[] = new CliRouter(array(
    'module' => 'Console',
    'presenter' => 'Default',
    'action' => 'default'
    ));

a mame pekne spravanie cli skriptu. pri prvom spusteni bez parametrov sa pusta Console:Default:default, ktory zobrazi napovedu.

Jednotlive akcie potom ako:
./script.php action [options] → Console:Action:default

Editoval edke (16. 2. 2010 15:28)

před 9 lety

Honza Kuchař
Backer | 1649
+
0
-

Nechcete to přidat do extras?

před 9 lety

edke
Člen | 198
+
0
-

honzakuchar wrote:

Nechcete to přidat do extras?

Ja som si to uz upravil do podoby extended triedy, nech mozem lahko updatovat nette bez zasahov. Ak ma niekto zaujem, mozem to tu postnut. Nevyzera to nejako elegantne, ale hlavne to funguje :)