Pass two parameters as one to TWIG url - php

I'm using a framework (specifically EC-Cube3, if interested) that uses a Silex application with TWIG templates.
It has a navigation sidebar that is configured with PHP object arrays. I can inject an item array that looks something like this:
$item = array(
"id" => "item_id"
"url" => "named_url"
);
The url is created in typical Silex fashion:
$app->match('/item', 'Controller::method')->bind('named_url');
The framework eventually uses the url field and evaluates it in TWIG like so:
{{ url(item.url) }}
And this is usually fine! But the problem comes when I have a URL that includes a parameter, like this:
$app->match('/item/{id}', 'Controller::method')->bind('named_url'); // Needs 'id' to be evaluated.
In this scenario, setting the URL by the same array won't work because TWIG's url function needs the id for the second argument.
Since I can't change the application's TWIG files (because then I can't safely update the application), I need to be able to set the item's url to include the id as well.
After investigating, I don't think this is possible. Is it true that this is impossible? Or is there some method that I'm unaware of?

You can use mutiple vars like this
{{ path('path_in_route', {'id': article.id,'slug': article.slug}) }}
And
path_in_route
must be in your router file.
Hope that helps you.

Can you try the following in your Twig file:
{{ url(item.url,{'id': id}) }}
I believe that should work, but not certain.
EDIT #2
What if you use something like this:
$app->match('/item', 'Controller::method($id)')->bind('named_url');
Where $id is the id you need to pass in. I'm not really familiar with Silex, but maybe it's something like that?

Related

PHP How to create urls properly?

I have never understood how to create proper URLs. Every time I end up with trying to figure out if I should do ?var=value or &var=value and then if ?var=value already exists then I end up with ?var=value&var=value.
P.S. I am working with Laravel. (So maybe there is a built-in function?)
For example:
I have pagination and my URL could look like this
www.example.com OR
www.example.com?name=John
Then my pagination link is href="?page=2" and I end up with
www.example.com?name=John?page=2
Then I want to navigate to the next page with href="?page=3" and I end up with this. Because it keeps on adding.
www.example.com?name=John?page=2?page=3
What a mess.... is there a function for PHP or Laravel that would create proper URLS? (knowing when to use ? or & and not add existing values all the time but replace them if they exist already.
If you're using Laravel I think you should use some helper functions:
route('user.profile', ['id' => 1]);
It will create url by route name and parameters, It will look like:
http://sitename/user/profile?id=1
And you can find some useful helper functions here
There should be one and only ? in URL's which separates URI and parameters, rest of the key-value pairs are separated by &, and if you need to pass & or ? as a parameter, then you need to encode them.
you could pass an array to http_build_query and it will build the url for you
and in laravel there are url helper functions you can use them with ease.
Laravel come with a route helper which allow you to generage url quickly by passing the name with which you register your route.
Route::get('/', 'HomeController#index')->name('home.route')
Here you can see I pass home.route to the name method which is the name which I use for this route. And when I want to generate the URL for that route in my view I will juste do
{{ route('home.route') }}
If ny route take some parameters like this
Route::get('/person/{id}', 'HomeController#index')->name('home.route')
In view I will generate the url like this
{{ route('home.route', ['id' =>$id]) }}
Because you want juste to make pagination, Laravel comme with a buil in pagination. When you want to paginate something in your views, you must just call the paginate function on your model and laravel will handle all the route for that. For example I you have a Person Model you can do that like this in your controller
$persons = Person::paginate(25)
And in your views to generate pagination for that you will have to do
{{ $persons->links() }}
And that's all

symfony 3 url issue

Hi I'm coming for a very simple question (I think) but i didn't found the answer or a similar case.
I'm using symfony 3 and trying to build a second menu for my administration pannel.
However, I have a problem about how I have to declare the relative url in my "href", For my main menu i used to do like this
{{ url ( 'admin' ) }}
and it worked. The fact is that now I have subfolders and many levels in my url.
The url i try to reach is myapp/admin/gameadmin, this url work when I'm going on it but when i try to put it in 'href' I have an error message which says that the route is not working.
i declared it like that ->
{{ url(admin/gameadmin) }}
I tried with different character -> admin:gameadmin, admin\gameadmin ... etc and with path instead of url i don't know if it's not the good way to declare it or if I have a problem with my controllers.
In my bundle it's organised like that :
->Controllers(folder)
->admin(folder) (You can also find my main controllers on this level)
->admingamecontroller (Where the page I try to reach is routed)
I hope i gave you all the informations, thank you for your help and sorry for my english !
The url parameter is not the the url per se (ie: admin/gameadmin), this is the route name, defined in your routing.yaml file, or in your controller annotation.
If your action is something like this:
/**
* #Route("/admin/gameadmin", name="gameadmin")
*/
public function gameAdminAction()
{
...
}
Then, to generate the route, you have to do this:
{{ url('gameadmin') }}
By doing this, all the links on your website will be up to date if you change the gameadmin url, as long as you don't change the route name.
I suggest you to read this documentation on the Symfony website: https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/routing.html
Edit: As pointed by user254319, if you're not using annotations, you'll have to edit your routing.yaml config file.
gameadmin:
path: /admin/gameadmin
controller: App\Controller\Admin\AdminGameController::gameadminAction
The route name is the yaml key: gameadmin.
Related Symfony documentation: https://symfony.com/doc/current/routing.html

Why is passing of second variable on href much flexible in Laravel?

I am using Laravel Framework 4.1.30.
My Original Problem was...
I got a working route that when I type "localhost/user/alvin" it works but when I click a drop-down bar, it does not work.
drop-down bar from template was: (li tag removed)
{{ Auth::user()->username }}
route is:
Route::get('/user/{username}', array(
'as' => 'profile-user',
'uses' => 'ProfileController#user'));
View of URL when I click the dropdown bar is:
"localhost/user/%7Busername%7D"
I got 3 working answers for this from other communities.
First was a simple:
{{ Auth::user()->username }}
Second was:
{{ Auth::user()->username }}
Last was:
<a href="{{ URL::route('profile-user',['username'=>Auth::user()->username]) }}">
{{ Auth::user()->username}}</a>
Originally I thought the simplest (First Solution) form would be the wisest choice but as per most developer they choose the Third answer because it allows some flexibility to some extent.
I want to implement a good Quality Assured code as much as possible.
My question... Why would the 3rd solution be much more flexible compared to a much simpler code?
You can even use a more flexible, shorter modification of the third one:
<a href="{{ route('profile-user', Auth::user()->username) }}">
When you are using named routes, you do not put actual URLs, nor controller method names into your Views. You only provide a route name to your Views, and all other things are defined in your routes, and can be changed, if needed, without making breaking anything else. It would be a waste not to use this feature.
It is also more flexible, by not specifying the parameter name, so it can be changed in the routes too, without breaking the Views. This way they will be just taken in the order they were inputted. They are also read by a controller method in the order, i.e. public function index($parameter1, $parameter2) not by an associative array.
The route() is an alias to URL::route().

How to pass an array from Symfony 2 controller to a TWIG template ?

I can`t pass an array from a symfony 2 controller to a TWIG template. I use this code in the controller:
$searchTerms['color'] = "Red";
return $this->render('TestBundle::search.html.twig',
array(
"searchTerms" => $searchTerms));
In the twig template, I am trying to access the variable like this:
{{ searchTerms['color'] }}
{{ searchTerms.color }}
Both output nothing, empty string, so it seems like array comes to template but its elements are empty.
What`s wrong?
Yes, this code works. The first thing to check is that your twig code is in the correct page (TestBundle::search.html.twig). This might sound silly but that happens sometimes...
If this is all good, I suggest that you try to debug within your template. Debugging is the most important thing. You will always have this kind of problem while programming, especially when you try something new. The better you are at debugging your code, the better you are as a programmer because there is no way you can get everything right the first time.
So, how can you debug?
To debug within your twig template, you can use the debug extension of twig. To activate the debug option, you will have to do a quick change in your config file. You can also read this thread if your lost.
You can debug any variable within your template like this:
<pre>
{% debug searchTerms %}
</pre>
This way, you can easily debug your variable and test what your problem is:
{% debug searchTerms['color'] %}
If you want to debug things quickly, I highly recommend that you use the LadyBugBundle. It is an awesome tool that will allow you to do something like that:
In your controller:
ladybug_dump($searchTerms);
In your TWIG template:
{{ searchTerms|ladybug_dump }}
Not that different from a classic var_dump option, but if you have long arrays or objects, ladybug will impress you. More importantly, in a controller, you will often have the need to stop the code at a certain point to avoid the page to load after your debug statement, this is fairly easy with ladybug:
ladybug_dump_die($searchTerms);
You can even ask ladybug to load the "debugged" variable into Symfony profiler with this simple statement.
$this->get('ladybug')->log($searchTerms);
You have now direct access of the variable from a tab of the Symfony2 profiler.
Ladybug can do a lot more, but for this, the doc is really good.
I think you must change template like this:
{% for item in searchTerms %}
{{ item.color }}<br/>
{% endfor %}
See official documentation: Creating and using Templates->embedding-controllers

Generate URL to external route with UrlGenerator

With Silex (the PHP micro framework), it's possible to give names to existing controllers, so that we can easily generate urls to them later. Example:
$app->get('/gallery', function () {...})
->bind('gallery');
// Later on, in a template
{{ path('gallery') }}
I think this is really useful and I can't live without it.
But is it possible to register a route to an external website ? Say I'd like to generate urls to a google search, kind of
{{ path('google', {'search':'symfony'}) }}
// Would render to http://google.com/search?q=symfony
I take any idea :) Thx for your help !
path() is a Twig Extension for routing. Routing is to route an incoming URL to a controller action.
You can, however, create your own twig extension if you want a helper to easily create those standard outgoing URLs.
Take a look at: http://symfony.com/doc/current/cookbook/templating/twig_extension.html
You could then create an extension that turns {{ google('search string') }} into a URL. Only the imagination is your boundary.

Categories