Say if I defined a route GET /user/{user_id}/post/{post_id}. How do I get the un-substitute route in middleware? i.e. if the request is GET /usr/123/post/456, is there a pre-defined function that can get me /user/{user_id}/post/{post_id}?
I am currently using following snippet
$urlParam = $request->route()[2];
if (isset($urlParam) && count($urlParam)) {
$urlPath = substr(str_replace(
array_map(function($item) { return "/" . $item . "/"; }, array_values($urlParam)),
array_map(function($item) { return "/{" . $item . "}/"; }, array_keys($urlParam)),
"/" . $request->path() . "/"), 1, -1);
}
return $urlPath;
but as you can see this is not bug-free, if both user_id & post_id are the same, above snippet will not generate right result.
In Laravel
If you wan to get the same route URI you can use
$request->route()->uri();
This will return user/{user_id}/post/{post_id}
In Lumen
$segments = $request->segments();
foreach ($request->route()[2] as $parameter => $value) {
$segment_index = array_search($value, $request->segments());
$segments[$segment_index] = "{{$parameter}}";
}
$segments = implode('/', $segments);
dd($segments);
And the result will be user/{user_id}/post/{post_id}
Related
How can I get about a Laravel route if the request is a get or post?
I try to test my laravel routes with the following
public function testRoutes()
{
$app = app();
$routes = $app->routes->getRoutes();
/**
* Test if mynamespace routes are redirected to login page if is not the login page
*/
echo PHP_EOL;
foreach ($routes as $route) {
if(strpos($route->getName(),'mynamespace::' ) !== false ) {
$url = $route->uri;
//$appURL = env('APP_URL') .'/';
$response = $this->get($url);
if((int)$response->status() !== 200 ){
echo $url . ' (FAILED) did not return 200. The response is ' . $response->status();
$this->assertTrue(false);
} else {
echo $url . ' (success ?)';
$this->assertTrue(true);
}
echo PHP_EOL;
}
}
}
but I would like exclude post requests for the moment
As we can see the Route class has a property $methods.
Your solution would look something like:
if (in_array('POST', $route->methods)) continue;
It may be interesting for you to look into the testing provided by Laravel itself. A simple way of testing response testing and much more!
Laravel testing.
I'm making an API that store a new version of an application. Here is my code:
public function saveNewVersion() {
$artifact_url = Input::get('url');
$artifact_id = Input::get('id');
$artifact_name = Input::get('name');
$artifact_version = Input::get('version');
$urls = explode('/', $artifact_url);
//Exploding URL to dir
$app_dir = "";
for($i=5; $i<sizeof($urls); $i++)
$app_dir .= $urls[$i] . '/';
$app_dir .= $artifact_id;
//Checking if the artifact_id exists in the database
$app = Applications::where('app_dir', '=', $app_dir);
if (!$app->count()) {
//Save it as new application
$new_app = new Applications();
$new_app->application->name = $artifact_name;
$new_app->app_dir = $app_dir;
$new_app->save();
$app_id = Applications::where('app_dir', '=', $app_dir)->first()->id;
} else {
$app_id = $app->first()->id;
//Checking if the application name is not same as newrelic (Optional)
if ($app->first()->application_name != $artifact_name) {
$app = $app->first();
$app->application_name = $artifact_name;
$app->save();
}
}
//check if the last version exists in the database
$version = Versions::where('application_id', '=', $app_id)->orderBy('id', 'desc');
$lastVersion = $version->first()->version_number;
if ($lastVersion != $artifact_version) {
//check if the new version is exists before
$flag = 0;
$versions = Versions::where('application_id', '=', $app_id)->orderBy('id', 'desc')->get();
foreach ($versions as $item) {
if ($item->version_number == $artifact_version) {
$flag = 1;
break;
}
}
if (!$flag) {
$version = new Versions();
$version->application_id = $app_id;
$version->version_number = $artifact_version;
$version->save();
echo 'Application' . $app_id . 'has been updated to version ' . $artifact_version;
}
}
}
When I call the API using postman, the API runs successfully and stores the new version of the application. But when I'm using CURL. I got ErrorException: Indirect modification of overloaded property App\Applications::$application and it points to my $new_app->save() code.
Is there any problem with my code ? Or are there some parameters used in postman that make this error invisible ?
I may be wrong here but it looks like the issue is the issue is here:
$new_app->application->name = $artifact_name;
I think it should be:
$new_app->application_name = $artifact_name;
based on the other code.
Basically, I have an admin (CMS) for my app. I have included menu and submenu setup, which are eventually populated on my nav section.
Name: User
URL: setup/user
Icon: fa fa-user
The problem is, if I add new menu (like above), I have to setup another route on web.php, like:
Route::resource('setup/user','UserController');
Well, there will be lots of menu to be created and my web.php is somehow messed up with lots of routes.
I followed this article and it gave me an idea, I tweaked it and created my own.
https://laracasts.com/discuss/channels/laravel/dynamically-calling-a-controller-method-in-laravel-5
Here's what I've done:
function wildcard($route, $controller, $verbs = ['get', 'post']) {
$stack = Route::getGroupStack();
$namespace = end($stack)['namespace'];
$controller = ucfirst(strtolower($route)).'Controller';
Route::match($verbs, rtrim($route, '/') . '/{method}', function($method, $params = null) use ($route, $namespace, $controller)
{
$controller = $namespace . '\\' . $controller;
$method = $controller . '#' . $method;
$params
? App::call($method, explode('/', $params))
: App::call($method);
});
}
wildcard('home',null);
My HomeController:
public function index()
{
return view('pages.common.dashboard');
}
But it doesn't display the view on my index method, just blank page. But it did get the method because I can dump from the method.
Maybe there's a better way on dynamic routing. Thanks.
Solution: You must return your App::call()
Route::match($verbs, rtrim($route, '/') . '/{method}', function($method, $params = null) use ($route, $namespace, $controller)
{
$controller = $namespace . '\\' . $controller;
$method = $controller . '#' . $method;
if($params){
// return the App::call
return App::call($method, explode('/', $params));
} else {
// return the App::call
return App::call($method);
}
});
I want to use ajax_pager in my block.
I've installed Libraries API and Ajax Pager API (as it described on the AP API page). But it's still not working.
When I use 'pager' instead of 'ajax_pager' it works.
What I'm doing wrong?
<?php
function latest_news_block_info() {
$blocks['latest_news_block'] = array(
// info: The name of the block.
'info' => t('Latest News'),
);
return $blocks;
}
function latest_news_block_view($delta = '') {
// The $delta parameter tells us which block is being requested.
switch ($delta) {
case 'latest_news_block':
// Create your block content here
$block['subject'] = t('Last news');
$query = new EntityFieldQuery();
//change news by the name of your content type
$entities = $query->entityCondition('entity_type', 'node')
->pager(5, 0)
->entityCondition('bundle', 'news')
->propertyOrderBy("created", "DESC")
->execute();
$content = "";
foreach($entities['node'] as $obj) {
$node = node_load($obj->nid);
$content .= "<img src='" .file_create_url($node->field_image['und'][0]['uri']) . "' width='200px' height='200px'>" . l($node->title, "node/" . $node->nid) . truncate_utf8($node->body['und'][0]['value'], 200, true, true) . '<br><hr>';
$block['content'] = $content;
}
break;
}
$pager = theme('ajax_pager', array('parameters' => array('selector' => 'block-system-main')));
$block['content'] .= $pager;
return $block;
}
I have build my own component in joomla and client wants now a friendly urls f.e
website.com/someplace/{product-id}-{product-name}. So i Build my own router like this.
function componentBuildRoute(&$query)
{
$segments = [];
if (isset($query['view'])) {
$segments[] = "szkolenie";
unset($query['view']);
}
if (isset($query['product_id'])) {
$productName = JFilterOutput::stringURLSafe(strtolower(getProductName($query['product_id'])));
$newName = $query['product_id'] . '-' . $productName;
$segments[] = $newName;
unset($query['product_id']);
}
return $segments;
}
and parse route function
function componentParseRoute($segments)
{
$app = JFactory::getApplication();
$menu = $app->getMenu();
$item =& $menu->getActive();
$count = count($segments);
switch ($item->query['view']) {
case 'catalogue' : {
$view = 'training';
$id = $segments[1];
}
break;
}
$data = [
'view' => $view,
'product_id' => $id
];
return $data;
}
While on the end of buildroute function segments are ok I have exactly what I want that on the beginning of parse route I have something like
website.com/szkolenie/1-krakow <-- I dont know wtf is this krakow( I know it is city i Poland) but still where is it get from ? The getProductName function implementation is
function getProductName($productId)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('#__component_training.id as id, #__component_product' . name)
->from($db->quoteName('#__component_training'))
->where('#__s4edu_product.product_id = ' . $productId)
->leftJoin('#__component_product ON
#__component_training.product_id=#__component_product.product_id');
$training = $db->loadObject();
return trim($training->name);
}
So taking all this into consideration I think that something is happening between the buildRoute and parseRoute, something what filters the $segment[1] variable, but how to disable that and why is it happening ?
P.S
Please do not send me to https://docs.joomla.org/Joomla_Routes_%26_SEF
I already know all the tutorials on joomla website which contains anything with sef.
P.S.S
It is built on joomla 3.7.0
You do not have a product named "krakow" ?
If not you can try to remove the $productName from the build function, just to check if this "krakow" is added automaticaly or it's from the getProductName() function.
Also i noticed that you have an error i guess in the function getProductName()
->where('#__s4edu_product.product_id = ' . $productId)
It's should be
->where('#__component_product.product_id = ' . $productId)