I have the following module.config.php :
return [
'router' => [
'routes' => [
'landingpage' => [
'type' => Segment::class,
'options' => [
'route' => '/landingpage[/:action/:id]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]*'
],
'defaults' => [
'controller' => Controller\LandingPageController::class,
'action' => 'index'
]
],
'may_terminate' => true,
]
]
],
'controllers' => [
'factories' => [
Controller\LandingPageController::class => LandingPageControllerFactory::class
]
],
'service_manager' => [
'invokables' => [
'LandingPage\Service\LandingPageService' => 'LandingPage\Service\LandingPageService'
]
]
];
I am trying to use the following route and it doesn't work:
http://localhost:8081/landingpage/show/1CGe2cveQ
If I use the following route it works :
http://localhost:8081/landingpage/show
If I use the previous route with a / it doesn't work:
http://localhost:8081/landingpage/show/
If you need more info let me know.
Thanks.
You have a double slash in the route declaration: the route is matched by /landingpage/ followed by /:action/:id. If you remove this double slash, the route will work as expected.
'route' => '/landingpage[/:action/:id]',
Moreover, I'd suggest you to modify the route declaration to make the id optional:
'route' => '/landingpage[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]+'
]
Tested:
config
'landingpage' => [
'type' => Segment::class,
'options' => [
'route' => '/landingpage[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]*'
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index'
]
],
'may_terminate' => true,
],
IndexController:
public function indexAction () {
print '<pre>' . print_r($this->params()->fromRoute(), true);
die();
}
public function showAction(){
print '<pre>' . print_r($this->params()->fromRoute(), true);
die();
}
Calling /landingpage
Array
(
[controller] => Application\Controller\IndexController
[action] => index
)
Calling /landingpage/show
Array
(
[controller] => Application\Controller\IndexController
[action] => show
)
Calling /landingpage/show/1CGe2cveQ
Array
(
[controller] => Application\Controller\IndexController
[action] => show
[id] => 1CGe2cveQ
)
Don't forget to clear the configuration cache, if it enabled ;)
I want to build a Zend-3-MVC application which can handle SOAP requests. It should therefore act as an SOAP server.
First of all I created the following controller:
<?php
namespace MyProject\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Soap\AutoDiscover as WsdlAutoDiscover;
use Zend\Soap\Server as SoapServer;
class SoapController extends AbstractActionController
{
public function wsdlAction()
{
$request = $this->getRequest();
$wsdl = new WsdlAutoDiscover();
$this->populateServer($wsdl);
$response = $this->getResponse();
$response->getHeaders()->addHeaderLine('Content-Type', 'application/wsdl+xml');
$response->setContent($wsdl->toXml());
return $response;
}
public function serverAction()
{
$request = $this->getRequest();
$server = new SoapServer(
$this->url()
->fromRoute('soap/wsdl', [], ['force_canonical' => true]),
[
'actor' => $this->url()
->fromRoute('soap/server', [], ['force_canonical' => true]),
]
);
$server->setReturnResponse(true);
$this->populateServer($server);
$soapResponse = $server->handle($request->getContent());
$response = $this->getResponse();
$response->getHeaders()->addHeaderLine('Content-Type', 'application/soap+xml');
$response->setContent($soapResponse);
return $response;
}
}
And this is my router.global.php in config/autoload:
<?php
use Zend\Router\Http\Literal;
return [
'router' => [
'routes' => [
'soap' => [
'type' => Literal::class,
'options' => [
'route' => '/soap',
],
'may_terminate' => false,
'child_routes' => [
'wsdl' => [
'type' => Literal::class,
'options' => [
'route' => '/wsdl',
'defaults' => [
'controller' => \MyProject\Controller\SoapController::class,
'action' => 'wsdl',
],
],
'may_terminate' => true,
],
],
],
],
],
];
And now I make an SOAP GET request to
https://example.com/soap/wsdl
But the route can't be resolved. I expect that the wsdlAction method is called but I only get a 404.
You need to register your controller also.
use Zend\ServiceManager\Factory\InvokableFactory;
'controllers' => [
'factories' => [
MyProject\Controller\SoapController::class => InvokableFactory::class
],
],
So, now your code should be :
use Zend\Router\Http\Literal;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'controllers' => [
'factories' => [
MyProject\Controller\SoapController::class => InvokableFactory::class
],
],
'router' => [
'routes' => [
'soap' => [
'type' => Literal::class,
'options' => [
'route' => '/soap',
],
'may_terminate' => false,
'child_routes' => [
'wsdl' => [
'type' => Literal::class,
'options' => [
'route' => '/wsdl',
'defaults' => [
'controller' => MyProject\Controller\SoapController::class,
'action' => 'wsdl',
],
],
'may_terminate' => true,
],
],
],
],
],
];
I'm having trouble adding an optional parameter to my home route.
This is my current router:
'routes' => [
'home' => [
'type' => Segment::class,
'options' => [
'route' => '/[:salon/]',
'constraints' => [
'salon' => '[a-zA-Z][a-zA-Z0-9_-]*'
],
'defaults' => [
'controller' => 'Application\Controller\Index',
'action' => 'index',
'salon' => 'test'
],
],
],
'application' => [
'type' => Segment::class,
'options' => [
'route' => '/application[/:controller[/:action]]',
'constraints' => [
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
],
'defaults' => [
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Application\Controller\Index',
'action' => 'index',
],
],
'may_terminate' => true,
'child_routes' => [
'default' => [
'type' => 'wildcard'
]
]
],
],
My Controller:
<?php
namespace Application\Controller;
class IndexController extends AbstractController
{
public function indexAction()
{
var_dump($this->params('salon'));
die;
}
}
domain.ltd/
This works and I'm getting default value for salon paramter which is 'test'
domain.ltd/test123
Expected value would be 'test123' but this displays me 404 error: The requested URL could not be matched by routing.
I've got a basic Yii2 project, in which i created a separate module "rest". I have set up urlManager in config/web.php file. It works fine for common url, but it seems to me it is not working with url starting with my module name: rest/.. I have actionAuth() in AuthController in my rest module, and it is accessible with this url: test.ru/auth/auth. But i want it to be accessible with this url:test.ru/auth. I tried to write like this in web.php :
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\auth',
'extraPatterns' => [
'POST /' => 'auth',
],
'pluralize' => false,
],
],
],
But it does not work(not found error in browser).
I also tried like this:
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\auth',
'extraPatterns' => [
'POST rest/auth' => 'auth',
],
'pluralize' => false,
],
],
],
It seems to me that urlManager does not want to work for module. Next i tried to write the same code in my Module.php in rest/ directory. But it produced many errors. I think because of the same error things like that dont work too:`
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\city',
'extraPatterns' => [
'DELETE {id}' => 'delete',
],
`
So my question is: how to set up urlManager for module in Yii2? I need to configure HTTP DELETE method, post methods work without any settings in urlManager.
The whole web.php file:
<?php
$params = require(__DIR__ . '/params.php');
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'language' => 'ru',
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'xxxxxxx',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
// 'loginUrl' => ['site/login'],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => require(__DIR__ . '/db.php'),
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\user',
'except' => ['delete', 'create', 'update', 'index'],
'extraPatterns' => [
'GET all' => 'all',
]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\auth',
'extraPatterns' => [
'POST reg' => 'reg',
'POST auth' => 'auth',
'POST rest/auth' => 'auth',
],
'pluralize' => false,
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\city',
'extraPatterns' => [
'DELETE {id}' => 'delete',
],
],
],
],
'i18n' => [
'translations' => [
'*' => [
'class' => 'yii\i18n\PhpMessageSource',
// 'basePath' => '#app/messages', // if advanced application, set #frontend/messages
'sourceLanguage' => 'en',
'fileMap' => [
//'main' => 'main.php',
],
],
],
],
],
'modules' => [
'admin' => [
'class' => 'app\modules\admin\Module',
],
'manager' => [
'class' => 'app\modules\manager\Module',
],
'rest' => [
'class' => 'app\modules\rest\Module',
],
'rbac' => [
'class' => 'mdm\admin\Module',
'controllerMap' => [
'assignment' => [
'class' => 'mdm\admin\controllers\AssignmentController',
/* 'userClassName' => 'app\models\User', */
'idField' => 'id',
'usernameField' => 'username',
],
],
'layout' => 'left-menu',
'mainLayout' => '#app/views/layouts/admin.php',
]
],
'aliases' => [
//'#mdm/admin' => 'app/mdm/admin',
],
'params' => $params,
];
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
}
return $config;
My Module.php code(commented code shows my attempt to write urlManager):
<?php
namespace app\modules\rest;
/**
* rest module definition class
*/
class Module extends \yii\base\Module
{
/**
* #inheritdoc
*/
public $controllerNamespace = 'app\modules\rest\controllers';
/**
* #inheritdoc
*/
public function init()
{
parent::init();
// custom initialization code goes here
\Yii::$app->user->enableSession = false;
$config = [
'components' => [
'basePath' => dirname(__DIR__),
// 'user' => [
// 'identityClass' => 'app\models\User',
// 'class' => 'app\models\User',
// 'enableSession' => false
// ],
// 'urlManager' => [
// 'enablePrettyUrl' => true,
// 'enableStrictParsing' => true,
// 'showScriptName' => false,
// 'rules' => [
// [
// 'class' => 'yii\rest\UrlRule',
// 'controller' => 'rest\city',
// 'extraPatterns' => [
// 'DELETE {id}' => 'delete',
// ],
// ],
// ],
// ],
'response' => [
'format' => \yii\web\Response::FORMAT_JSON,
'charset' => 'UTF-8',
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if(( $response->statusCode >= 200) && ( $response->statusCode < 300)) {
if(isset($response->data['_appErr'])) {
unset($response->data['_appErr']);
$response->data = [
'success' => false,
'error' => $response->data,
'data' => null,
];
} else {
$response->data = [
'success' => $response->isSuccessful,
'error' => null,
'data' => $response->data,
];
}
} else {
if($response->statusCode == 401) {
$response->data = [
'success' => false,
'error' => [
'code' => 9,
'message' => 'Unauthorized',
'user_msg' => 'You need to be authorized',
],
'data' => null,
];
}
// else {
// $response->data = [
// 'success' => false,
// 'error' => [
// 'code' => 1,
// 'message' => 'server has returned '.$response->statusCode.' error',
// ],
// 'data' => null,
// ];
// }
}
},
],
],
];
\Yii::configure(\Yii::$app, $config);
}
}
Try this:
namespace yii\rest;
class UrlRule extends Object implements UrlRuleInterface {
public function parseRequest($manager, $request) {
list($e1, $e2) = sscanf($request->getPathInfo(), '%[a-zA-Z]/%[a-zA-Z]');
if ($e1 === 'auth' && $e2 === '') {
return ['/auth/auth', $request->queryParams];
}
return false;
}
}
Use forward slash(/) while defining the controller value in the rules array.
This will work:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest/user',
'except' => ['delete', 'create', 'update', 'index'],
'extraPatterns' => [
'GET all' => 'all',
]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest/auth',
'extraPatterns' => [
'POST reg' => 'reg',
'POST auth' => 'auth',
],
'pluralize' => false,
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest/city',
'extraPatterns' => [
'DELETE {id}' => 'delete',
],
],
]
Check out the documentation here: http://www.yiiframework.com/doc-2.0/guide-rest-versioning.html
In ZF3 I want to get default parameter from route. I'm getting parameters in this way in controller:
$params = $this->params()->fromRoute('crud');
My urls looks like this:
1: somedomain/admin/color/add
2: somedomain/admin/color
In 1) I'm getting add in my $params variable.
In 2) I'm getting null but I'm expecting default (in this case view)
I think this is problem with bad router configuration.
'admin' => [
'type' => Segment::class,
'options' => [
'route' => '/admin/:action',
'defaults' => [
'controller' => Controller\AdminController::class,
'action' => 'index',
],
],
'may_terminate' => true,
'child_routes' => [
'color' => [
'type' => Segment::class,
'options' => [
'route' => '/:crud',
'constraints' => [
'crud' => 'add|edit|delete|view',
],
'defaults' => [
'controller' => Controller\AdminController::class,
'crud' => 'view',
],
],
],
],
],
In your route definition, you didn't says the router that your crud parameter is optionnal. So when you call somedomain/admin/color, it is the route /admin/:action which is selected.
To specify a optional parameter, use the bracket notation (assuming you use the same action):
'admin' => [
'type' => Segment::class,
'options' => [
'route' => '/admin/:action[/:crud]',
'defaults' => [
'controller' => Controller\AdminController::class,
'action' => 'index',
'crud' => 'view',
],
'constraints' => [
'crud' => 'add|edit|delete|view',
],
],
],