to identify if there is a route zend framework 2 - zend-framework-routing

I have a url that redraw $ this->view->url($item['action']) this way but this variable can contain the route in the system or not, how can I do this check, check if this route exists in ZF2 ?

One option in my mind is to pass the navigation object to the view
In controller:
return [
'navigation' => $this->navigation,
];
In view:
if($this->navigation->findOneBy('route', $item['action'])) {
$url = $this->view->url($item['action']);
}
Another option would be to enclose the call in a try/catch. If the function throws an exception, the route does not exist
try {
$url = $this->view->url($item['action']);
} catch(Zend\Router\Exception\RuntimeException $e) {
$url = '';
}

Related

Slim 4 get all routes into a controller without $app

I need to get all registed routes to work with into a controller.
In slim 3 it was possible to get the router with
$router = $container->get('router');
$routes = $router->getRoutes();
With $app it is easy $routes = $app->getRouteCollector()->getRoutes();
Any ideas?
If you use PHP-DI you could add a container definition and inject the object via constructor injection.
Example:
<?php
// config/container.php
use Slim\App;
use Slim\Factory\AppFactory;
use Slim\Interfaces\RouteCollectorInterface;
// ...
return [
App::class => function (ContainerInterface $container) {
AppFactory::setContainer($container);
return AppFactory::create();
},
RouteCollectorInterface::class => function (ContainerInterface $container) {
return $container->get(App::class)->getRouteCollector();
},
// ...
];
The action class:
<?php
namespace App\Action\Home;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Response;
use Slim\Http\ServerRequest;
use Slim\Interfaces\RouteCollectorInterface;
final class HomeAction
{
/**
* #var RouteCollectorInterface
*/
private $routeCollector;
public function __construct(RouteCollectorInterface $routeCollector)
{
$this->routeCollector = $routeCollector;
}
public function __invoke(ServerRequest $request, Response $response): ResponseInterface
{
$routes = $this->routeCollector->getRoutes();
// ...
}
}
This will display basic information about all routes in your app in SlimPHP 4:
$app->get('/tests/get-routes/', function ($request, $response, $args) use ($app) {
$routes = $app->getRouteCollector()->getRoutes();
foreach ($routes as $route) {
echo $route->getIdentifier() . " → ";
echo ($route->getName() ?? "(unnamed)") . " → ";
echo $route->getPattern();
echo "<br><br>";
}
return $response;
});
From there, one can use something like this to get the URL for a given route:
$routeParser = \Slim\Routing\RouteContext::fromRequest($request)->getRouteParser();
$path = $routeParser->urlFor($nameofroute, $data, $queryParams);
With the following caveats:
this will only work for named routes;
this will only work if the required route parameters are provided -- and there's no method to check whether a route takes mandatory or optional route parameters.
there's no method to get the URL for an unnamed route.

How to access to Slim container from other classess?

