I am writting an application with zf2 and I came to this issue which I don't know how to implement.
At the moment I have a router like this :
'routes' => [
'stock' => [
'type' => 'regex',
'options' => [
'regex' => '/stock(?<sku>\/.*)',
'defaults' => [
'controller' => MyController::class,
'action' => 'check',
],
'spec' => '/path%path%'
],
So when my url contains ../stock/13567/2312 the parameter gets passed into the checkAction function.
However, I would like to show a different content when the url is just ../stock/ or ../stock without any parameter sent. How can I achieve this ?
Thanks.
If you want to show different content depending if sku parameter is passed you can do following thing in your controller:
public function indexAction()
{
// Return sku parameter if exists, false otherwise
$sku = $this->params('sku', false);
if ($sku) {
// For example get single item
...
$view->setTemplate('template-a');
} else {
// Get all items
...
$view->setTemplate('template-b');
}
return $view;
}
Just augment the regex to mark the param as optional, as in the docs:
'regex' => '/stock(?<sku>\/.*)?'
... and don't forget to provide the explicit default value:
'defaults' => [
'controller' => MyController::class,
'action' => 'check',
'sku' => '' // or else
],
Related
Help with routing settings, there is the following request template with frontend: /books/([0-9]+)/book-authors/([0-9]+)/images
There is a controller located in namespace: Shop\Controllers\Books\BookAuthors\ImagesController
The controller has an indexAction method.
In routing.php I specify the following:
$router = new Router(false);
$router->removeExtraSlashes(true);
$router->setDefaultNamespace('Shop\Controllers');
$router->setDefaultController('index');
$router->setDefaultAction('index');
$router->addGet('/books/([0-9]+)/book-authors/([0-9]+)/images', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'bookId' => 1,
'authorId' => 2,
'controller' => 'images',
'action' => 'index',
]);
return $router;
As a result, we get that the redirect always goes to the default controller. Please tell me how to fix...
I tried to debug and check why the template does not fit, but when I checked regex101 on the site, everything matches there and should work, but for some reason it does not work in phalcon.
Application return every time "not found"
The route works fine, although you can try this for simplicity and clarity:
$router->addGet('/books/{bookId:[0-9]+}/book-authors/{authorId:[0-9]+}/images',
[
'controller' => 'images',
'action' => 'index'
]
);
And in your ImagesController define indexAction as:
public function indexAction(int $bookId, int $authorId)
{
echo "BookId: $bookId and AuthorId: $authorId";
}
For /books/10/book-authors/22/images the result should be:
BookId: 10 and AuthorId: 22
Try this:
$router->addGet('/books/:int/book-authors/:int/images', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'controller' => 'images',
'action' => 'index',
'bookId' => 1,
'authorId' => 2,
]);
Note that I don't know if you can have multiple ":int" in the router definition and I have not tried this code.
If you can't have multiple ":int" in the line, you may need to restructure and move the bookId and authorId to the end and use :params. Note that I also dropped the "images" controller name since you don't need that in the line.
$router->addGet('/books/book-authors/:params', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'controller' => 'images',
'action' => 'index',
'params' => 1,
]);
Your URL would be something along the lines of "/books/book-authors/98/212" for bookID 98 and authorId 212.
My main router goes like this (simplified):
'router' => [
'routes' => [
'blog' => [
'type' => 'regex',
'options' => [
'regex' => "/(?<language>[a-z]{2})?",
'spec' => "/%language%",
'defaults' => [
'controller' => 'Blog\Controller\Posts',
'action' => 'index'
],
],
'may_terminate' => true,
'child_routes' => [
// [...]
'add_post' => [
'type' => 'literal',
'options' => [
'route' => '/admin/post/add',
'defaults' => [
'controller' => 'Blog\Controller\Posts',
'action' => 'add'
]
]
], // end add post
] // end child routes
] // end blog route (main route)
] // end routes
] // end Router
And in the template displayed on "/en/admin/post/add" I have a call to $this->url(), that ends up printing /%language%/admin/post/add.
I have the language code available on $language on my template, and
I'd like to pass it on to url() so it properly constructs the the url using the spec.
Also, I'd like, if possible, not to specify the name of the route on my call to url(), so it uses the default one for $this.
How would I go around to accomplish this?
Thanks and regards
You could use a segment route instead of a regex one and then use
$this->getHelperPluginManager()->getServiceLocator()->get('request')->getUri()->getPath();
in your view to print the actual route it's been used
While #marcosh answer works, since then I've found a simpler solution:
$this->url($this->route, ['language' => $language]);
Will output what I want. Seems clearer to me.
I'm using the FriendsOfCake CakePDF Plugin with wkhtmltopdf to render my views as PDF.
I also use their Search plugin to filter view data with a form.
For now, when I print the data in the view it always renders all view data into the PDF and not only the filtered data that is displayed on screen.
Is there any way to do this? I can't find anything that mentions such a case in the Plugin Docs. It seems like the PDF plugin always reloads the page in its default state or rather loads the default query from the index function instead of the filtered data. Since this is my first CakePDF project I don't really get what I have to do to make it render the filtered data instead. Can anybody help with that?
Here is what my main files look like so far:
class PaintingsController extends AppController
{
public function index()
{
$query = $this->Paintings
->find('search',
$this->Paintings->filterParams($this->request->query))
->contain(['Artists',
'Tickets' => function ($q) {
return $q->where(['Tickets.active' => false]);
}
]);
$this->viewBuilder()->options([
'pdfConfig' => [
'orientation' => 'portrait',
'filename' => 'paintings.pdf'
]
]);
$this->set('paintings', $this->paginate($query));
$this->set('_serialize', ['paintings']);
}
}
class PaintingsTable extends Table
{
public function searchConfiguration()
{
$search = new Manager($this);
$search->like('title', [
'before' => true,
'after' => true,
'field' => $this->aliasField('title'),
'filterEmpty' => true
])->value('property', [
'field' => $this->aliasField('property'),
'filterEmpty' => true
])->like('artist_name', [
'before' => false,
'after' => true,
'field' => $this->Artists->target()->aliasField('surname'),
'filterEmpty' => true
])->value('technique', [
'field' => $this->aliasField('technique'),
'filterEmpty' => true
]);
return $search;
}
}
In Template\Paintings\index.ctp
... data in tables ...
<?= $this->Html->link('Save as PDF',[
'action' => 'index',
'_ext' => 'pdf'],[
'class' => 'create-pdf-link',
'target' => 'blank'
]) ?>
Then everything gets rendered in Templates\Paintings\pdf\index.ctp without the applied filtering.
Your PDF link won't contain any filter paramters, so there is no reload or anything, it just won't do any filtering.
The current query is not being incorportated automatically when generating links/URLs, you have to explicitly pass it to the URL array on your own, like
$this->Html->link(
'Save as PDF',
[
'action' => 'index',
'_ext' => 'pdf'
] + $this->request->query, // there it goes
[
'class' => 'create-pdf-link',
'target' => 'blank'
]
);
See also Cookbook > Routing > Generating URLs
FIY, in CakePHP 2, things are a bit different, you would use
$this->request->params['named']
instead of
$this->request->query
like
$this->Html->link(
'Save as PDF',
[
'action' => 'index',
'_ext' => 'pdf'
] + $this->request->params['named'],
[
'class' => 'create-pdf-link',
'target' => 'blank'
]
);
Following up on my previous question
Why are my params not showing up in the url?
What is the best way to deal with blank parameters? Do I need to write an if statement for each field and assign a value if null? Currently I have 2 parameters and if the first one is blank it is setting the value of the second parameter as the first
Below is an example. If Zip is the first parameter and bar is the second...
www.foo.com/results/12345/bar
zip = 12345
bar = bar
if the first param is empty...
www.foo.com/results/bar/
zip = bar
I would like to do this in the url so the below won't work.
$search_zip = $this->params()->fromRoute('zip','default');
Below is where I post the params.
return $this->redirect()->toRoute('home/results',array(
'zip'=>$homeSearch->search_zip ,
You need create a route
'results' => [
'type' => 'Segment',
'options' => [
'route' => 'results[/:zip][/:bar][/]',
'defaults' => [
'__NAMESPACE__' => '...',
'controller' => '...',
'action' => '...',
'zip' => 'default',
'bar' => 'default'
],
'constraints' => [
'zip' => '[0-9]+',
'bar' => '[a-z]+'
]
]
]
]
in controller
$this->params('zip');
$this->params('bar');
$this->redirect()->toRoute('results', ['zip' => 123, 'bar' => 'bar']);
I currently have a Segment route looking like this: /shop/:shopId/ where shopId has no default value.
Whenever the route is matched a code in Module.php is triggered, that would do some preparation according to the shopId and save it in the session for example.
My question is, if it is possible, at that point, to set the default value for the route to that shopId? The final goal is to be able to assemble URLs without specifying the shopId each time from this moment on.
I remember in ZF1 this behavior was by default, where matched params from the Request were reused when assembling the URL and you had to explicitly specify you wanted them removed. Now I need the same functionality, but configured on a Module.php level, rather than having to rewrite every single assemble() call.
Option one: from your indexAction
$id = $routeMatch->getParam('id', false);
if (!$id)
$id = 1; // id was not supplied set default one note this can be added as constant or from db ....
Option two: set route in module.config.php
'product-view' => array(
'type' => 'Literal',
'options' => array(
'route' => '/product/view',
'defaults' => array(
'controller' => 'product-view-controller',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '[/:cat][/]',
'constraints' => array(
'cat' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
in you controller:
public function indexAction()
{
// get category param
$categoryParam = $this->params()->fromRoute('cat');
// if !cat then get random category
$categoryParam = ($categoryParam) ? $categoryParam : $this->categories[array_rand($this->categories)];
$shortList = $this->listingsTable->getListingsByCategory($categoryParam);
return new ViewModel(array(
'shortList' => $shortList,
'categoryParam' => $categoryParam
));
}