2014-12-04 6 views
8

Ho un controller della console e un'azione per inviare messaggi di posta elettronica (definiti di seguito in module.config.php)Come posso creare un URL in un controller della console in ZF2?

'console' => array(
    'router' => array(
     'routes' => array(
      'cronroute' => array(
       'options' => array(
        'route' => 'sendEmails', 
        'defaults' => array(
         'controller' => 'Application\Controller\Console', 
         'action' => 'send-emails' 
        ) 
       ) 
      ),    
     ) 
    ) 
), 

Nell'azione voglio mandare una e-mail contenente un collegamento a un'altra azione sul sito. Questo normalmente verrebbe eseguito con un URL View Helper, ma poiché la richiesta è di tipo Console e non HTTP, ciò non funziona. Ho provato a creare una richiesta HTTP, ma non so come assegnargli il dominio del sito o il link Controller/Azione. Codice

mio controller:

$vhm = $this->getServiceLocator()->get('viewhelpermanager'); 
$url = $vhm->get('url'); 
$urlString = $url('communication', array('action' => 'respond', 'id' => $id, 
    array('force_canonical' => true)); 

Questo genera un errore:

====================================================================== 
    The application has thrown an exception! 
====================================================================== 
Zend\Mvc\Router\Exception\RuntimeException 
Request URI has not been set 

Come si crea una richiesta HTTP in un controller della console che ha lo schema del sito, del dominio e path/to/azione? E come posso passare all'URL View Helper?

+0

Sei riuscito a trovare una soluzione? –

+0

Non nel modo desiderato, creando una route HTTP in un controller della console. Ho finito per impostare una variabile per l'URL del sito nell'array di configurazione. – Nick

risposta

0

Aggiornamento: La risposta corretta per questo post può essere trovato qui: Stackoverflow: Using HTTP routes within ZF2 console application

bene si sta molto vicino a questo, ma non si utilizza il plugin Url. Se ti sei immerso un po 'più nella Documentazione ZF2 dei Plugin Controller, avresti potuto trovare la soluzione.

Vedere per riferimento: ZF2 Documentation - Controller plugins

vostro ConsoleController deve implementare uno dei seguenti, per essere in grado di recuperare i plugin controllore:

  1. AbstractActionController
  2. AbstractRestfulController
  3. setPluginManager

Bene Consiglio di estendere il controller con lo AbstractActionController se non lo si è ancora fatto.

Nel caso in cui si utilizza il AbstractActionController si può semplicemente chiamare $urlPlugin = $this->url() dal momento che la AbstractActionController ha un __call() implementazione recuperare il plugin per voi. Ma è anche possibile utilizzare: $urlPlugin = $this->plugin('url');

Quindi, al fine di generare l'URL per la posta è possibile effettuare le seguenti operazioni nel controller:

$urlPlugin = $this->url(); 
$urlString = $urlPlugin->fromRoute(
    'route/myroute', 
    array(
     'param1' => $param1, 
     'param2' => $param2 
    ), 
    array(
     'option1' => $option1, 
     'option2' => $option2 
    ) 
); 

È ora possibile passare questo URL al tuo viewModel o utilizzare l'URL viewHelper all'interno di viewModel, ma dipende da te.

Cerca di evitare viewHelpers all'interno del controller in quanto abbiamo plug-in disponibili per questo caso.

Nel caso in cui vi chiedete quali metodi la AbstractActionController ha, qui è ZF2 ApiDoc - AbstractActionController

Al fine di rendere questo lavoro è necessario impostare il percorso di configurazione con una struttura adeguata:

// This can sit inside of modules/Application/config/module.config.php or any other module's config. 
array(
    'router' => array(
     'routes' => array(
      // HTTP routes are here 
     ) 
    ), 

    'console' => array(
     'router' => array(
      'routes' => array(
       // Console routes go here 
      ) 
     ) 
    ), 
) 

Se hai ottenuto un modulo console, basta seguire i percorsi di instradamento della console. Non dimenticare la chiave della console con tutti i percorsi sottostanti! Date un'occhiata alla documentazione di riferimento: ZF2 - Documentation: Console routes and routing

+0

Il mio controller estende 'AbstractActionController', quindi posso chiamare' $ this-> url(); 'per ottenere il plugin. Ma quando chiamo '$ urlPlugin-> fromRoute ('route', array());' guarda solo nella console array() in module.config.php per i percorsi. La rotta che voglio creare è nel router regolare => array (routes => array()). Il che significa che ora ho ricevuto l'errore "Rotta con nome" comunicazione "non trovata". Penso che sia ancora perché il plugin URL funziona per le richieste HTTP, ma non mentre è nella console. – Nick

+0

http://framework.zend.com/manual/2.0/en/modules/zend.console.routes.html, non dimenticare la chiave (console) all'interno di 'routes.config.php'. Spero che questo ti aiuti. Aggiornerà la risposta. – Kwido

+1

Ma la rotta che desidero non è nei percorsi di instradamento della console. Voglio creare un percorso dai percorsi regolari del router. Devo inserire un URL nel mio sito Web nel corpo di un'email che viene inviata da un processo cron che chiama un percorso nei percorsi della console. Sembra che non sia possibile avere accesso ai percorsi HTTP da una rotta della console. – Nick

0

Ecco come questo problema può essere risolto:

<?php 

// Module.php 

use Zend\View\Helper\ServerUrl; 
use Zend\View\Helper\Url as UrlHelper; 
use Zend\Uri\Http as HttpUri; 
use Zend\Console\Console; 
use Zend\ModuleManager\Feature\ViewHelperProviderInterface; 

class Module implements ViewHelperProviderInterface 
{ 

    public function getViewHelperConfig() 
    { 
     return array(
      'factories' => array(
       'url' => function ($helperPluginManager) { 
        $serviceLocator = $helperPluginManager->getServiceLocator(); 
        $config = $serviceLocator->get('Config'); 

        $viewHelper = new UrlHelper(); 

        $routerName = Console::isConsole() ? 'HttpRouter' : 'Router'; 

        /** @var \Zend\Mvc\Router\Http\TreeRouteStack $router */ 
        $router = $serviceLocator->get($routerName); 

        if (Console::isConsole()) { 
         $requestUri = new HttpUri(); 
         $requestUri->setHost($config['website']['host']) 
          ->setScheme($config['website']['scheme']); 
         $router->setRequestUri($requestUri); 
        } 

        $viewHelper->setRouter($router); 

        $match = $serviceLocator->get('application') 
         ->getMvcEvent() 
         ->getRouteMatch(); 

        if ($match instanceof RouteMatch) { 
         $viewHelper->setRouteMatch($match); 
        } 

        return $viewHelper; 
       }, 
       'serverUrl' => function ($helperPluginManager) { 
        $serviceLocator = $helperPluginManager->getServiceLocator(); 
        $config = $serviceLocator->get('Config'); 

        $serverUrlHelper = new ServerUrl(); 
        if (Console::isConsole()) { 
         $serverUrlHelper->setHost($config['website']['host']) 
          ->setScheme($config['website']['scheme']); 
        } 

        return $serverUrlHelper; 
       }, 
      ), 
     ); 
    } 
} 

Naturalmente si devono definire i valori di accoglienza e schema predefinito in configurazione dal momento che non c'è modo di rilevarli automaticamente in modalità console.

+1

Grazie per la soluzione! L'ho postato di nuovo nel caso in cui la tua applicazione non sia in esecuzione nella directory principale '/' dopo il dominio: http://stackoverflow.com/questions/27295895/how-can-i-create-a-url-in -a-console-Controller-in-ZF2/30.614.363 30.614.363 # – Athlan

0

Non riesco a crederci, ma l'ho fatto :)

Spero che funzionerà per tutti voi.

controller in cui viene utilizzata la funzione fromRoute() ho aggiunto queste righe sotto:

$event = $this->getEvent(); 
    $http = $this->getServiceLocator()->get('HttpRouter'); 
    $router = $event->setRouter($http); 
    $request = new \Zend\Http\Request(); 
    $request->setUri(''); 
    $router = $event->getRouter(); 
    $routeMatch = $router->match($request); 

    var_dump($this->url()->fromRoute(
         'route_parent/route_child', 
         [ 
          'param1' => 1, 
          'param2' => 2, 
         ) 
    ); 

uscita:

//mydomain.local/route-url/1/2 

Naturalmente route_parent/route_child non è un percorso console, ma HTTP percorso:)

0

Grazie a @Alexey Kosov per la risposta. Probabilmente avrai un problema quando la tua applicazione lavora in sottodirectory piuttosto che nella directory root dopo il dominio '/'.

si deve aggiungere:

$router->setBaseUrl($config['website']['path']); 

codice totale:

<?php 

// Module.php 

use Zend\View\Helper\ServerUrl; 
use Zend\View\Helper\Url as UrlHelper; 
use Zend\Uri\Http as HttpUri; 
use Zend\Console\Console; 
use Zend\ModuleManager\Feature\ViewHelperProviderInterface; 

class Module implements ViewHelperProviderInterface 
{ 

    public function getViewHelperConfig() 
    { 
     return array(
      'factories' => array(
       'url' => function ($helperPluginManager) { 
        $serviceLocator = $helperPluginManager->getServiceLocator(); 
        $config = $serviceLocator->get('Config'); 

        $viewHelper = new UrlHelper(); 

        $routerName = Console::isConsole() ? 'HttpRouter' : 'Router'; 

        /** @var \Zend\Mvc\Router\Http\TreeRouteStack $router */ 
        $router = $serviceLocator->get($routerName); 

        if (Console::isConsole()) { 
         $requestUri = new HttpUri(); 
         $requestUri->setHost($config['website']['host']) 
          ->setScheme($config['website']['scheme']); 
         $router->setRequestUri($requestUri); 
         $router->setBaseUrl($config['website']['path']); 
        } 

        $viewHelper->setRouter($router); 

        $match = $serviceLocator->get('application') 
         ->getMvcEvent() 
         ->getRouteMatch(); 

        if ($match instanceof RouteMatch) { 
         $viewHelper->setRouteMatch($match); 
        } 

        return $viewHelper; 
       }, 
       'serverUrl' => function ($helperPluginManager) { 
        $serviceLocator = $helperPluginManager->getServiceLocator(); 
        $config = $serviceLocator->get('Config'); 

        $serverUrlHelper = new ServerUrl(); 
        if (Console::isConsole()) { 
         $serverUrlHelper->setHost($config['website']['host']) 
          ->setScheme($config['website']['scheme']); 
        } 

        return $serverUrlHelper; 
       }, 
      ), 
     ); 
    } 
} 
0

ho avuto un problema simile con console Zend - l'aiutante serverUrl vista, inoltre, non ha lavorato correttamente per impostazione predefinita.


Il mio caso:

/module/Application/src/Application/Controller/ConsoleController.php

... 
public function someAction() 
{ 
    ... 
    $view = new ViewModel([ 
     'data' => $data, 
    ]); 
    $view->setTemplate('Application/view/application/emails/some_email_template'); 
    $this->mailerZF2()->send(array(
     'to' => $data['customer_email'], 
     'subject' => 'Some email subject', 
    ), $view); 
    ... 
} 

/module/Application/view/application/emails/some_email_template.phtml

<?php 
/** @var \Zend\View\Renderer\PhpRenderer $this */ 
/** @var array $data */ 
?><!doctype html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
    <link ... rel="stylesheet" /> 
    <title>...</title> 
</head> 
<body> 
<div style="..."> 
    ... <a href="<?= $this->serverUrl() ?>"><img src="<?= $this->serverUrl() ?>/images/logo-maillist.png" width="228" height="65"></a> ... 
    <p>Hello, <?= $this->escapeHtml($data['customer_name']) ?>!</p> 
    <p>... email body ...</p> 
    <div style="..."> 
     <a href="<?= $this->serverUrl() ?>/somepath/<?= $data['some-key'] ?>" style="...">some action</a> ... 
    </div> 
    ... 
</div> 
</body> 
</html> 

L'helper vista serverUrl restituisce solo "http://" u nder Console Controller (runned by cron). Ma lo stesso modello viene visualizzato correttamente nelle richieste HTTP web gestite da altri controller.


ho riparato in questo modo:

/config/autoload/global.php

return array(
    ... 
    'website' => [ 
     'host' => isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'my.production.domain', 
     'scheme' => 'https', 
     'path' => '', 
    ], 
); 

/config/autoload/local.php

return array(
    ... 
    'website' => [ 
     'host' => isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'my.local.domain', 
    ], 
); 

/public/index.php (the ZF2 engine starting script)

chdir(dirname(__DIR__)); 

// --- Here is my additional code --------------------------- 
if (empty($_SERVER['HTTP_HOST'])) { 
    function array_merge_recursive_distinct(array &$array1, array &$array2) 
    { 
     $merged = $array1; 
     foreach ($array2 as $key => &$value) { 
      if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) { 
       $merged[$key] = array_merge_recursive_distinct($merged[$key], $value); 
      } else { 
       $merged[$key] = $value; 
      } 
     } 
     return $merged; 
    } 

    $basicConfig = require 'config/autoload/global.php'; 
    $localConfig = @include 'config/autoload/local.php'; 
    if (!empty($localConfig)) { 
     $basicConfig = array_merge_recursive_distinct($basicConfig, $localConfig); 
    } 
    unset($localConfig); 

    $_SERVER['HTTP_HOST'] = $basicConfig['website']['host']; 
    $_SERVER['HTTP_SCHEME'] = $basicConfig['website']['scheme']; 
    $_SERVER['HTTPS'] = $_SERVER['HTTP_SCHEME'] === 'https' ? 'on' : ''; 
    $_SERVER['SERVER_NAME'] = $_SERVER['HTTP_HOST']; 

    unset($basicConfig); 
} 
// ---/End of my additional code --------------------------- 

// Setup autoloading 
require 'init_autoloader.php'; 
... 

E questo è tutto quello che ho cambiato.

Magico! Funziona! :-)

Spero che questo aiuti anche a qualcuno.

Problemi correlati