{"id":5540,"date":"2014-09-12T16:15:35","date_gmt":"2014-09-12T20:15:35","guid":{"rendered":"https:\/\/www.caskeys.com\/dc\/?p=5540"},"modified":"2025-05-22T13:58:28","modified_gmt":"2025-05-22T17:58:28","slug":"quick-tip-php-object-oriented-_post-and-_get","status":"publish","type":"post","link":"https:\/\/www.caskeys.com\/dc\/quick-tip-php-object-oriented-_post-and-_get\/","title":{"rendered":"PHP Object Oriented Request Data"},"content":{"rendered":"<p>This article assumes LAMP or other PHP based web layout, and basic proficiency with Object Oriented PHP scripting.<\/p>\n<p>Have you ever found yourself wanting to use OOP methods in PHP but found it frustrating due to the rather bolted on nature of object support? In particular, dealing with outside data arrays like<em> $_POST<\/em> and <em>$_GET<\/em>?<\/p>\n<p>Since the advent of OOP support in PHP, it doesn&#8217;t take long to get spoiled by the type hinting and name space advantages OOP offers (I&#8217;ll leave the other benefits to be debated by the ever on going Procedural vs OOP soldiers still at war out there).<\/p>\n<p>The problems come when you have to start processing uncontrolled outside data, and as mentioned above, one of the biggest offenders is request data from the client. The moment this occurs &#8211; pretty much the moment you build any website, your nice clean OOP concept goes right out the window. Type hinting and automated error checking quickly follow suit. How do we fix this? Let&#8217;s start with our goals:<\/p>\n<ul>\n<li>Type hinting. Without type hinting, powerful IDEs like Dreamweaver are little more than very expensive text editors.<\/li>\n<li>Deal with missing variables. Even with validation, there are times, perhaps by design when some incoming variables might not have a value assigned.<\/li>\n<li>Avoiding repetition. Re typing array keys over and over isn&#8217;t just inconvenient. You&#8217;re practically begging to insert hard to locate typo bugs in the code.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Now with those objectives in mind, it&#8217;s easy to see the first two could be solved by grouping our variables into an object. The real question is how to get them there and avoid repetitious code.<\/p>\n<p>For a working example let&#8217;s assume we have an incoming form post with the following fields:<\/p>\n<ul>\n<li>First Name<\/li>\n<li>Last Name<\/li>\n<li>E-mail<\/li>\n<li>Phone<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>We&#8217;ll use the HTML5 <i>required<\/i> attribute and JavaScript validation to make sure most of the fields are filled out, but we want &#8220;Phone&#8221; to be optional. This is all well and good, but as any experienced developer is aware, you can never, EVER trust client side validation. So even without an optionally blank field, we&#8217;re going to have to ensure missing variables are initialized on post.<\/p>\n<p>Let&#8217;s try a couple of solutions and evaluate them vs. our criteria. For this article, we&#8217;re going to use <em>$_REQUEST<\/em>. If you aren&#8217;t familiar, <a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> is a handy single command that acquires all values you&#8217;d normally get from <em>$_GET<\/em>, <em>$_POST<\/em> and <em>$_COOKIE<\/em>.<\/p>\n<h2>\u00a0Standard Object<\/h2>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\n\/\/ Initialize standard object with request array.\r\n$request = object($_REQUEST);\r\n\r\n\/\/ Do stuff...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>On the surface this is a beautifully elegant solution. The PHP Standard Object initializes with\u00a0<em><a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\">$_REQUEST<\/a> <\/em>in a single line, and any\u00a0<a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> vars are now available as data members.<\/p>\n<p>Unfortunately, this method has two serious drawbacks.<\/p>\n<ol>\n<li>Firstly, Standard Object has no methods for our members. All we&#8217;ve really accomplished is shifting a bunch of data from one global space to another with no validation or protection. Might be quick and easy, but it&#8217;s nothing close to an object oriented solution and will inevitably bite us in the butt at some point.<\/li>\n<li>Any missing\u00a0<a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> vars stay missing. The Standard Object can&#8217;t include what isn&#8217;t there to begin with. To solve that issue you might try this:<\/li>\n<\/ol>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\n\/\/ If any post vars are missing, populate them with NULL.\r\nif(!isset($_REQUEST&#x5B;&#039;name_f&#039;])) \u00a0\u00a0 \u00a0$_REQUEST&#x5B;&#039;name_f&#039;] \u00a0\u00a0 \u00a0= NULL;\r\nif(!isset($_REQUEST&#x5B;&#039;name_l&#039;])) \u00a0\u00a0 \u00a0$_REQUEST&#x5B;&#039;name_l&#039;] \u00a0\u00a0 \u00a0= NULL;\r\nif(!isset($_REQUEST&#x5B;&#039;mail&#039;])) \u00a0\u00a0 \u00a0\u00a0 $_REQUEST&#x5B;&#039;mail&#039;] \u00a0\u00a0 \u00a0\u00a0 = NULL;\r\nif(!isset($_REQUEST&#x5B;&#039;phone&#039;])) \u00a0\u00a0 \u00a0 $_REQUEST&#x5B;&#039;phone&#039;]\u00a0\u00a0 \u00a0\u00a0 = NULL;\r\n\r\n\/\/ Initialize standard object with post array.\r\n$post = object(&amp;lt;a title=&amp;quot;$_REQUEST&amp;quot; href=&amp;quot;http:\/\/php.net\/manual\/en\/reserved.variables.request.php&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;&amp;lt;em&amp;gt;$_REQUEST&amp;lt;\/em&amp;gt;&amp;lt;\/a&amp;gt;);\r\n\r\n\/\/ Do stuff...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>With this technique we insert blank values into\u00a0<a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> before initializing Standard Object, and solve the missing variable issue. Unfortunately we&#8217;ve exchanged one problem for another: Now we have to repeat every key twice. Lastly, we&#8217;ve also done nothing about type hinting. Conclusion? Not with the hassle.<\/p>\n<h2>Custom Class, Populate Members Individually In Constructor<\/h2>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\nclass request\r\n{\r\n\u00a0\u00a0\u00a0 private\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$name_f\u00a0\u00a0 \u00a0= NULL, \/\/ First name.\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$name_l = NULL, \/\/ Last name.\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$mail\u00a0\u00a0 \u00a0= NULL, \/\/ Email.\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$phone\u00a0 = NULL; \/\/ Phone number.\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 \/\/ Class constructor\r\n\u00a0\u00a0\u00a0 public function __construct()\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&amp;gt;populate_members();\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0private function populate_members()\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if(isset($_REQUEST&#x5B;&#039;name_f&#039;]))\u00a0\u00a0\u00a0 $this-&amp;gt;name_f\u00a0\u00a0\u00a0 = $_REQUEST&#x5B;&#039;name_f&#039;];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(isset($_REQUEST&#x5B;&#039;name_l&#039;]))\u00a0\u00a0\u00a0 $this-&amp;gt;name_l\u00a0\u00a0\u00a0 = $_REQUEST&#x5B;&#039;name_l&#039;];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(isset($_REQUEST&#x5B;&#039;mail&#039;]))\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&amp;gt;mail\u00a0\u00a0\u00a0\u00a0\u00a0 = $_REQUEST&#x5B;&#039;mail&#039;];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(isset($_REQUEST&#x5B;&#039;phone&#039;]))\u00a0\u00a0\u00a0\u00a0 $this-&amp;gt;phone\u00a0\u00a0\u00a0\u00a0 = $_REQUEST&#x5B;&#039;phone&#039;];\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\/\/ Accessors\r\n\u00a0\u00a0 \u00a0public function get_name_f()\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$return $this-&amp;gt;name_f;\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0...\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\/\/ Mutators \r\n\u00a0\u00a0 \u00a0public function set_name_f($value)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$this-&amp;gt;name_f = $value;\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0...\r\n}\r\n\r\n\/\/ Initialize class object.\r\n$post = new post();\r\n\r\n\/\/ Do stuff...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>This is a little better. By writing our own class and running a function that populates piecemeal in the constructor, we get type hinting from our IDE and all of our variable instantiate work is packaged up. One problem remains &#8211; we still have to type every identifier three times at minimum. That&#8217;s a bug just waiting to happen. It&#8217;s a good start though, so let&#8217;s build on it a bit with the method below:<\/p>\n<h2>Custom Class, Dynamic Population<\/h2>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\nclass request\r\n{\r\n    private\r\n        $name_f    = NULL, \/\/ First name.\r\n        $name_l = NULL, \/\/ Last name.\r\n        $mail    = NULL, \/\/ Email.\r\n        $phone  = NULL; \/\/ Phone number.\r\n    \r\n    \/\/ Class constructor\r\n    public function __construct()\r\n    {\r\n        $this-&amp;gt;populate_members();\r\n    }\r\n    \r\n    private function populate_members()\r\n    {\r\n        \/\/ Iterate through each class variable.\r\n        foreach($this as $key =&amp;gt; $value)\r\n        {            \r\n            \/\/ If we can find a matching a post var with key matching\r\n            \/\/ key of current object var, set object var to the post value.\r\n            if(isset($_POST&#x5B;$key]))\r\n            {                    \r\n                $this-&amp;gt;$key = $_POST&#x5B;$key];                                   \r\n            }\r\n        } \r\n    }\r\n    \r\n    \/\/ Accessors\r\n    public function get_name_f()\r\n    {\r\n        $return $this-&amp;gt;name_f;\r\n    }\r\n    ...\r\n    \r\n    \/\/ Mutators \r\n    public function set_name_f($value)\r\n    {\r\n        $this-&amp;gt;name_f = $value;\r\n    }\r\n    ...\r\n}\r\n\r\n\/\/ Initialize object.\r\n$post = new post();\r\n\r\n\/\/ Do stuff...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Now we&#8217;re in business! This might look a bit complex at first glance, but it&#8217;s really the simplest of all attempts thus far. More importantly it provides everything we asked for and then some.<\/p>\n<p>Let&#8217;s look closer at the <em>populate_members()<\/em> method and see what&#8217;s going on:<\/p>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\nforeach($this as $key =&amp;gt; $value)\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>PHP allows us to loop through all the data members of an object just as if it were an array (this has other uses elsewhere, more on that in another article). We can even key the data member&#8217;s name as a string just as if it were an array key, and that&#8217;s what we&#8217;re leveraging for a dynamic data member population. FYI, we really don&#8217;t care about <em>$value<\/em> here, it&#8217;s just a necessary filler syntax.<\/p>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\nif(isset($_REQUEST&#x5B;$key]))\r\n{\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0$this-&amp;gt;$key = $_POST&#x5B;$key];\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Now in each loop we use the value of <em>$key<\/em> as an string array key for <em>$_POST <\/em>and evaluate it with <em>isset()<\/em>. If <em>isset()<\/em> returns TRUE, we know the value exists. All that&#8217;s needed is to populate the corresponding data member with that <em>$_POST<\/em> value. Again, PHP helps us out; it is perfectly legal to pass string variables as a data member id at run time.<\/p>\n<p>Once the loop is completed, all\u00a0<a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> keys that have a matching data member will have been located and the data members populated. Any missing\u00a0<a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> values are simply ignored; we already established a default value for their corresponding data members.<\/p>\n<p>At this point all conditions have been met. Your IDE will provide type hinting and error checking. Variables are only entered once as data member names. Missing\u00a0<a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> values are dealt with elegantly. No helper code outside of the class is needed. Best of all, this concept isn&#8217;t limited to\u00a0<a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> at all. Any array array is also fair game.<\/p>\n<p>We could stop right here, but unfortunately there&#8217;s just one little flaw remaining. Elegant as it is, this solution fully bypasses the object&#8217;s mutator methods, and in the process throws best practice data validation right out the window. There&#8217;s nothing stopping you from putting some data validation into the loop (or ignoring best practice), but with just a little more front end work, you can leverage your mutators and keep all of the data validation encapsulated.<\/p>\n<h2>Custom Class, Dynamic Mutation<\/h2>\n<p>&nbsp;<\/p>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\nclass request\r\n{\r\n    private\r\n        $name_f    = NULL, \/\/ First name.\r\n        $name_l = NULL, \/\/ Last name.\r\n        $mail    = NULL, \/\/ Email.\r\n        $phone  = NULL; \/\/ Phone number.\r\n    \r\n    \/\/ Class constructor\r\n    public function __construct()\r\n    {\r\n        $this-&amp;gt;populate_members();\r\n    }\r\n    \r\n    private function populate_members()\r\n    {\r\n        \/\/ Interate through each class variable.\r\n\tforeach($this as $key =&amp;gt; $value) \r\n\t{\t\t\t\r\n\t\t\/\/ If we can find a matching a post var with key matching\r\n\t\t\/\/ key of current object var, set object var to the post value. \r\n\t\tif(isset($_REQUEST&#x5B;$key]))\r\n\t\t{\r\n\t\t\t\/\/ Add &#039;set_&#039; prefix so member name is now a mutator method name.\r\n\t\t\t$method = &#039;set_&#039;.$key;\r\n\t\t\t\t\r\n\t\t\t\/\/ If a mutator method by the current name exists, run it and\r\n\t\t\t\/\/ pass current request value. \r\n\t\t\tif(method_exists($this, $method)=== TRUE)\r\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t$this-&amp;gt;$method($_REQUEST&#x5B;$key]);\r\n\t\t\t}\r\n\t\t}\r\n\t} \r\n    }\r\n    \r\n    \/\/ Accessors\r\n    public function get_name_f()\r\n    {\r\n        $return $this-&amp;gt;name_f;\r\n    }\r\n    ...\r\n    \r\n    \/\/ Mutators \r\n    public function set_name_f($value)\r\n    {\r\n        $this-&amp;gt;name_f = $value;\r\n    }\r\n    ...\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>This looks and works very similar to the above method, but instead of populating members directly, values are routed through the object&#8217;s mutator methods. This does double duty of encapsulating validation and providing a secondary gateway to control just which members you want populated at all.<\/p>\n<p>The secret is that PHP allows you to reference methods by string at run time just it it does members. First, we use a bit of string manipulation to get a member name from our <a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> name. I use a prefix of &#8220;set_&#8221; for my mutators, so it&#8217;s a simple matter of tacking that on to a placeholder variable.<\/p>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\n\/\/ Add &#039;set_&#039; prefix so member name is now a mutator method name.\r\n$method = &#039;set_&#039;.$key;\r\n<\/pre>\n<p>Next, we will need to make sure the method exists. PHP will immediately halt the script and throw a fatal error if an attempt is made to call non-existent methods, so this check is vital. If the check passes, we use the string to call out mutate method and pass it our <a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> value. Notice how the member&#8217;s signature is NOT part of the string &#8211; treat it exactly as you would any hard coded member&#8217;s signature.<\/p>\n<pre class=\"brush: php; title: Code:; notranslate\" title=\"Code:\">\r\n\/\/ If a mutator method by the current name exists, run it and\r\n\/\/ pass current request value. \r\nif(method_exists($this, $method)=== TRUE)\r\n{\t\t\t\t\t\t\t\t\t\t\r\n\t$this-&amp;gt;$method($_REQUEST&#x5B;$key]);\r\n}\r\n<\/pre>\n<p>Now we truly are ready. All of our <a title=\"$_REQUEST\" href=\"http:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\"><em>$_REQUEST<\/em><\/a> data is packaged into a fully encapsulated object with elegant evaluation and gateways. Our IDE will now provide us with type hinting and error checking, plus all of the code is reusable and double keying has been kept to the bare minimum. No more hidden typos, mystery variables, and annoying PHP notice errors!<\/p>\n<p>Give it a try, season to taste and enjoy.<\/p>\n<p>Until next time!<br \/>\nDC<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Easily and dynamically transfer $_POST, $_GET and other data into objects while retaining full IDE support.<\/p>\n","protected":false},"author":1,"featured_media":6216,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[71],"tags":[234],"class_list":["post-5540","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology-temerity","tag-coding-php"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.caskeys.com\/dc\/wp-content\/uploads\/2016\/06\/logo-php.png","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5lNM5-1rm","jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/5540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/comments?post=5540"}],"version-history":[{"count":37,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/5540\/revisions"}],"predecessor-version":[{"id":7401,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/posts\/5540\/revisions\/7401"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/media\/6216"}],"wp:attachment":[{"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/media?parent=5540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/categories?post=5540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.caskeys.com\/dc\/wp-json\/wp\/v2\/tags?post=5540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}