I am looking into building my own custom small framework and trying to make it as flexible as possible, I have now got to the input process of the design and I am wondering how I could implement the "request" class and how to return POST params from a POST request, etc.
I noticed that a lot of frameworks have a request class which hook directly into the "php://input" stream which I have tried to do and would like to utilize, however the only problem is this returns a string instead of an object or array of value=params.
What may be the best way for me to implement a method which would give me access to the param values of a POST request? I could probably explode the "php://input" string however this would be messy, I also tried the parse_str() on the stream which worked however sadly this also has issues if one of those values is something along the lines of foo">bar< as it seems to break out of the object and leave me with a partial incomplete value of foo.
My ultimate solution would be something along the lines of:
$_POST contains foo=bar;arg=value;
class request {
function get($arg=null)(){
if(!arg){/* return all, both foo and arg accessible*/}
else
/*return single value of the param with the $arg text*/
}
$foo = request->get('foo'); // "bar"
$all = request->get() // foo=bar;arg=value;
print $all->arg; // "value"
Related
So I have a doubt, and I'am not really sure how to solve it.
I'am trying to make a rest API with PHP, no framework, nothing, so first of all I thought of making
The functions: get, show,create, update, delete.
Like that I will be able to call the function
needed, the first parameter will be the url where is going to make the petition and the second one will be a function, like this, for example:
function get($url,$func){
}
I did my research and I know from where to start initially,
However, my problem starts when I want to get the parameter of the route,
Like for example if I use a framework, I will be like this:
SHOW
$app->post("/show/{id}","show_f");
in the above example the route will be "show" and the "id" will be the argument.
However, my problem is how can I get the argument (id) of the route
Do I need to convert to an array the $url value? (like this: explode('/', $url);),
so like that when I receive the initial value will be a string, however, when I split it, I will get an array of the route and the argument.
Does it sound reasonable, or do I complicate myself?
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
This isn't a real fluent interface. I have an object which builds up a method stack. Which gets executed by a single function call. But now I might add another virtual method, which "takes over" that method stack.
Use case: I'm wrapping my superglobals into objects. This allows me to "enforce" input filtering. $_GET and co provide simple sanitizing methods. And my new version now allows chaining of atomic filters. As example:
$_GET->ascii->nocontrol->text["field"]
This is a method call. It uses angle brackets. But that's just a nice trick which eases rewriting any occourence of $_GET["field"]. Anyway.
Now there are also occasionally forms with enumerated fields, as in field[0],field[1],field[2]. That's why I've added a virtual ->array filter method. It hijacks the collected method stack, and iterates the remaining filters on e.g. a $_POST array value. For example $_POST->array->int["list"].
Somewhat shortened implementation:
function exec_chain ($data) {
...
while ($filtername = array_pop($this->__filter)) {
...
$data = $this->{"_$filtername"} ($data);
...
}
function _array($data) {
list($multiplex, $this->__filter) = array($this->__filter, array());
$data = (array) $data;
foreach (array_keys($data) as $i) {
$this->__filter = $multiplex;
$data[$i] = $this->exec_chain($data[$i]);
}
return $data;
}
The method stack gets assembled in the $this->__filter list. Above exec_chain() just loops over it, each time removing the first method name. The virtual _array handler is usually the first method. And it simply steals that method stack, and reexecutes the remainder on each array element. Not exactly like in above example code, but it just repeatedly repopulates the original method stack.
It works. But it feels kind of unclean. And I'm thinking of adding another virtual method ->xor. (YAGNI?) Which would not just iterate over fields, but rather evaluate if alternate filters were successful. For example $_REQUEST->array->xor->email->url["fields"]. And I'm wondering if there is a better pattern for hijacking a function list. My current hook list ($this->__filter) swapping doesn't lend itself to chaining. Hmm well actually, the ->xor example wouldn't need to iterate / behave exactly like ->array.
So specifically, I'm interested in finding an alternative to my $this->__filter list usage with array_pop() and the sneaky swapping it out. This is bad. Is there a better implementation scheme to executing a method list half part me -> half part you?
I've made a similar chaining interface before, I like your idea of using it on GET/POST vars.
I think you will be better off doing something like $var->array->email_XOR_url; rather than $var->array->email->XOR->url;. That way you can catch the various combinations with your __get/__call magic.
A submitted form on my site returns an array of request data that is accessible with
$data = $this->getRequest();
This happens in the controller which gathers the data and then passes this array to my model for placing/updating into the database.
Here is the problem. What if I want to manipulate one of the values in that array? Previously I would extract each value, assigning them to a new array, so I could work on the one I needed. Like so:
$data = $this->getRequest();
$foo['site_id'] = $data->getParam('site_id');
$foo['story'] = htmlentities($data->getParam('story'));
and then I would pass the $foo array to the model for placing/updating into the database.
All I am doing is manipulating that one value (the 'story' param) so it seems like a waste to extract each one and reassign it just so I can do this. Additionally it is less flexible as I have to explicitly access each value by name. It's nicer to just pass the whole request to the model and then go through getting rid of anything not needed for the database.
How would you do this?
Edit again: Looking some more at your question what I am talking about here all goes on in the controller. Where your form`s action will land.
Well you have a couple of options.
First of all $_GET is still there in ZF so you could just access it.
Second there is:
$myArray = $this->_request->getParams();
or
$myArray = $this->getRequest()->getParams();
Wich would return all the params in an array instead of one by one.
Thirdly if the form is posted you have:
$myArray = $this->_request()->getPost();
Wich works with $this->_request->isPost() wich returns true if some form was posted.
About accessing all that in your view you could always just in controller:
$this->view->myArray = $this->_request->getParams();
edit: right I taught you meant the view not the model. I guess I do not understand that part of the question.
If you want to deal with the post data inside your model just:
$MyModel = new Model_Mymodels();
$data = $this->_request->getParams();
$data['story'] = htmlentities($data['story']);
$myModels->SetItAll($data);
And then inside your model you create the SetItAll() function (with a better name) and deal with it there.
Edit: oh wait! I get it. You hate sanytising your input one by one with your technique. Well then what I showed you about how to access that data should simplify your life a lot.
edit:
There is always the Zend_Form route if the parameters are really coming from a form. You could create code to interface it with your model and abstract all this from the controller. But at the end of the day if you need to do something special to one of your inputs then you have to code it somewhere.
im re-factoring php on zend code and all the code is full of $_GET["this"] and $_POST["that"]. I have always used the more phpish $this->_request->getPost('this') and $this->_request->getQuery('that') (this one being not so much logical with the getquery insteado of getGet).
So i was wondering if my method was safer/better/easier to mantain. I read in the Zend Framework documentation that you must validate your own input since the request object wont do it.
That leaves me with 2 questions:
What is best of this two? (or if theres another better way)
What is the best practice for validating php input with this methods?
Thanks!
I usually use $this->_request->getParams(); to retrieve either the post or the URL parameters. Then I use the Zend_Filter_Input to do validation and filtering. The getParams() does not do validation.
Using the Zend_Filter_Input you can do application level validation, using the Zend Validators (or you can write your own too). For example, you can make sure the 'months' field is a number:
$data = $this->_request->getParams();
$validators = array(
'month' => 'Digits',
);
$input = new Zend_Filter_Input($filters, $validators, $data);
Extending Brian's answer.
As you noted you can also check out $this->_request->getPost() and $this->_request->getQuery(). If you generalize on getParams(), it's sort of like using the $_REQUEST superglobal and I don't think that's acceptable in terms of security.
Additional to Zend_Filter, you may also use simple PHP to cast the required.
E.g.:
$id = (int) $this->_request->getQuery('id');
For other values, it gets more complicated, so make sure to e.g. quote in your DB queries (Zend_Db, see quoting identifiers, $db->quoteIdentifier()) and in views use $this->escape($var); to escape content.
You can't write a one-size-fits-all validation function for get/post data. As in some cases you require a field to be a integer and in others a date for instance. That's why there is no input validation in the zend framework.
You will have to write the validation code at the place where you need it. You can of course write some helper methods, but you can't expect the getPost() to validate something for you all by itself...
And it isn't even getPost/getQuery's place to validate anything, it's job is to get you the data you wan't, what happens to it from there on should not be it's concern.
$dataGet = $this->getRequest()->getParam('id',null);
$valid = new Zend_Validate_Digits();
if( isset($dataGet) && $valid->isValid($dataGet) ){
// do some...
} else{
// not set
}
I have always used the more phpish $this->_request->getPost('this') and $this->_request->getQuery('that') (this one being not so much logical with the getquery insteado of getGet).
What is best of this two? (or if theres another better way)
Just a quick explanation on the choice of getQuery(). The wording choice comes from what kind of data it is, not how it got there. GET and POST are just request methods, carrying all sorts of information, including, in the case of a POST request, a section known as "post data". A GET request has no such block, any variable data it carries is part of the query string of the url (the part after the ?).
So, while getPost() gets the data from the post data section of a POST request, getQuery() retrieves data from the query string of either a GET or POST request (as well as other HTTP Request methods).
(Note that GET Requests should not be used for anything that might produce a side effect, like altering a DB row)
So, in answer to your first question, use the getPost() and getQuery() methods, this way, you can be sure of where the data source (if you don't care, getParams() also works, but may include additional data).
What is the best practice for validating php input with this methods?
The best place to validate input is where you first use it. That is to say, when you pull it from getParams(), getPost(), or getQuery(). This way, your data is always correct for where you need it, and if you pass it off, you know it is safe. Keep in mind, if you pass it to another Controller (or Controller Action), you should probably check it again there, just to be safe. How you do this depends on your application, but it still needs to be checked.
not directly related to the topic, but
to insure that you get an number in your input, one could also use $var+0
(however if $var is a float it stays a float)
you may use in most cases
$id = $this->_request->getQuery('id')+0;