I have been experimenting in CakePHP with links and noticed that sometimes you just pass parameters and sometimes pass them with names prefixed. What is the difference between the two links:
$this->Html->link('Edit', array('controller'=>'users','action'=>'edit', $user['User']['id']));
$this->Html->link('Edit', array('controller'=>'users','action'=>'edit', 'id'=> $user['User']['id']));
The URL they create is largely irrelevant due to the routing capabilities, but in the first example I access the id directly in the controller method like:
public function edit( $id )
but for the named parameter I would have to physically pass it using the router!
Can anyone shed some more light on this? What the difference is and when to use each...
Also worth noting is that in CakePHP 3.0, they have removed named parameters which seems odd because BOTH links would still work... Any thoughts on this?
you dont have to pass named paramteres through the router.
they simply end up in
$this->request->named[...] // or
$this->request['named'][...]; // or
$this->request->params['named'][...]
they will be removed in favor of query string parameters: "?foo=bar&..."
which then will be (as already!) available via
$this->request->query('foo'); // >= 2.3
$this->request->query['foo']; // <= 2.2
etc
passed will also always be available via
$this->request->pass[...]; // or
$this->request['pass'][...]; // or
$this->request->params['pass'][...];
but that you could have all found out reading http://book.cakephp.org/2.0/en/controllers/request-response.html
the main difference between passed onces and named/query is that the latter are more exchangable whereas the passed onces due to their direct access in
public function xyz($one, $two, $three)
are more deeply integrated then and should be used for distinctive information passed.
the named/query ones don't have a specific order and are more like pagination and other fluent information.
for me passed parameters actually change the site (own canonical link etc) whereas the others don't do that and "canonical-link" back to the site without any named/query parameters (to avoid duplicate content on pagination etc).
Related
I already have a GET route with an URI /projects/{id} which displays Infos of a project with a given id. I also have a GET index route (/projects), which shows all my projects.
My problem is that I currently try to create different indexes (for example one which only displays the projects where I am assigned [e.g. on /projects/mines], or the projects which are pending administrator approval [e.g. on /projects/proposals], and still others displays).
So I want to know if I can have two GET routes /projects/{id}and /projects/{display_mode} which will be calling two differents methods of my ProjectController (respectively show and index).
Thanks for your help! :)
You may have one route /projects which returns all projects as default.
If there is query parameter like
/projects?displayMode=proposals
then you can apply filters.
In your controller it would look something like this
$projects = Project::query();
if ($request->query('displayMode') == 'proposals')
$projects->where('pending', true)
return $projects->get();
You can add multiple filters too in the same way
I'm not sure about specific Laravel options for the route definitions (sorry!), but if the {id} will always be an integer and {display_mode} will always have non-digits in it, you could keep just one route, but do the conditional handling in your controller. Just have the mainAction do something likeā¦
return preg_match('/^\d+$/', $param) ? idHelperAction($param) : displayModeHelperAction($param);
Then create those two helper functions and have them return whatever you want.
$param is supposed to be whatever you get from that route parameter -- /projects/{param}.
That should call the idHelperAction for routes where $param is all digits and nothing else; otherwise, it should call the displayModeHelperAction. Either way, it sends the same $param to the helper function and returns whatever that helper function returns -- effectively splitting one route definition into two possible actions.
Of course, you might have to add some context in the code sample. If the functions are all defined in the same class, you might need to use $this->idHelperAction($param) or self::idHelperAction($param) (and the same with the other helper action), depending on whether it's static or not; or tell it where to find the functions if you put them in another class, etc., etc. -- all the normal contextual requirements.
I'm quite new to Joomla! (and PHP in general) and trying to learn by developing a website on my local Joomla!-Installation.
I'm using WAMP-Server with PHP 5.5.12, Apache 2.4.9 and Joomla! 3.6.4.
Now I like to retrieve data from both $_POST and $_GET. Both are equaly insecure so it is only logical to retrieve and treat them together.
According to this article https://docs.joomla.org/Secure_coding_guidelines#Secure_strings i should be able to do it like this:
$string = JFactory::getApplication()->input->method->getString( 'myText', '' );
It's not working, complaining that 'method' is a non-object. ('Fatal error: Call to a member function getString() on a non-object')
All other data-source's from that same list (e.g. 'get', 'post', 'cookie', 'request', etc.) do not produce any error and seem to work flawless.
Unfortunately I need to retrieve data from either $_POST or $_GET (or both, but without $_COOKIE) wich is exactly what data-source='method' is supposed to do.
Of course I can use 'post' and 'get' sequentially but that seems stupid to me if there is an option wich could do it directly (less overhead? and slimmer code).
Than I maybe have to address priority, but let's leave that aside for now.
At https://docs.joomla.org/Retrieving_request_data_using_JInput the only Super-Global-'s mentioned are 'get', 'post' and 'server'. Not a word about the other sources that obviously
exist (no error occurring) or wich of the named sources is used as default.
My search has gone in circles for a while now and i can't find more related informations (targeting Joomla! or JInput, not PHP).
If I'm missing something fundamental here, feel free to tell me.
With this said my questions are now:
Is there any setting (or update) i have to make to get the 'method'-data-source working?
Is there another value (!='method') for data-source in JInput that can be used to directly retrieve data from exactly either $_POST
or $_GET or do I need to sequentially call 'post' and 'get' to accomplish this (maybe 'method' was renamed due to a conflict in names)?
Thanks for your time reading (and maybe answering).
I finally figured it out, thx to #Xorifelse for a push in the right direction.
The answers to my questions would be:
1) Is there any setting (or update) i have to make to get the 'method'- working?
One would have to add an array called '_METHOD' to the $GLOBALS-array in a way like this:
$GLOBALS['_METHOD'] = array_merge($_GET,$_POST);
Calling the JInput with data-source='method' then would return the merged content of $_GET and $_POST, with $_POST overwriting
values in $_GET if they have the same key.
2) Is there another value (!='method') for data-source in JInput that can be used...?
Every existing array inside the $GLOBALS-array (who's name starts with an underscore ('_') character and consists of uppercase characters only) can be used by calling the JInput with data-source beeing the name of that array (without the leading underscore).
If one has newly created and/or filled that array prior to the call by JInput doesn't matter. So using a name like _GETANDPOST instead of
_METHOD in the first question would describe its purpose mutch better.
BUT....
messing around with $GLOBALS is commonly considered bad practice!!
For everyone wondering how these values for the data-source in JInput work and why they seemingly could be called like a method
even they aren't methods:
the answer is to be found in 'magic methods' and 'property overloading'.
https://secure.php.net/manual/en/language.oop5.magic.php
https://secure.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
Is it OK to use
$id = $request->get('some_id');
instead of setting some parameters in Routes AND Controller like:
Route::get('some_page/{parameters}', 'controllerName#functionName');
function functionName($parameters)
{
$id = $parameters;
}
Appreciation
Of course it's good. When you're using GET, both ways are similar and if you like to use $request->get() for some reason, it's totally ok.
If you're using Form, it's the only right way. Plus, you can create custom Request class to use it for validation and other operations:
https://laravel.com/docs/master/validation#form-request-validation
They have two fundamentally different goals.
Using $request->get() is a way to retrieve a value from inside the php's REQUEST object regardless of its association with routing pattern you use.
Following HTTP's standards, you probably use $_GET to read some value without it changing the database [significantly] and you use $_POST to write data to you server.
While {pattern} in routing ONLY and ONLY should be used as a way for your application to locate something, some resource(s); in other words, its only goal is to help you route something in your server.
Nevertheless, in certain cases, such as /user/{id} the value of {id} might encounter some overlapping as to whether be treated as a route parameter or as a key of $_REQUEST.
Things such as tokens, filters criteria, sorting rules, referrers (when not significantly) etc. can be read right from $_REQUEST without interfering them into routing pattern of you application.
In Fat Free Framework code and examples online I sometimes see URL parameters referenced like this:
route_func($f3, $args) {
echo $args['name']
}
i also see:
route_func($f3, $args) {
$param=$f3->get('PARAMS.name');
echo $param;
}
Which method is preferred? Are there any caveats to one or the other?
The PARAMS variable can be accessed from anywhere in the code, so $f3->get('PARAMS.name') works everywhere.
Anyway, for convenience purpose, at routing time the route parameters are passed to the route handler. So you can spare one line of code by using the 2nd argument passed to the route handler.
In other words, the 2 examples you provided are equivalent, so choose the one that you understand best.
See this answer for more details about arguments passed at routing time.
NOTE:
As #user3587554 suggested, the 2 syntaxes differ on the treatment of non-existing keys: $args['name'] throws an error while $f3->get('PARAMS.name') returns NULL. So to be perfectly identical, the first syntax should be #$args['name']. But most of the time, this precaution is useless since there's no doubt about the parameter name(s).
Rather than using controller/action/key1/value1/key2/value2 as my URL, I'd like to use controller/action/value1/value2. I think I could do this by defining a custom route in my Bootstrap class, but I want my entire application to behave this way, so adding a custom route for each action is out of the question.
Is this possible? If so, how would I then access valueN? I'd like to be able to define the parameters in my action method's signature. e.x.:
// PostsController.php
public function view($postID) {
echo 'post ID: ' . $postID;
}
I'm using Zend Framework 1.9.3
Thanks!
While I don't think it's possible with the current router to allow N values (a fixed number would work) you could write a custom router that would do it for you.
I would question this approach, however, and suggest that actually listing all of your routes won't take long and will be easier in the long run. A route designed as you've suggested would mean that either your named parameters are always in the same order, i.e.
/controller/action/id/title/colour
or that they are almost anonymous
/controller/action/value1/value2/value3
With code like
$this->getRequest()->getParam('value2'); //fairly meaningless
Does it have to be N or can you say some finite value? For instance can you imagine that you'll never need more than say 5 params? If so you can set up a route:
/:controller/:action/:param0/:param1/:param2/:param3/:param4
Which will work even if you don't specify all 5 params for every action. If you ever need 6 somewhere else you can just add another /:paramN onto the route.
Another solution I've worked with before is to write a plugin which parses the REQUEST_URI and puts all the extra params in the request object in the dispatchLoopStartup() method. I like the first method better as it makes it more obvious where the params are coming from.