Suppose that in my dependencies.php file I setup this container:
<?php
$container = $app->getContainer();
$container['db'] = function($config)
{
$db = $config['settings']['db'];
$pdo = new PDO("mysql:host=" . $db['host'] . ";port=" . $db['port'] .
";dbname=" . $db['dbname'] . ";charset=" . $db['charset'], $db['user'], $db['pass']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
};
I can use this container inside my route, called for example table.php:
<?php
use Slim\Http\Request;
use Slim\Http\Response;
$app->get('/table/get_table', function (Request $request, Response $response, array $args)
{
$sql = $this->db->prepare("SELECT * FROM some_table");
$sql->execute();
$result = $sql->fetchAll();
return $response->withJson($result);
});
this is basically the default usage, right? Said that, how can I instead use the db container from other classes? Supposes I have created a class called TableUtility and imported inside the table.php:
class TableUtility
{
function GetTableFromDb()
{
$sql = $this->db->prepare("SELECT * FROM some_table");
$sql->execute();
$result = $sql->fetchAll();
return $response->withJson($result);
}
}
as you can see I moved the logic of PDO inside GetTableFromDb of TableUtility, how can I access to db container from this class?
The usage in table.php will be:
<?php
use Slim\Http\Request;
use Slim\Http\Response;
$app->get('/table/get_table', function (Request $request, Response $response, array $args)
{
$tableUtility = new TableUtility();
return $response->withJson($tableUtility->GetTableFromDb());
});
actually I get in TableUtility:
Call to a member function prepare() on null
The full name for what you refer to as container is Dependency Injection Container. It is supposed to contain dependencies for objects. Passing this container to objects is considered bad practice. Instead you should pass only required dependencies for that object, which in your case is to pass db to $tableUtility. This is usually used by passing dependencies when constructing the object, or using setter methods. In your case you can refactor your code like this:
class TableUtility
{
function __construct($db) {
$this->db = $db;
}
}
Now in any method of TableUtility class, you have access to db object using $this->db but you'll need to pass db to class constructor whenever you create a new object. So you also need to do this:
$app->get('/table/get_table', function (Request $request, Response $response, array $args)
{
$tableUtility = new TableUtility($this->db);
// rest of the code
});

Mojolicious: determine controller based on placeholder parameters

I know that it's possible to write code like this.
$r->post('/v1/:controller/:action')
And mojo will call appropriate controller class.
Is it possible to do something like this in Mojo (maybe with stash):
$r->post('/v1/:model/:method')->to(
action => ':method',
controller => sub {
my ($captures) = #_;
my $controller = $captures->{'model'};
...
return $controller;
}
)

How is defined current url in zend (inside job of a framework)

Tell please what script uses zend framework for definition current URL? More exactly I interest what use ZEND for definition domain name: this $_SERVER['HTTP_HOST'] or this
$_SERVER['SERVER_NAME'] ? (or may be something other)?
P.S. ( I search in documentation but not found, (I do not know this framework), also I search in google, but also not found answer on my question? )
Try use: $this->getRequest()->getRequestUri() to get current of requested URI.
In the view script use: $this->url() to get current URL.
Or using via static integrated Zend Controller front via instance:
$uri = Zend_Controller_Front::getInstance()->getRequest()->getRequestUri();
You can get a value of URI implementation via singleton to get a value of request() data:
$request = Zend_Controller_Front::getInstance()->getRequest();
$url = $request->getScheme() . '://' . $request->getHttpHost();
On the View use it as:
echo $this->serverUrl(true); # return with controller, action,...
You should avoid hardcode such as example (NOT TO USE!):
echo 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
instead of this example use as on a view:
$uri = $this->getRequest()->getHttpHost() . $this->view->url();
If you want using getRequest in ZEND more explore The Request Object.
SKIP IT BELOW (AUTOPSY EXAMPLE HOW WORKS IT).
Full of example code how getRequestUri() how it works and why is isRequest instead using $_SERVER is because on a platform specific is randomly get a data:
first if uri null, thand if requested from IIS set is as HTTP_X_REWRITE_URL. If not, check on IIS7 rewritten uri (include encoded uri). If not on IIS than REQUEST_URI will check scheme of HTTP_HOSTNAME, or if failed use as ORIG_PATH_INFO and grab a QUERY_STRING.
If is setted, grab a data automatically via string of returned object $this in a class.
If failed, than will be set a parsed string than set it.
if ($requestUri === null) {
if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch
$requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
} elseif (
// IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem)
isset($_SERVER['IIS_WasUrlRewritten'])
&& $_SERVER['IIS_WasUrlRewritten'] == '1'
&& isset($_SERVER['UNENCODED_URL'])
&& $_SERVER['UNENCODED_URL'] != ''
) {
$requestUri = $_SERVER['UNENCODED_URL'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$requestUri = $_SERVER['REQUEST_URI'];
// Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path
$schemeAndHttpHost = $this->getScheme() . '://' . $this->getHttpHost();
if (strpos($requestUri, $schemeAndHttpHost) === 0) {
$requestUri = substr($requestUri, strlen($schemeAndHttpHost));
}
} elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
$requestUri = $_SERVER['ORIG_PATH_INFO'];
if (!empty($_SERVER['QUERY_STRING'])) {
$requestUri .= '?' . $_SERVER['QUERY_STRING'];
}
} else {
return $this;
}
} elseif (!is_string($requestUri)) {
return $this;
} else {
// Set GET items, if available
if (false !== ($pos = strpos($requestUri, '?'))) {
// Get key => value pairs and set $_GET
$query = substr($requestUri, $pos + 1);
parse_str($query, $vars);
$this->setQuery($vars);
}
}
$this->_requestUri = $requestUri;
return $this;

Set Zend response into a variable

I have an action that returns a JSON. I need to call it from another controller and I need to get this response into a variable to parse the JSON.
I've tried:
private function makeListFromUrl($menu)
{
$req = new Zend_Controller_Request_Http();
$req->setRequestUri('/module/controller/get.json/');
$res = new Zend_Controller_Response_Http();
$dis = $this->getFrontController()->dispatch($req, $res);
$dis->dispatch($req, $res);
$json = $res->getBody();
return Zend_Json::decode($json);
}
But this code causes the front controller to render the action, overriding the actual action. I just want to make a request, get the response into a variable, while leaving the actual request untouched.
Thanks.
i have a simple solution to this, not sure if it's the best, but worked very well.
$actionHelper = new Zend_View_Helper_Action();
$var = $actionHelper->action('action', 'controller', 'module', $params);
same way you'd do inside the view, but in the controller.
i hope this can help somebody.
You have to set returnResponse(true) for the FrontController to send the response back.
private function makeListFromUrl($menu)
{
$req = new Zend_Controller_Request_Http();
$req->setRequestUri('/module/controller/get.json/');
$front = Zend_Controller_Front::getInstance();
$front->returnResponse(true);
$response = $front->dispatch($requestObj);
$json = $res->getBody();
return Zend_Json::decode($json);
}