<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>HirdWeb &#187; PHP</title>
	<atom:link href="http://www.hirdweb.com/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hirdweb.com</link>
	<description>Another Blog clogging up the already crowded internet</description>
	<lastBuildDate>Wed, 28 Jul 2010 16:05:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Code Standards</title>
		<link>http://www.hirdweb.com/2010/07/28/code-standards/</link>
		<comments>http://www.hirdweb.com/2010/07/28/code-standards/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 16:05:05 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Ideas and Sorts]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=290</guid>
		<description><![CDATA[As I have been going through different code bases, I keep seeing things that just really amaze me. It all surrounds coding standards, or the lack thereof. Different places have different ideas of what is best, and I can only offer mine to the fray. However, once a standard is in place, no matter how [...]]]></description>
			<content:encoded><![CDATA[<p>As I have been going through different code bases, I keep seeing things that just really amaze me. It all surrounds coding standards, or the lack thereof. Different places have different ideas of what is best, and I can only offer mine to the fray. However, once a standard is in place, no matter how odd it may be, it is important to keep to those standards. This is for a few reasons. </p>
<p>First, it is important for readability. By seeing the code in the same format and structure it helps to get through lines of code quickly. It helps because all of the code is in the same format throughout the code. The person looking at the code can quickly understand without having to go back and figure out what is happening because the code is all of a sudden out of whack and what you may think is happening may not be happening. Especially when indentation may also be out of line and brackets are not used. Take for example the two examples below</p>
<pre>$fin=0;
foreach($var as $v){
if($v==3){$fin=$v+3}
unset($fin);echo $v;
}</pre>
<p>As a stand alone example it may be easy to decipher what is happening. In a file that has over 3000 lines of code, it may be overlooked and even cause issues if changes are made that affect that block. By breaking from the set coding standards and doing it &#8220;your own way&#8221;, sure it may be quicker for you, but it creates havoc, even for you later on.<br />
<span id="more-290"></span><br />
Second, it is about cleanliness. Using the same block of code above, that looks absolutely horrid to me. I know some people code this way because &#8220;it takes up less space&#8221;, some even make a claim that it makes the code process faster. To that point, if you need to cut down on whitespace in the code in order to get the application to go faster, then maybe you ought to look at the code again, because it is likely something else that is causing problems, not the whitespace. If that code block again had been done with a few standards in place, it could look like this instead:</p>
<pre>$fin = 0;
foreach ( $var as $v ) {
    if ( $v == 3 ) {
        $fin = $v + 3;
    }

    unset($fin);
    echo $v;
}</pre>
<p>By doing this, the code looks cleaner, which adds to its readability. Clean code not only looks good, but is very easy to do. It helps to maintain the flow of work, especially in larger projects. By sticking to a clean code standard, all developers can jump in at any time and pick up easily, as everything is nicely placed, and easy to understand. There will be times when you write some code, then do not touch it for months, maybe years, and have to go back to review something. You will be very glad if you kept to standards and kept your code clean. </p>
<p>Third, it is about working in the team. If you are alone in the project, then great. You get to choose how you want to work. Most times it is more than just you, so it is important that everyone works in the same standards. This can be up to the team to determine. This can include spacing, indentation, bracket use, variable naming conventions, ternary use, etc. But whatever the team decides, stick to it. Do not be a rogue and do it your own way just because you think it is better. Having the code in a standardized format really, really helps in the long run. Teams are able to debug code quicker because they do not have to decipher different standards. Coding can happen in a dynamic environment where you may be working on a data object one day, then have to switch to help with the controller layer the next. You will not have to go through the code and decipher the different styles. </p>
<p>With that being said, some of the standards that I use may not work for everyone. I am a little neurotic and OCD when it comes to code, so I like a specific style, but can adapt as needed. Here are some of the things I use:</p>
<ul>
<li />Variables names must be descriptive of what they represent, the only exception being is for counters/iterators<br />
for example, a variable for total amount would be $total, or the variable for tax would be $tax, or the variable for a unique identifier would be $uid.  </p>
<li />For loops, If and Switch statements must be bracketed, must have spaces between the parenthesis, and must be indented. The length of indentation I usually use 4 spaces (or set the tab stops to 4 spaces). Switch statements must have indentations for each case. Example:
<pre>if ( $var = 0 ) {
    // do something
}

for ( $c = 0; $c <=5; $c++ ) {
    // do something
}

switch ( $var ) {
    case 1:
        // do something
        break;
    case 2:
        // do something
        break;
    default:
        // do something
} </pre>
<p>There should never be any If statement or loop that is never bracketed, ever. I think that is lazy coding, I think it looks atrocious, and when more code is needing to be added to the struct, it causes more time wasted to ensure that the proper items are included. </p>
<li />Functions should be bracketed, and indented, even if it is only one line of code in the function. Comments should also be done on every function describing the purpose of the function.
<li />Comments describing functions/objects/classes should follow the same format. If PHPDoc is used, then use it throughout. Do not change the way you comment these. I have seen functions in a file commented using PHPDoc, using the "// ----- description", and then surrounded by "//" around the entire comments. I really do not care which one to use, but when one is decided to be used, use only that.
<li />Never, ever use short tags, or short echo tags. They are just bad form, another example of lazy coding, and will cause problems here soon. Even though PHP6 is all but dead, the "enhancement" to remove short tag/short echo tag will make it to a release here soon. I understand the old PHP4 was all over it, but should not have been. Use the full tag and do not use "&lt;?=" to echo something out.
<li />Do not just copy and paste code to other parts of the application. If you find that a code block can be re-used in other areas, then wrap it in a function, or an object/class, and keep the code centralized. When the code needs to be updated, you then only have to update one section, instead of multiple files.
</ul>
<p>OK, so my rant is over. The list above is my standards. This may not always work in every project. Some of the good areas to look at for ideas or practices for code standards are:<br />
<a href='http://pear.php.net/manual/en/standards.php' target='_blank'>http://pear.php.net/manual/en/standards.php</a><br />
<a href='http://framework.zend.com/manual/en/coding-standard.html' target='_blank'>http://framework.zend.com/manual/en/coding-standard.html</a><br />
<a href='https://trac.cakephp.org/wiki/Developement/CodingStandards' target='_blank'>https://trac.cakephp.org/wiki/Developement/CodingStandards</a></p>
<p>Most of the standards I use are located in these documents. </p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2010/07/28/code-standards/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP 5 News</title>
		<link>http://www.hirdweb.com/2010/07/26/php-5-news/</link>
		<comments>http://www.hirdweb.com/2010/07/26/php-5-news/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 01:42:58 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=286</guid>
		<description><![CDATA[I am going to take a break from the NuSOAP server finish up, and that will come soon. Instead, the update to PHP 5.2.14 has come out. What is really odd about this news, is that according to the release of the news, it also &#8220;marks the end of the active support for PHP 5.2. [...]]]></description>
			<content:encoded><![CDATA[<p>I am going to take a break from the NuSOAP server finish up, and that will come soon. Instead, the update to PHP 5.2.14 has come out. What is really odd about this news, is that according to the <a href='http://www.php.net/archive/2010.php#id2010-07-22-1'>release of the news</a>, it also<br />
<blockquote>&#8220;marks the end of the active support for PHP 5.2. Following this release the PHP 5.2 series will receive no further active bug maintenance. Security fixes for PHP 5.2 might be published on a case by cases basis. All users of PHP 5.2 are encouraged to upgrade to PHP 5.3.&#8221;</p></blockquote>
<p>There are a lot of different applications that are just now adopting 5.2, and it will not be actively supported.<br />
<span id="more-286"></span><br />
Marco Tabini posted a really great article on this, and I highly suggest to review this. It is located at <a href='http://blog.tabini.ca/2010/07/php-5-2-support-ends-just-as-its-adoption-begins/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=php-5-2-support-ends-just-as-its-adoption-begins'>his blog: blog.tabini.ca</a>. While Marco makes great points in his article, the comments on the article are also a good thing to read. </p>
<p>One idea that is important to remember, is that 5.3 will (in theory) work even if the code was made for 5.2. This is of course, the code is well written. But that is the case no matter what code or library, or base you may use. That is the most important aspect, write good code. However, by not providing support when a possible major group of users come on board, can be risky. However, this is where the whole argument of open source and paid services can come back to play in political office meeting rooms. </p>
<p>Paid services, like Microsoft&#8217;s .NET libraries for example, are expensive, but are still supported. Sure it is expensive. Think of this in an enterprise application environment. A company has invested a lot of man hours on a major project upgrade (from 4 to 5.2 for whatever reason they had to stay at 4 for the time), and then find out that the major project they undertook to move to 5.2 will now need further evaluation to determine if 5.3 is acceptable to the company. More cost of investing time, energy, resources, and money can be a huge thing when the &#8220;powers that be&#8221; decide if they want to continue to use open source for their applications. </p>
<p>I know this is a very simplistic example, and there are even more questions with this, like if it was an enterprise app why did it stay on php4 for so long. But since 5.3 has been out for a little over a year, it seems shocking that they would be so quickly retiring active support for this. </p>
<p>It may have more to do with other things, including shelving PHP6. I am not as worried about 5.2 retiring. But it is an interesting event. Some will say this is really nothing, and that there is really nothing to this. And they may be entirely correct. </p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2010/07/26/php-5-news/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finishing up the NuSOAP server</title>
		<link>http://www.hirdweb.com/2010/07/20/finishing-up-the-nusoap-server/</link>
		<comments>http://www.hirdweb.com/2010/07/20/finishing-up-the-nusoap-server/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 15:57:09 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[NuSOAP]]></category>
		<category><![CDATA[webservices]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=269</guid>
		<description><![CDATA[In the last post, the NuSOAP server introduced a new level of complexity, and had a multidimensional array, along with creating a more robust status message for the client to help determine the success or failure of the request. This post will examine the remaining functions in the NuSOAP server, and making the rest of [...]]]></description>
			<content:encoded><![CDATA[<p>In the last post, the NuSOAP server introduced a new level of complexity, and had a multidimensional array, along with creating a more robust status message for the client to help determine the success or failure of the request. This post will examine the remaining functions in the NuSOAP server, and making the rest of the functions work, and more complex types including third and fourth level complexities along with a non-named (integer) array for the result. </p>
<p>We will be building on the code we used last time, so as a refresher, the code from the last post can be located at:<br />
<a href="http://www.hirdweb.com/webservice/20100710_server.txt" target="_top">http://www.hirdweb.com/webservice/20100710_server.txt</a><br />
<a href="http://www.hirdweb.com/webservice/20100710.txt" target="_top">http://www.hirdweb.com/webservice/20100710.txt</a></p>
<p>First off, here are the remaining functions to be exposed in the service:
<ul>
<li><strong>showGroupItems</strong> – Shows what is needed based on a set event, all items are made up of course</li>
<li><strong>showMadLib</strong> – Returns a mad lib based on passing in a number of different items</li>
<li><strong>showNumbers</strong> – Returns a non associative array of numbers, requires an ID, and returns the numbers associated with that ID</li>
</ul>
<p>Each of these webservices will require a little different structure.<br />
showGroupItems will have a third level of complexity<br />
showMadLib will require a long list of strings as the input<br />
showNumbers will return an array of string elements, integer value for the element, instead of a named element<br />
<span id="more-269"></span><br />
Make sure to save the file with a different name. I named it &#8220;20100720_server.php&#8221;. You will need to also update the WSDL call, otherwise it will still reference an older file name. Here is what I updated my location with:
<pre>$wsdl_addr = 'http://www.hirdweb.com/webservice/20100720_server.php';</pre>
<p>Let&#8217;s first tackle the showGroupItems. The idea behind this is to show an example of a complex type for the returned result. We already have a complex type, but we need to make a returned result with a multidimensional array. The required input is:<br />
id = a specific event name, in this case, we limit it to: movie, picnic, drive, shopping</p>
<p>For each of these events, we have a set of items that will go with it:<br />
food &#8211; this is an array of items for food, drink and treat<br />
equip &#8211; string containing a comma separated list of equipment needed<br />
transport &#8211; string for the transport to/of the event<br />
people &#8211; string of a comma separated list (or a single item) of people involved in the activity</p>
<p>First we need the list, so add this to the file named <em>items.php</em> that contains all the data for the services. We created this file in a previous post. (<em>Just a note: in a &#8220;real world&#8221; application, these would likely be stored in a database and you would need to query the information you need in order to build the array</em>). </p>
<pre>$items = array(
	'movie' => array(
		'food'	=> array('food' => 'nachos with jalepenos and cheese', 'drink' => 'soda', 'treat' => 'candy'),
		'equip' => 'ticket, 3D glasses',
		'transport' => 'car',
		'people' => 'friend A, friend B, friend C',
	),
	'picnic' => array(
		'food'	=> array('food' => 'sandwiches', 'drink' => 'sports drinks', 'treat' => 'granola bars'),
		'equip' => 'basket, blanket',
		'transport' => 'van',
		'people' => 'Mom, Dad, brothers, sisters, cousins',
	),
	'drive' => array(
		'food'	=> array('food' => 'snacks', 'drink' => 'water', 'treat' => 'crackers'),
		'equip' => 'gloves, sunglasses',
		'transport' => 'sports car',
		'people' => 'myself, hot date',
	),
	'shopping' => array(
		'food'	=> array('food' => 'grapes', 'drink' => 'juice box', 'treat' => 'candybar'),
		'equip' => 'cart, list',
		'transport' => 'moving van',
	)
);</pre>
<p>We will create a function with some very basic error checking, and be able to use our error function if there are errors. </p>
<pre>function showGroupItems($id){
	require('items.php');
	// Make sure the id is lowercase
	$id = strtolower($id);
	if ( $id == '' ){
		return error('empty');
	}
	// make sure the item is in the array keys
	if ( !array_key_exists($id, $items) ){
		// return an error
		return error("not_found");
	}
	$final = $items[$id];

	$fin_data['status'] = array('status'=>'ok','message'=>'');
	$fin_data['group_items'] = $final;

	return $fin_data;
}</pre>
<p>Now we need to tackle the registration of this function to the webservice. This is where we really need to think about what we need to return. First, we need to set the registration and the base complex type:</p>
<pre>// ================================================
// === showGroupItems register
$in = array(
	'id' => 'xsd:string',
);
$out = array('return' => 'tns:showGroupItems');
$namespace = 'uri:hirdwebservice';
$soapaction = 'uri:hirdwebservice/showGroupItems';
$doc = 'Simplistic service to return an array of items for a specific event, the ones available are: movie, picnic, drive, shopping';
$server->register('showGroupItems', $in, $out, $namespace, $soapaction, 'rpc', 'encoded', $doc);
// ================================================</pre>
<p>In this registration, we defined a &#8220;showGroupItems&#8221; type. So we need to create that to pull in the status type, and start building the showGroupItems result</p>
<pre>// showGroupItems types ++++++++++++++++++++++++++++++++++++++++++
$server->wsdl->addComplexType('showGroupItems','complexType','struct','all','',
    array(
        'status' => array('name' => 'head', 'type' => 'tns:status_mssg'),
        'group_items' => array('name' => 'message', 'type' => 'tns:groupItems')
    )
);
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</pre>
<p>In this one, we set the next level complex type to &#8220;groupItems&#8221;. In this type, we will split it into two parts. One will be for the string portions of the result, the other into the next level complex type. Add the following to the showGroupItems types code block. </p>
<pre>$server->wsdl->addComplexType(
	'all_food','complexType','struct','all','',
	array(
		'food' => array('name' => 'food', 'type' => 'xsd:string', 'minOccurs' => "0"),
		'drink' => array('name' => 'drink', 'type' => 'xsd:string', 'minOccurs' => "0"),
		'treat' => array('name' => 'treat', 'type' => 'xsd:string', 'minOccurs' => "0"),
	)
);

$server->wsdl->addComplexType(
	'groupItems','complexType','struct','all','',
	array(
		'food' => array('name' => 'food', 'type' => 'tns:all_food'),
		'equip' => array('name' => 'equip', 'type' => 'xsd:string', 'minOccurs' => "0"),
		'transport' => array('name' => 'transport', 'type' => 'xsd:string', 'minOccurs' => "0"),
		'people' => array('name' => 'people', 'type' => 'xsd:string', 'minOccurs' => "0"),
	)
);</pre>
<p>This definition splits the returned result. The first element item in the array is defined by a separate complex type &#8220;all_food&#8221;. The rest are regular strings. We can update all of these to be arrays as well, and that is something to try on your own. The &#8220;minOccurs&#8221; definition tells the webservice that the item is optional and may not appear. Which is ok if it does not, then the service will ignore the empty space and go on. In our data list, the last item, &#8220;shopping&#8221; does not have a &#8216;people&#8217; element. So by defining the minOccurs as 0, it will not be required to print out. Now add the following to the client:</p>
<pre>$try4 = $proxy->showGroupItems('Picnic');
$try5 = $proxy->showGroupItems('Shopping');</pre>
<p>And print those out you should receive something similar to the following:</p>
<pre>showGroupItems
"Picnic"
Array
(
    [status] =>
    [group_items] => Array
        (
            [food] => Array
                (
                    [food] => sandwiches
                    [drink] => sports drinks
                    [treat] => granola bars
                )

            [equip] => basket, blanket
            [transport] => van
            [people] => Mom, Dad, brothers, sisters, cousins
        )
)
"Shopping"
Array
(
    [status] =>
    [group_items] => Array
        (
            [food] => Array
                (
                    [food] => grapes
                    [drink] => juice box
                    [treat] => candybar
                )

            [equip] => cart, list
            [transport] => moving van
        )
)</pre>
<p>Now we are completed with this function, now on to the last two. These are pretty simple. I will give you the functions, and the registration for this one, and the complexTypes definitions should be easy by now, so I will skip posting this one.  Since this one is a mad lib, there is nothing to add in, we can just insert the input elements into the string. </p>
<pre>function showMadLib($adj1, $adj2, $adj3, $adj4, $adverb1, $adverb2, $noun1, $noun2, $noun3, $verb1, $verb_past1, $verb_past2 ){
	// Put all validation code here
	if ( ($adj1 == '')||($noun1 == '')||($verb_past1 == '')||($adverb1 == '')||($adj2 == '')||($noun2 == '')||
			($noun3 == '')||($adj3 == '')||($verb1 == '')||($adverb2 == '')||($verb_past2 == '')||($adj4 == '') ){
		return error("partial");
	}

	// example submission:
	// "disagreeable","dilapidated","evanescent","ubiquitous","obediently","painfully","monkey","spaceship","boogey man","answer","photographed", "knitted"

	$mad_lib = "Today I went to the zoo. I saw a $adj1 $noun1 jumping up and down in its tree. He $verb_past1 $adverb1 through the " .
			"large tunnel that led to its $adj2 $noun2. I got some peanuts and passed them through the cage to a gigantic gray $noun3 " .
			"towering above my head. Feeding that animal made me hungry. I went to get a $adj3 scoop of ice cream. It filled my stomach." .
			"Afterwards I had to $verb1 $adverb2 to catch our bus. When I got home I $verb_past2 my mom for a $adj4 day at the zoo.";

	$fin_data['status'] = array('status'=>'ok','message'=>'');
	$fin_data['mad_lib'] = $mad_lib;

	return $fin_data;
}</pre>
<p>The function is in place, and as you can see, it takes a lot of different input. It returns only a string as the final message, so when you build the complexType, remember that. Here is the registration:</p>
<pre>// ================================================
// === showMadLib register
$in = array(
	'adj1' => 'xsd:string',
	'adj2' => 'xsd:string',
	'adj3' => 'xsd:string',
	'adj4' => 'xsd:string',
	'adverb1' => 'xsd:string',
	'adverb2' => 'xsd:string',
	'noun1' => 'xsd:string',
	'noun2' => 'xsd:string',
	'noun3' => 'xsd:string',
	'verb1' => 'xsd:string',
	'verb_past1' => 'xsd:string',
	'verb_past2' => 'xsd:string',
);
$out = array('return' => 'tns:showMadLib');
$namespace = 'uri:hirdwebservice';
$soapaction = 'uri:hirdwebservice/showMadLib';
$doc = 'Returns a mad lib based on the data it is sent. Need 4 Adjectives, 2 Adverbs, 3 Nouns, 1 Verb, and 2 Verb: Past Tense. It replies with a string that contains the madlib. ';
$server->register('showMadLib', $in, $out, $namespace, $soapaction, 'rpc', 'encoded', $doc);
// ================================================</pre>
<p>Now after you build the complexType add the following to the client:</p>
<pre>$try6 = $proxy->showMadLib("disagreeable","dilapidated","evanescent","ubiquitous","obediently","painfully","monkey","spaceship","boogey man","answer","photographed", "knitted");
$try7 = $proxy->showMadLib("hello","","","","","","",""," ","","", "");</pre>
<p>And now you can test the function. </p>
<p>Lastly, we need to do a service that returns an array of data (numbers for this example) that has no associative type array. Add this to the &#8220;items.php&#8221; file:</p>
<pre>$various = array (
	array(
		array('number' => "01"),
		array('number' => "02"),
		array('number' => "03"),
		array('number' => "04"),
		array('number' => "05"),
		array('number' => "06"),
		array('number' => "07"),
		array('number' => "08"),
		array('number' => "09"),
	),
	array(
		array('number' => "121654898"),
		array('number' => "11151"),
		array('number' => "18852"),
		array('number' => "1114885111111"),
		array('number' => "11111111111111111111"),
	),
	array(
		array('number' => "2654846354684654"),
	),
	array(
		array('number' => "303030303030303030"),
		array('number' => "32323232323232323232323232"),
	),
	array(
		array('number' => "44444444"),
		array('number' => "41414141"),
		array('number' => "42424242"),
		array('number' => "43434343"),
		array('number' => "40404040"),
	),
	array(
		array('number' => "5"),
		array('number' => "10"),
		array('number' => "15"),
		array('number' => "20"),
		array('number' => "25"),
	),
);</pre>
<p>As you can see, it is just a regular array with numbers and nothing else. Based on the number they send to the service, it will return the string of numbers. After planning, build out the function. </p>
<pre>function showNumbers($id){
	require("items.php");

	// place all validation code here
	if ( ($id < 0) || ($id > 5)  ){
		// return an error
		return error("custom", "numbers", "You need to enter an ID that is 0, 1, 2, 3, 4, or 5.");
	}

	$numbers = $various[$id];

	$fin_data['head'] = array('status'=>'ok','message'=>'');
	$fin_data['numbers'] = $numbers;

	return $fin_data;
}</pre>
<p>We only want numbers from 0 to 5, so if there is anything else, then return an error. Now we need to register the function. </p>
<pre>// ================================================
// === showNumbers register
$in = array(
	'id' => 'xsd:string',
);
$out = array('return' => 'tns:showNumbers');
$namespace = 'uri:hirdwebservice';
$soapaction = 'uri:hirdwebservice/showNumbers';
$doc = 'Returns an array of numbers in a non-assoc array key format';
$server->register('showNumbers', $in, $out, $namespace, $soapaction, 'rpc', 'encoded', $doc);
// ================================================</pre>
<p>This is basically the same, we need an ID, and we will return a formatted complexType named &#8220;showNumbers&#8221;. But now we need to actually format those. Since we are using a non associative array for the return, we need to format a new type. This is still a complexType, but it is not a struct, but an &#8220;array&#8221;. Start with the base complexType to build off of, then add the array type which references a regular struct complexType. This is done as follows:</p>
<pre>// showNumbers types ++++++++++++++++++++++++++++++++++++++++++
$server->wsdl->addComplexType(
	'number','complexType','struct','all','',
	array(
		'number' => array('name' => 'number', 'type' => 'xsd:string'),
	)
);

<strong>$server->wsdl->addComplexType(
	'numbers','complexType','array','',
	'SOAP-ENC:Array',
	array(),
	array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'tns:number[]')), 'tns:number'
);</strong>

$server->wsdl->addComplexType('showNumbers','complexType','struct','all','',
    array(
        'status' => array('name' => 'head', 'type' => 'tns:status_mssg'),
        'numbers' => array('name' => 'message', 'type' => 'tns:numbers')
    )
);
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</pre>
<p>The new array type will have different items we need to declare. The first being is that it is an array not a struct, we do not want all, so will do &#8220;&#8221; instead of passing &#8220;all&#8221;. Next, we need to tell the class that we want a SOAP-ENC:Array. Since we are not defining a struct, the normal position where we would put our return data is now a blank array. Finally we need to build the array type, reference in the SOAP-ENC:arrayType. Add the wsdl def to it, then make sure you add the square brackets to the named array. Now build the regular struct we already know. Add the following to the client to test the service:</p>
<pre>$try8 = $proxy->showNumbers(2);
$try9 = $proxy->showNumbers(5);</pre>
<p>And you should get something similar to:
<pre>showNumbers
"2"
Array
(
    [status] =>
    [numbers] => Array
        (
            [0] => Array
                (
                    [number] => 2654846354684654
                )
        )
)
"5"
Array
(
    [status] =>
    [numbers] => Array
        (
            [0] => Array
                (
                    [number] => 5
                )
            [1] => Array
                (
                    [number] => 10
                )
            [2] => Array
                (
                    [number] => 15
                )
            [3] => Array
                (
                    [number] => 20
                )
            [4] => Array
                (
                    [number] => 25
                )
        )
)</pre>
<p>and that will complete the server side of this. These are very simplistic examples, but can be used to build on for more applicable items. For example, You may have a database full of authors and the books they wrote, along with prices, ISBN numbers, publishers, and excerpts from the book. By using a combo of the previous examples, you can create a service that allows others to query the DB based on author, that will return each book, publisher, price with tax for the state they are requesting along with an excerpt of each book. </p>
<p>The server for this post is located at <a href='http://www.hirdweb.com/webservice/20100720_server.php' target="_top">http://www.hirdweb.com/webservice/20100720_server.php</a><br />
The client for this post is located at <a href='http://www.hirdweb.com/webservice/20100720.php' target='_top'>http://www.hirdweb.com/webservice/20100720.php</a></p>
<p>Code for this post is located at:<br />
server: <a href='http://www.hirdweb.com/webservice/20100720_server.txt' target='_top'>http://www.hirdweb.com/webservice/20100720_server.txt</a><br />
client: <a href='http://www.hirdweb.com/webservice/20100720.txt' target='_top'>http://www.hirdweb.com/webservice/20100720.txt</a><br />
items: <a href='http://www.hirdweb.com/webservice/items.txt' target='_top'>http://www.hirdweb.com/webservice/items.txt</a></p>
<p>Next we will test these in ASP.NET and figure out how to really use these. </p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2010/07/20/finishing-up-the-nusoap-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Services with NuSOAP</title>
		<link>http://www.hirdweb.com/2010/07/02/web-services-with-nusoap/</link>
		<comments>http://www.hirdweb.com/2010/07/02/web-services-with-nusoap/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 14:31:19 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[NuSOAP]]></category>
		<category><![CDATA[webservices]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=220</guid>
		<description><![CDATA[Doing a lot with webservices lately. Which is really a great thing if there is a central repository of information that needs to be disseminated between different external systems. I am doing a lot with NuSOAP and php SOAP. But this tutorial is going to be about the NuSOAP libraries. You can get these libraries [...]]]></description>
			<content:encoded><![CDATA[<p>Doing a lot with webservices lately. Which is really a great thing if there is a central repository of information that needs to be disseminated between different external systems. I am doing a lot with NuSOAP and php SOAP. But this tutorial is going to be about the NuSOAP libraries. You can get these libraries from:<br />
<a title="http://sourceforge.net/projects/nusoap/" href="http://sourceforge.net/projects/nusoap/" target="_blank">http://sourceforge.net/projects/nusoap/</a></p>
<p>First thing to do is to download this, and install into a directory that you can access. For different security reasons, it may be needed to keep these libraries outside of the accessible web directories.</p>
<p>The next step is to determine what needs to be required to get the data. This may include authentication and credentials, id&#8217;s, phrases, or anything else. It could be possible to not have anything required and just return all records. And that is the next step: determine what to expose. What type of information would you want to send back to the world? Hopefully it is not sensitive data, and only the data that needs to be exposed.</p>
<p>Now with that in mind, we are ready to go. I have set up a webservice server that has five different functions:</p>
<p><strong>showPhrases</strong> &#8211; Phrases from Shakespeare plays that replace the names in the phrase with the passed in name/string<br />
<strong>showTaxes</strong> &#8211; Calculates the tax based on the passed in price and state<br />
<strong>showGroupItems</strong> &#8211; Shows what is needed based on a set event, all items are made up of course<br />
<strong>showMadLib</strong> &#8211; Returns a mad lib based on passing in a number of different items<br />
<strong>showNumbers</strong> &#8211; Returns a non associative array of numbers, requires an ID, and returns the numbers associated with that ID</p>
<p>Each of these functions provides a little more to view based on the webservice. The first and fourth functions will return a string of data. The second function returns an array with different data types. The third returns a complex type of a multidimensional array. I did this because there are many different tutorials out there using NuSOAP, but only seem to return a basic type and has very little to help when setting up the WSDL when it needs to be more complex. The fifth function demonstrates how to return a non associative array with the webservice in a complex type.</p>
<p>I will break down each function per post. But now we need a way that we can test these functions when we get them going. So the first thing to do is create a NuSOAP client to grab the exposed data. For the client, we will use the showTaxes example that has been created.</p>
<p><span id="more-220"></span></p>
<p>Remember, the first thing we need to do, is determine what we are going to do with code. Never just start putting down code without a plan. Always have a plan, and include requirements for the code in the plan. Our plan for the client will be as follows:</p>
<ol>
<li>Require the NuSOAP libraries</li>
<li>Identify the WSDL we are to use</li>
<li>Create the client with UTF-8 enabled</li>
<li>Create a proxy</li>
<li>Call the webservice server</li>
<li>Grab the results</li>
<li>Print them to the screen</li>
</ol>
<p>This is a very basic and generic plan. When you use webservices, it is highly unlikely that you will ever just print/dump the returned data to the screen. Whatever is needed by the application for the returned data needs to be included in the plan.</p>
<p>So the first part, we need to create a client file wherever this will reside, so create a client.php or whatever you want to name the file. Then we need to include the NuSOAP libraries:</p>
<pre>
&lt;?php
ini_set('display_errors',1);

require_once('nusoap/nusoap.php');
</pre>
<p>In the snippet above, I have turned on errors right now so that I can see exactly what may be going wrong. In the real world, you really do not want to do this to expose the errors. They should always be handled gracefully. </p>
<p>We next want to define the WSDL. The WSDL for the examples I have created is located at: http://www.hirdweb.com/webservice/index.php?wsdl. </p>
<pre>
// Set the WSDL location
$wsdl='http://www.hirdweb.com/webservice/index.php?wsdl';
</pre>
<p>Next, we want to create the client, set the UTF-8 parameters, and do a little error trapping to make sure the client is good. </p>
<pre>
$client = new nusoap_client($wsdl, 'wsdl');
$client->decode_utf8 = false;
$client->xml_encoding = 'UTF-8';

$err = $client->getError();
if ($err) {
    echo '&lt;h2&gt;Error Found While Connecting&lt;/h2&gt;&lt;pre&gt;' . $err . '&lt;/pre&gt;\n';
}
</pre>
<p>This will create the client, using the WSDL (I put the WSDL in a variable for readability, but you can pass the WSDL right in the instantiation call). We are not going to decode UTF-8, but we are going to encode any XML in UTF-8. The error handler looks to see if there is an error in establishing the client. If there is one found, then it will dump that to the screen. Again, for the live world, a better error handler is needed. </p>
<p>Next, we set up a proxy to call the function we want, which is showTaxes. A little about this function, in case you want to explore more before the next post: This function calculates the taxes based on 9 different states in the US. They are: AZ, AL, AK, CA, OR, WA, UT, ID, WY. Any other state passed in will result in an error being spit back by the service. This webservice function needs two parameters passed to it: The price and the state. The price should be a float value, and we will get into the server more later to write in validation code to make sure it is a float. The following code would create the proxy and then make the call. (I put in a couple different examples so you can see the difference and the errors)</p>
<pre>
$proxy = $client->getProxy();

$returned_data_ca = $proxy->showTaxes("199.99", "CA");
$returned_data_or = $proxy->showTaxes("199.99", "OR");
// This will return an error
$returned_data_ny = $proxy->showTaxes("199.99", "NY");
</pre>
<p>This will make the call to the service three times for different states, and then store the returned data in the variables. Now to print them to the screen and close the file:</p>
<pre>
echo "&lt;br /&gt;&lt;hr /&gt;&lt;h1&gt;showTaxes CA Results&lt;/h1&gt;";
echo '&lt;pre&gt;';
print_r($returned_data_ca);
echo '&lt;/pre&gt;';

echo "&lt;br /&gt;&lt;hr /&gt;&lt;h1&gt;showTaxes OR Results&lt;/h1&gt;";
echo '&lt;pre&gt;';
print_r($returned_data_or);
echo '&lt;/pre&gt;';

echo "&lt;br /&gt;&lt;hr /&gt;&lt;h1&gt;showTaxes NY Results&lt;/h1&gt;";
echo '&lt;pre&gt;';
print_r($returned_data_ny);
echo '&lt;/pre&gt;';
?>
</pre>
<p>And just like that, you have a webservice client that you can now use as we get into the server. </p>
<p>The result has been put up at the following location:<a href='http://www.hirdweb.com/webservice/20100702.php' target='_blank'>http://www.hirdweb.com/webservice/20100702.php</a>.</p>
<p>Next, we will look at the creation of the NuSOAP server. </p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2010/07/02/web-services-with-nusoap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PEAR and CakePHP</title>
		<link>http://www.hirdweb.com/2009/05/04/pear-and-cakephp/</link>
		<comments>http://www.hirdweb.com/2009/05/04/pear-and-cakephp/#comments</comments>
		<pubDate>Tue, 05 May 2009 02:23:41 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[cakePHP]]></category>
		<category><![CDATA[PEAR]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=185</guid>
		<description><![CDATA[This post is about my experience with loading in PEAR to a CakePHP 1.2.x application. This may be the right way or the wrong way, but I got it to work throughout the application. I had to do some changes, and if there is a better way of doing this, please let me know. First [...]]]></description>
			<content:encoded><![CDATA[<p>This post is about my experience with loading in PEAR to a CakePHP 1.2.x application. This may be the right way or the wrong way, but I got it to work throughout the application. I had to do some changes, and if there is a better way of doing this, please let me know. </p>
<p>First off, here is the issue. I needed to be able to export a group of records from the database to an excel spreadsheet. I have tried to use the <a href="http://bakery.cakephp.org/articles/view/excel-xls-helper" target="_blank">Excel Spreadsheet add in that is listed on the Bakery</a>. It works nice, and I had to do some modification for 1.2, but it worked. But not the way I wanted it. I have used the PEAR library Spreadsheet_Excel_Writer before and I like the type of control that I wanted, over the cells, the formatting, the merging, etc etc etc. It provides the type of control that I wanted. So here is what I did to get this to work with the CakePHP framework. </p>
<p>First, I have to download the PEAR library and the Spreadsheet_Excel_Writer libraries to use. Since I use a local system to help develop, I could download these libraries to the local system and transport these over to the CakePHP application. So I went to PEAR site to get the libraries. To download these I ran the following commands:</p>
<pre>
pear install PEAR-1.8.1
pear install OLE-1.0.0RC1
pear install Spreadsheet_Excel_Writer-0.9.1
</pre>
<p>URL&#8217;s are listed below:</p>
<p>http://pear.php.net/package/PEAR/download</p>
<p>http://pear.php.net/package/Spreadsheet_Excel_Writer/download</p>
<p>http://pear.php.net/package/OLE/download</p>
<p><span id="more-185"></span><br />
These downloaded the to local drives and I copied them over to the CakePHP area. Here is where it gets a little tricky. And I thank &#8220;brian&#8221; who helped me on the <a href="http://groups.google.com/group/cake-php">Cake Google group</a> to get past this when I got into a problem. So here we go, diving in to this. </p>
<p>First off, the PEAR libraries need to be put in the vendors directory. If you look at the directory structure for Cake, it appears like this:<br />
/app<br />
/cake<br />
/vendors</p>
<p>Inside of the /app directory, there is another vendors directory. This is where I put the PEAR libraries. This causes problems, because in the /cake/config/paths.php file, there is a path defined for VENDORS, and for PEAR:</p>
<pre>
if (!defined('VENDORS')) {
	define('VENDORS', CAKE_CORE_INCLUDE_PATH.DS.'vendors'.DS);
}

define('PEAR', VENDORS.'Pear'.DS);
</pre>
<p>Now, I have put the PEAR libraries in the top level vendor directory. If you choose to put it in the app/vendors directory, then you may need to change a core file, which is not advisable, because you would need to change the path above to</p>
<pre>
if (!defined('VENDORS')) {
	define('VENDORS', CAKE_CORE_INCLUDE_PATH.DS.'app/vendors'.DS);
}
</pre>
<p>So back to the PEAR libraries. Here is what I needed to do. I moved the PEAR directories to the /vendors directory. So here is what that directory looks like:</p>
<pre>
/vendors
    /css
    /js
   /Pear   <--- Look at this, case sensitive based on those paths above
        /OLE
        /OS
        /PEAR
        /scripts
        /Spreadsheet
        INSTALL
        LICENSE
        OLE.php
        package.dtd
        PEAR.php
        PEAR5.php
        README
        System.php
        template.spec
    /shells
</pre>
<p>This is part of the PEAR install we need to do. Now we need to update the paths in some of these files so that CakePHP can find them and include them. </p>
<p>**** ORIGINAL ENTRY THAT HAS BEEN EDITED/DEPRECATED ********************<br />
**** EDIT: Based on the original post this is the method I originally used. This way works, but requires a<br />
**** little too much overhead and editing the files in the PEAR libraries which is never really a good idea<br />
**** and should only be used sparingly. To see the way that it should be done, please see below this<br />
**** section.<br />
****<br />
**** In the file /vendors/Pear/Spreadsheet/Excel/Writer.php there is 2 requires<br />
**** require_once 'PEAR.php';<br />
**** require_once 'Spreadsheet/Excel/Writer/Workbook.php';<br />
****<br />
**** In order for the Cake App to see these, at least in my set up, I needed to change these to the<br />
**** following:<br />
**** require_once 'PEAR.php';<br />
**** require_once PEAR . 'Spreadsheet/Excel/Writer/Workbook.php';<br />
****<br />
**** I needed to add "PEAR . " to the require_once call. Now I needed to add this to the following files:<br />
**** /vendors/Pear/Spreadsheet/Excel/Writer.php<br />
**** require_once 'PEAR.php';<br />
**** require_once PEAR . 'Spreadsheet/Excel/Writer/Workbook.php';<br />
****<br />
**** /vendors/Pear/Spreadsheet/Excel/Writer/Workbook.php<br />
**** require_once PEAR . 'Spreadsheet/Excel/Writer/Format.php';<br />
**** require_once PEAR . 'Spreadsheet/Excel/Writer/BIFFwriter.php';<br />
**** require_once PEAR . 'Spreadsheet/Excel/Writer/Worksheet.php';<br />
**** require_once PEAR . 'Spreadsheet/Excel/Writer/Parser.php';<br />
**** require_once PEAR . 'OLE/PPS/Root.php';<br />
**** require_once PEAR . 'OLE/PPS/File.php';<br />
****<br />
**** /vendors/Pear/OLE/PPS.php<br />
**** require_once 'PEAR.php';<br />
**** require_once PEAR . 'OLE.php';<br />
****<br />
**** This had helped the application find my PEAR libraries when trying to do this<br />
**** END ORIGINAL ENTRY ***********************************************</p>
<p><strong><em>Now, a word about the edit. The above method works, but is not a preferred method. The best method for this, so there is no need to edit PEAR library files is the following. And a big thanks to <a href="http://cakebaker.42dh.com/">Daniel Hofstetter</a> for pointing this out. </em></strong></p>
<p>I put this at the top of my controller file. I am sure there is better places for this, probably even the app_controller file so that all controllers get the needed include path set. Here is what I did. </p>
<p>I needed to append the include path so that the new PEAR path would be found. After the php opening, I added this line:</p>
<pre>
ini_set("include_path", PEAR . PATH_SEPARATOR . ini_get("include_path"));
</pre>
<p>I am going to go over this just a little. First off, the ini_set is called to set the include_path. But we do not want to destroy any other include paths that are set up as well. So when we add the PEAR path, we need to also include the other paths as well. So the initial include_path was as follows (given in example form only, where the directory "test" is where I have CakePHP installed)<br />
ini_get("include_path") = </p>
<pre>
/www/htdocs/html/test:/www/htdocs/html/test/app/:.:/usr/local/php5/lib/php
</pre>
<p>Since CakePHP already defines the variable for the PEAR path as "PEAR", we can use that to add to the include path, like shown above. After setting the path using ini_set(), we run ini_get("include_path") it would = </p>
<pre>
/www/htdocs/html/test/vendors/Pear/:/www/htdocs/html/test:/www/htdocs/html/test/app/:.:/usr/local/php5/lib/php
</pre>
<p>By doing it this way, there is no need to edit the PEAR library files, and we can add new PEAR libraries without having to worry about editing those files as well. </p>
<p>Now, I needed to make the controller aware of the vendor library. In my controller file I added this line before the class declaration:</p>
<pre>
App::import('vendor', 'Spreadsheet_Excel_Writer', array('file' => '../vendors/Pear/Spreadsheet/Excel/Writer.php'));
</pre>
<p>In Cake 1.2, this is how the vendor's are imported. The vendor() declaration has been deprecated. This imports a vendor, gives the class a name (I choose the base one that it is usually called), and the location of the of the file. In my set up, I needed to add the "../", you may not have to. </p>
<p>In the function, (I called "export"), I did not want to have a "view" page for it. The first thing I did was grab the information I needed. For this example, I needed all users that signed up for a conference. So I grabbed that information and put it in an array $registrations. </p>
<pre>
function export ($id = null){
       // I only want to get a specific conference, not all of them
	if ( $id == 'all' ){
		$this->Session->setFlash('Please select a specific conference to export the registrations.');
		$this->redirect(array('action' => 'index'));
	}

	// Now get the registrations for the conference
	$registrations = $this->Registration->find('all',
		array(
			'conditions' => array('conference_id' => $id),
			'fields' => array('*'),
			'recursive' => '-1',
			'order' => array('Registration.created'),
		)
	);
</pre>
<p>Now comes the fun part, building the column heading array, and then instantiating the writer</p>
<pre>
	// Set up the header array
	$titles = array(
		'Name' => 15,
		'Address' => 20,
		'City' => 20,
		'State' => 7,
		'Zip Code' => 10,
		'Email' => 20,
		'Phone' => 13,
	);

	$rn = 0; // row number
	// Build the XLS file using PEAR
	$xlsBook = new Spreadsheet_Excel_Writer();
	$xlsBook->send("registrations.xls");
	$xls =&#038; $xlsBook->addWorksheet('Registrations');
</pre>
<p>Everything else is now just as the same as it would be with the Spreadsheet-Excel_writer. Create the formats as you would like, for text, numerics, specialized strings, colors, etc. Write the sheet headings, if you so desire</p>
<pre>
	/* Create styles for the spreadsheet */
	$format_bold =&#038; $xlsBook->addFormat();
	$format_bold->setBold();

	$main =&#038; $xlsBook->addFormat(
		array('Size' => 14,
			'Align' => 'center',
			'Color' => 'black',
			'Bold' => 'true'
		));
	$main->setBold();

	$formatText =&#038; $xlsBook->addFormat(array('Size' => 11));

	$cn = 0;
	$xls->write($rn, 0, "CONFERENCE REGISTRATIONS", $main);
	$xls->mergeCells($rn,0,$rn,11);
	$rn++;
</pre>
<p>As you can see, just use the writer calls to write the data, format it, and do what you need. To get more information on this, please <a href="http://pear.php.net/package/Spreadsheet_Excel_Writer/docs">check the PEAR documentation for this library</a>. </p>
<p>Finish up the column headings by doing a quick little loop</p>
<pre>
	// Set up the headings of the columns
	foreach ( $titles as $t => $val){
		$xls->setColumn($cn, $cn, $val);
		$xls->write($rn, $cn++, $t, $format_bold);
	}
	$rn++;
	// reset the column num
	$cn = 0;
</pre>
<p>Now you can do the actual rows in a loop:</p>
<pre>
	foreach ( $registrations as $r ){
		$xls->write($rn, $cn++, $r['Registration']['name'], $formatText);
	    $xls->write($rn, $cn++, $r['Registration']['address'], $formatText);
	    $xls->write($rn, $cn++, $r['Registration']['city'], $formatText);
	    $xls->write($rn, $cn++, $r['Registration']['state'], $formatText);
	    $xls->write($rn, $cn++, $r['Registration']['zip_code'], $formatText);
	    $xls->write($rn, $cn++, $r['Registration']['email'], $formatText);
	    $xls->write($rn, $cn++, $r['Registration']['contact_phone1'], $formatText);
	    // cycle to the next row
	    $rn++;
	    // Reset the column
	    $cn = 0;
	}

	$xlsBook->close();
	exit();
} // end of function
</pre>
<p>Now, this does the work for me on my code. To call it in the view, I have a page that shows all registrations on the page, the function name is "registrations". I set a variable in this function for the ID number to be passed to the view. In the view for this function, I have put the following:</p>
<pre>
if ( $param != 'all') {
	echo "&lt;p&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - - &lt;b&gt;";
	echo $html->link(__('EXPORT DATA', true), array('action' => 'export', $param) );
	echo "&lt;/b&gt; - - &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;";
}
</pre>
<p>So I want a specific conference. If there is not one, and they are viewing all registrations for all conferences, then it does not show the link. But if it is a specific id, then it shows the link to export with the corresponding parameter for the ID. </p>
<p>And there it is. Using the Spreadsheet_Excel_Writer PEAR library with CakePHP 1.2. </p>
<p>Again, this works for me, and there may be a better way of doing things, and if so, please feel free to tell me. I am always looking for new things to learn. </p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2009/05/04/pear-and-cakephp/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Regular Expressions</title>
		<link>http://www.hirdweb.com/2009/04/05/regular-expressions/</link>
		<comments>http://www.hirdweb.com/2009/04/05/regular-expressions/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 01:55:06 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[cakePHP]]></category>
		<category><![CDATA[regex]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=168</guid>
		<description><![CDATA[Here is a topic that has really flustered a lot of developers. Regular expressions is a concept that can be hard to get a real handle on. PHP has a couple of functions that can help do regular expressions. The one I focus on most is using the function: preg_match() This is a very useful [...]]]></description>
			<content:encoded><![CDATA[<p>Here is a topic that has really flustered a lot of developers. Regular expressions is a concept that can be hard to get a real handle on. PHP has a couple of functions that can help do regular expressions. The one I focus on most is using the function:<br />
preg_match()</p>
<p>This is a very useful tool, and if you look at the <a href="http://us3.php.net/manual/en/function.ereg.php">PHP manual for ereg()</a>, it states that the function &#8220;preg_match&#8221; is a faster alternative to &#8220;ereg()&#8221;. Now while I am not going to get into the details of the speed and response times for both functions, as there will always be someone with a different opinion or case that shows how their way is better, and that is fine. What most people have a hard time dealing with is getting the actual match to do what is needed. There are times when It is just easier to do a Google search and get some code that someone else has already done and plug it in. But the real power is knowing what you are doing first, that way you can build your own.</p>
<p>For this example, we can take a look at CakePHP&#8217;s own little validation object. When you set up a model and add some validation to it, it calls this object. Based on the data that this going into the tables, it will call one of these functions. The way these functions work is by checking the input for a specific character list/set that should be contained in the text. If the entry does not match up, then it is not validated. The way CakePHp does this is by using the preg_match() function.<br />
<span id="more-168"></span></p>
<p>If you are new to regular expressions, then seeing something like this:</p>
<pre>
define('VALID_EMAIL', "/^[a-z0-9!#$%&#038;'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&#038;'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2,4}|museum|travel)$/i");
</pre>
<p>may be a little scary. But never fear, this is not as bad as it seems. It just looks real scary. And besides, even Cake made it a little better. </p>
<p>So let&#8217;s look at this function:</p>
<pre>
function email($check, $deep = false, $regex = null) {
. . .
	if (is_null($_this->regex)) {
		$_this->regex = '/^[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i';
	}
	$return = $_this->_check();
. . .
}

function _check() {
. . .
	if (preg_match($_this->regex, $_this->check)) {
		$_this->error[] = false;
		return true;
	} else {
		$_this->error[] = true;
		return false;
	}
}
</pre>
<p><em>If you would like to know more about the function, then please browse to the CakePHP manual to get more info about that function, since all this is going to do is point out the regex part of it. </em></p>
<p>First off, the function called is &#8220;email&#8221;. In this function, there is a regex match set that is the following:<br />
&#8216;/^[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+)*@&#8217; . $_this->__pattern['hostname'] . &#8216;$/i&#8217;</p>
<p>It passes that to the _check() function, which puts this regex pattern to the email address that is entered to see if there is a match. So to jump ahead if someone were to put in an email address of:<br />
 &#8211; flavio@nothing.com<br />
It would pass that function. (NOTE: this does not mean it is a valid email address that can recieve emails, it just means that the characters in the email address are in the valid format of (address_name)@(hostname).(Extension) )</p>
<p>But this also means that someone could put in the email address:<br />
 &#8211; flavio@nothing.show<br />
And that would pass as well, while the following email addresses:<br />
 &#8211; flavio<br />
 &#8211; flavio@nothing<br />
 &#8211; flavioATnothingDOTcom<br />
would fail. </p>
<p>But now that we know that, how did we get there? </p>
<p>Let&#8217;s break down the match. </p>
<p>The first thing, we are looking for a pattern, so we need to ad the following:<br />
/ /<br />
around the pattern. This is a Perl syntax that is followed for finding patterns. Now the bookends come, with the caret ( ^) and the dollar sign ( $ ). The caret means to search the beginning of the string for the pattern, and the dollar sign matches the end of the string. In this example, the caret matches the first part of the email address entered, and the dollar sign matches the end. </p>
<pre>
'/^[ ]$/'
</pre>
<p>So we are off to a good start. but there since we are looking for a pattern that does not need to be case sensitive, as we do not care if there are uppercase letters or not, we need to add an &#8220;i&#8221; at the end. </p>
<pre>
'/^[ ]$/i'
</pre>
<p>Now we are ready to start looking at the beginning of the string. We are going to put this in a bracket to group the characters, or create a class. We want to get any valid characters for an email address. This would include any letters, numbers and some special characters. We will need to escape some of these (using the &#8220;\&#8221; to escape)</p>
<pre>
'/^[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]$/i'
</pre>
<p>This will now look for the address name, sort of. As long as there are no periods in the address account name, it will work, but there are addresses out there that have a &#8220;.&#8221; in it:<br />
 &#8211; flavio.elguappo@nothing.com<br />
would not pass the validation as of yet (given that we would have also added the domain by the time it is checked). </p>
<p>So we need to add that match set in to the expression. CakePHP does this by using an atomic grouping. Using the parenthesis usually means that a &#8220;backreference&#8221; should be done. You can escape this by using &#8220;?:&#8221;. The question mark-colon combo after the first parenthesis signifies that what is coming is not a backreference. Now, to get the addresses that have a period in the account name we add this:<br />
(?:\.[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+)</p>
<p>As you can see, this is almost the same pattern as before. We want to check the same things again after any appearance of a period. So now it looks like:</p>
<pre>
'/^[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+)$/i'
</pre>
<p>Last things here, we need to account for the @ symbol in the address, and add the domain name. Since CakePHP already takes care of that, they have there own addition:</p>
<pre>
'/^[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i'
</pre>
<p>And the final php code would be as follows:</p>
<pre>
$checked = preg_match('/^[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&#038;\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i', $email_address_to_check);

return $checked;
</pre>
<p>Now I am sure I glossed over some regex rules and explanations. I will never claim to be an expert on regex, as I am still learning as much as I can about this. Now this is not the only way to check an email address. If you do not use CakePHP and the real nifty built in helper, then you can use this one:</p>
<pre>
"/^[^0-9][A-z0-9_]+([.][A-z0-9_]+)*[@][A-z0-9_]+([.][A-z0-9_]+)*[.][A-z]{2,4}$/"
</pre>
<p>This one is similar, check the account name for valid characters, see if it has any periods in the name, check the @ symbol and then check the domain name, and then the domain extension, allowing for 2-4 characters in the extension. </p>
<p>And if you want to get some real good info on other regex info, here are a couple of links I found useful:<br />
<a href="http://www.webcheatsheet.com/php/regular_expressions.php">http://www.webcheatsheet.com/php/regular_expressions.php</a><br />
<a href="http://www.regular-expressions.info/tutorial.html">http://www.regular-expressions.info/tutorial.html</a><br />
<a href="http://us3.php.net/manual/en/function.preg-match.php">http://us3.php.net/manual/en/function.preg-match.php</a><br />
(Make sure you read the comments as they have some good info)</p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2009/04/05/regular-expressions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ideas to help code</title>
		<link>http://www.hirdweb.com/2009/03/31/ideas-to-help-code/</link>
		<comments>http://www.hirdweb.com/2009/03/31/ideas-to-help-code/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 15:47:14 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Ideas and Sorts]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=166</guid>
		<description><![CDATA[I have caught myself doing this often, and need to always regroup and figure out what is a better way to do these types of things. I am speaking of coding in absolutes. What does this mean? Coding a type of block that is hard set to do something exactly. Like for an example, let&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I have caught myself doing this often, and need to always regroup and figure out what is a better way to do these types of things. I am speaking of coding in absolutes. What does this mean? Coding a type of block that is hard set to do something exactly. Like for an example, let&#8217;s say that there is a calendar application. In this calendar application, there are four languages to select from, so a code block does something like this:</p>
<pre>
// Controller file
$eng = $this->Users->Select("language", "English");
$spn = $this->Users->Select("language", "Spanish");
$gmn = $this->Users->Select("language", "German");
$fre = $this->Users->Select("language", "French");
</pre>
<p><em>**Note this is not using any kind of construct in CakePHP, Symfony or any particular framework, just an example of a User class with a function called Select passing in 2 variables.</em></p>
<p>As an example, the view of this same code may be something like:</p>
<pre>
// Controller File
$this->set('lang', array($eng, $spn, $gmn, $fre);
</pre>
<p>Now while this may work for the time being, it could cause a hassle later on if there are more languages that the application will need to support.<br />
<span id="more-166"></span></p>
<p>Now, this is not saying that the above example is bad practice, because it is entirely possible that it will only need these two languages. Like if you were programming an application for a Canadian business, it would need to have both English and French. There may never be a requirement for Spanish, German, or any other language. What I am doing more of now, is making things more dynamic, to handle new items seamlessly and with little new code. </p>
<p>Taking the above example, we could put it into something like so:</p>
<pre>
// Model File
class User extends someBaseModelObject {
. . .
function getLanguages(){
      $langs = array(
          "English", "German", "Spanish", "French"
      );
      return $langs;
}

// Controller File
$langs = $this->User->getLanguages();

$this->set('lang', $langs);
</pre>
<p>Now if there is a new language, all that needs to be updated is the Model file instead of adding new lines of code to one part, updating another line of code in another part, and so on. </p>
<p>Is this possibly an oversimplification of this idea? Yes it is. But I do not write this as a simplification, but to just show something I am starting to focus on more, is that I need to make things more dynamic so I do not have to re-do code as new things are added. I use language as an example in this post, because that is just an easy example to show. There are many things that could be done for dynamic purposes. It is all about thinking about the right way to code. </p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2009/03/31/ideas-to-help-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CakePHP and Symfony</title>
		<link>http://www.hirdweb.com/2009/03/02/cakephp-and-symfony/</link>
		<comments>http://www.hirdweb.com/2009/03/02/cakephp-and-symfony/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 04:02:05 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[cakePHP]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=158</guid>
		<description><![CDATA[There are many frameworks out there that have a good deal of uses to them. In this post, the focus is on CakePHP vs Symfony. Does this mean one will be a winner over the other? Not really. I will only present what I have come to find in each of these frameworks and how [...]]]></description>
			<content:encoded><![CDATA[<p>There are many frameworks out there that have a good deal of uses to them. In this post, the focus is on CakePHP vs Symfony. Does this mean one will be a winner over the other? Not really. I will only present what I have come to find in each of these frameworks and how I have used them in different ways.</p>
<p>Since this will be a comparison, most of the ideas will revolve around the tutorials that each camp has created. Plus, I will be only looking at the latest stable versions, so they are:<br />
CakePHP: 1.2.1.8004<br />
Symfony: 1.2</p>
<p>Each have their own tutorials, and they are at the following:<br />
Symfony: <a href='http://www.symfony-project.org/jobeet/1_2/Propel/en/01' target='_blank' title='Jobeet Tutorial'>Jobeet Tutorial</a>, using Propel.<br />
CakePHP: <a href='http://book.cakephp.org/view/219/Blog' target='_blank' title='CakePHP Blog'>CakePHP Blog</a></p>
<p><strong>First off, about the tutorials. </strong><br />
I really do think that Symfony has a better tutorial. It is a lot more intensive and sometimes confusing, which means it also goes more in depth about what this framework can do, and how to do it. This tutorial also brings in a good deal of real world dilemmas. </p>
<p>CakePHP&#8217;s blog tutorial is just a standard blog tutorial, which everyone seems to have anymore. It is a good tutorial, and it does show off some real good aspects of the framework, but it really does lack some of the &#8220;gotchas&#8221; that would really happen in the real world.<br />
<span id="more-158"></span></p>
<p><strong>Installation Process and Upgrade</strong><br />
Symfony &#8211; Getting Symfony is pretty easy. You can download it from the site in a &#8220;sandbox&#8221; form. It is pretty easy and able to do much right from the download. But what makes this framework so wonderful about getting it, is that you can use PEAR to download it. By following the <a href='http://www.symfony-project.org/installation/1_2' target='_blank' title='Symfony Detailed Installation Instructions'>detailed installation instructions</a>, there are a few different ways to install this. If you have the PEAR libraries, it makes it very easy to install and upgrade. </p>
<p>CakePHP &#8211; <a href='http://book.cakephp.org/view/32/Installation' target='_blank' title='CakePHP Installation'>Getting CakePHP is also easy</a>. While it does not have a PEAR installation path, the zip file is available in many forms, like .zip, or .gz, bz2, or .dmg. After you unzip the file, just plop it in the web accessible document root. It will work right out of the box provided on most systems. It is supposed to work right away with mod_rewrite, so certain Windows systems may have issues. (However, I have loaded it on a Windows Vista system and it worked ok, so take that for what it is worth). The directory structure allows it to work right away as is. However, the webroot  app can be moved outside the normal directory structure to make a different configuration. Upgrading can be done as well, usually by overwriting the /cake directory.</p>
<p>But as with everything, always follow directions on upgrading. Very important. </p>
<p><strong>Basic Ideals Behind the Framework</strong><br />
Symfony &#8211; Using a basic MVC (Model-View-Controller) design theory, it really does separate the logic portions of the application. By using the built in view, it keeps the majority of the PHP out of the HTML area. The models use more of a YAML approach to build the data objectivity. YAML (YAML Ain&#8217;t a Markup Language, morphed from Yet Another Markup Language). It can use Propel or Doctrine to help in this. The Jobeet tutorial I used was the Propel version. The controller is a standard idea of what you would expect in a controller. </p>
<p>CakePHP &#8211; Uses a MVC design theory, and really follows the same patterns. The real strength of CakePHP, at least to me, is it does not mess around with another version of data markup, like YAML. Some people like it, I do not prefer it. So to me this is better. However, the model also provides a real easy way to provide data validation for each row in the table. By using basic PHP concepts, you can set up validation for inserts and/or updates. The view is a little less robust than the Symfony version. While it does help with different pages/views, the framework does have a little too much reliance on php generated code. However, it does have excellent helpers to help generate HTML, forms, tables, etc. </p>
<p><strong>Routing and Fancy URLs</strong><br />
Symfony &#8211; By updating the file: apps/frontend/config/routing.yml (yes it uses another YAML format) you can route certain calls to certain pages. However, this makes it real easy to create Fancy URLs in which the URL actually has some real data in it instead of something like : &#8216;jobs/2/34&#8242;. </p>
<p>CakePHP &#8211; In order to create Fancy URLs, CakePHP needs to have the default routes updated. While it is not as easy as it is in Symfony, it is possible. By using the <a href='http://book.cakephp.org/view/46/Routes-Configuration' target='_blank' title='Routes Configuration'>detailed instructions</a> in the Cookbook, you can set this up to have the nice URLs. </p>
<p><strong>Command Line Interface Utilities</strong><br />
Symfony &#8211; Now while this is not an instructional post on how to use each CLI, I must say, I like the Symfony version a lot better. While it is clean and real forthcoming, there is a lot you can do with it. Combine that with the Propel and you have a really good CLI tool to help with the application. </p>
<p>CakePHP &#8211; The CLI in CakePHP leaves a little to be desired. While it is very helpful in creating the Models, the Controllers, and the Views, it really does not do as much. But for CakePHP this is actually ok. There are a lot of things to do with the CLI, but not as much as Symfony has.</p>
<p><strong>Configuration</strong><br />
Symfony &#8211; Symfony seems to thrive on configurations for some reason. There is a whole directory dedicated to just config files. To me this seems a bit of overkill to do it this way. However, with the way Symfony is laid out, it works this way. There are different things to configure, and following the instructions is key. Especially since these files are read from top to bottom, so if you have a custom config in the routes after the default entry, it will never find the custom one. </p>
<p>CakePHP &#8211; There is also a full directory dedicated to configurations as well, but less files to parse through. Some may say this is a bad thing, some may say this is a good thing. The main files to look at are the core.php and database.php files. The routes.php file is also useful, but all in all, less config files to deal with. </p>
<p><strong>Naming Conventions</strong><br />
Instead of separating this area, it is important to note that with each framework, there is a reason behind the madness with naming conventions. By adhering to these conventions, the framework works a lot better and can do a lot more. </p>
<p>In Symfony there is more leeway with file names, tables, etc. </p>
<p>In CakePHP they are a bit more strict, but these conventions can also be bent to suit the needs. </p>
<p><strong>Core Components</strong><br />
Symfony &#8211; There is a good deal of components in this framework, and they all have a set purpose. Instead of matching each one as a 1:1 deal, it is important to go over the usability of these components. In Symfony, there are good ones to help paginate, create sessions, scaffold an application and even do security. Using these is easy, and this is one area where both frameworks excel.  </p>
<p>CakePHP &#8211; Again, this is a great area for both frameworks. While in CakePHP, the components are not limited to the core ones, but can be extended (as in Symfony), they are very useful in helping create the application. These components are very helpful and can be a boon to even the novice programmer. </p>
<p>Both of these frameworks use these components to help speed the application up while not giving in to shoddy work. </p>
<p><strong>Testing</strong><br />
Symfony &#8211; The great thing about Symfony, is that it has a built in testing platform. The testing platform it includes is Lime. This is a great boost to development. Now while writing the application, you can actually write the test first, then the application to make sure you know which area needs more attention. Both Unit and Functional testing is handled, and can work with others like PHPUnit and Selenium. </p>
<p>CakePHP &#8211; one of the great things about this framework, is that you can choose which testing platform to use. The drawback to that is, you do not get a testing platform with the package. However, it is encouraged to use SimpleTest to do this. Installation is another step, but it helps to test the application. Writing the tests is a little more than what it takes in Symfony, however, I also believe that it does testing better than Symfony. </p>
<p><strong>Security</strong><br />
Here is a question for any and all frameworks. How secure is it? well this can be answered with the following question:<br />
How secure are you writing this application?</p>
<p>Even though Symfony and CakePHP provide good methods, components and helpers to handle securing your application, you have to use these, and use them correctly. Both proved ACL implementations, data validation and sanitation and much more to help secure the app. For any one to make a statement that one framework is more secure than the other, is just not getting the point of security. </p>
<p><strong>Documentation</strong><br />
Symfony &#8211; By far, this is the more documented framework. I have been able to find a ton of information on Symfony questions. The documentation in the cookbook is solid, and the tutorial is better than anything I have seen from other frameworks. There are other groups, IRC channels and other avenues to explore to help you get the info you need. </p>
<p>CakePHP &#8211; This framework is still coming of age. So the documentation is not always complete and not always found right away. There are groups, IRC channels and other avenues to get this information, just not as plentiful. However, that will change very shortly. With a stronger emphasis on community events and community submissions, this framework could easily have a plethora od documentation avenues by next year. </p>
<p><em>**NOTE: The following is based on my own personal experience.<br />
As mentioned in the comments below, CakePHP does have stats to show it is bigger and more popular than Symfony. Please see Nate&#8217;s comments below for the links.</em></p>
<p><strong>Community</strong><br />
Symfony &#8211; With many sites already using Symfony, the community is growing like wildfire. It was already a very abundant community, with many people helping and contributing. As with every open source project, it is only as strong as its community, which is very active. </p>
<p>CakePHP &#8211; <del datetime="2009-05-21T13:05:57+00:00">This is the up and comer. Not quite as widespread as Symfony, but it has it very loyal followers.</del> There are many ways that a community member can help out (and not just by donating), and this community is really rising fast to help meet the demand for more events and more documentation. </p>
<p><strong>Final Analysis</strong><br />
While I will not give a clear cut answer as to which is the better framework, because the best solution is the solution that will meet the needs of the business/client/etc. Sometimes that may be Symfony, sometimes it may be CakePHP. Sometimes it may just be .ASPX. But there is no real clear cut winner in my mind. </p>
<p>I have used both frameworks to develop applications. Some of them huge, some of them small. I find CakePHP easier to start up from the ground up. And I find the extensibility of Symfony really helpful in certain apps that require a lot of redundant user input. Both frameworks are great. I would use both of them all the time for different things. </p>
<p>Which also means that I am no expert in either one. Since I spend time in both frameworks, I know what I like and do not like about each of them. I would also wager to say that no one is really an expert in either framework, unless you are the main developer of that project. What I am presenting is the different aspects I have found from my development standpoint. Some may see things missing in this list, which I am sure there are. These are some of the things to decide when trying to figure out if a framework will help you. Some developers also are of the opinion that no framework is good and would rather develop from scratch. That is fine too. Remember that the best solution to the problem, is the solution that solves the main crux of the problem. </p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2009/03/02/cakephp-and-symfony/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Non Code Code</title>
		<link>http://www.hirdweb.com/2009/02/17/non-code-code/</link>
		<comments>http://www.hirdweb.com/2009/02/17/non-code-code/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 01:17:33 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Ideas and Sorts]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[documentation]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=156</guid>
		<description><![CDATA[We all get to a point in the coding process where there needs to be &#8220;non-code&#8221; code. This does not have the same type of structure or verbiage as the construct of PHP, C# or anything else. This is our own little distinct code. It may seem like I am talking about lol-catz, which I [...]]]></description>
			<content:encoded><![CDATA[<p>We all get to a point in the coding process where there needs to be &#8220;non-code&#8221; code. This does not have the same type of structure or verbiage as the construct of PHP, C# or anything else. This is our own little distinct code.</p>
<p>It may seem like I am talking about lol-catz, which I am not. This is the code we do inside of our code. It extends beyond the logic of the code, or hopefully it does. If your own little code defies all logic, then maybe the code will break hard one day. This code is our own little way of saying how we are putting the code together. This is the notes/documentation that we write (or fail to write), the variable naming convention, object/function naming, any user messages we write, and error trapping/error handling we do. And there is more, this is just a few of the things that we get to write our own &#8220;code&#8221;.</p>
<p>One of the funniest things for me to do is to go back and look at some of my very first code. I look at the documentation I did, and it is funny to read. Some of the things I actually am scratching my head wondering what I was meaning half the time. The variables have great names which only partially tell what they were supposed to be doing. And the best is looking at the old VB 6 code where the variables followed the Microsoft horrendous naming structure.</p>
<p>Why do I write this and not about real code? Because there will be a time that you will be on both sides, writing and reading, and before you get upset that the person previous to you did not know what they were doing, they probably did. They wrote their non-code code perfectly for them and may have even understood their words at one time. And as sure as that will happen, you will write something that someone else will come in and scratch their head and say &#8220;What?&#8221;</p>
<p>So take it all in stride. Laugh about it, decipher it, and go forward. There is not enough time in the day to sit and stew about bad code/bad documentation/bad variable naming/bad non-code code.</p>
<p>And next post, I really do promise I will write more about actual code.</p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2009/02/17/non-code-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Central ACL Check</title>
		<link>http://www.hirdweb.com/2008/11/17/central-acl-check/</link>
		<comments>http://www.hirdweb.com/2008/11/17/central-acl-check/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 12:33:31 +0000</pubDate>
		<dc:creator>stephen</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[cakePHP]]></category>

		<guid isPermaLink="false">http://www.hirdweb.com/?p=142</guid>
		<description><![CDATA[With checking ACL&#8217;s, the code I use is as follows: $info = $this->Member->read(null, $id); // Check for permissions to edit this account if ( !$this->Acl->check(array('model' => 'Member', 'foreign_key' => $this->Auth->user('member_id')), $info['Member']['username'], 'update') ) { $this->Session->setFlash(__('You are not allowed to edit this user. -- ' . $this->Auth->user('member_id'), true)); $this->redirect(array('action'=>'index')); } While this works and is not [...]]]></description>
			<content:encoded><![CDATA[<p>With checking ACL&#8217;s, the code I use is as follows:</p>
<pre>
$info = $this->Member->read(null, $id);

// Check for permissions to edit this account
if ( !$this->Acl->check(array('model' => 'Member', 'foreign_key' => $this->Auth->user('member_id')), $info['Member']['username'], 'update') ) {
	$this->Session->setFlash(__('You are not allowed to edit this user. -- ' . $this->Auth->user('member_id'), true));
	$this->redirect(array('action'=>'index'));
}
</pre>
<p>While this works and is not that bad of an idea at all, there is a way to centralize this check and put it in the main app_controller.php file.<br />
<span id="more-142"></span></p>
<p>Depending on the scope of the project, or the business needs of the application, this check can be done and centralized so that there is not the need to put the ACL check in its form above in every action in every controller that needs to have this done. So for the Member controller, you may need to copy/paste the code above to check the ACL for permissions to view, edit, delete, add, etc. That is just one controller, what if there were others as well, like Post, Event, Pictures, etc. That is going to be a lot of code to write to check the ACL. </p>
<p>Now even though the <a href='http://book.cakephp.org/view/471/Checking-Permissions-The-ACL-Component' target='_new' title='5.1.3.4 Checking Permissions: The ACL Component'>Cookbook on checking ACLs</a> shows a simple one line approach:</p>
<pre>
$this->Acl->check(array('model' => 'User', 'foreign_key' => 2356), 'Weapons');
</pre>
<p>it is not just a simple one line approach. There are other things to consider, like what do you want to do if it fails. Is there a specific error message, does it need to redirect to a certain page, and what about if the person needs to be logged in and not need any special ACL permissions.This can get to be a few lines in length, and have a few more things that need to be done. This would be per function/action in the controller. </p>
<p>What I have done, is put the check in the app_controller. This way I need to check it with one line of code, instead of a few. I know, this may seem trivial, but this is something that could get really drawn out in heavier applications. </p>
<p>In the app_controller.php file, I created two functions:<br />
_enforceAccess()<br />
_checkAccess()</p>
<p>First I will explain the _enforceAccess() function. Since I use the model method of ACL, the function is looking for the following:<br />
model<br />
user&#8217;s ID<br />
Object being acted on<br />
Action for the object<br />
Redirect Page</p>
<p>I also do a check for logged in status as well, to make sure that if an action is needed after login, like viewing, then I can check that here as well, instead of per function in the controller. I set all of the parameters to null, in case there is no needed permission check and I need to check logged in status. </p>
<p>So the way this function looks after everything is added:</p>
<pre>
function _enforceAccess($model = null, $id = null,$object = null, $action = null, $redirect = array("/")) {
	if (!$this->loggedin) {
		$this->Session->setFlash('You do not have permissions to carry out the requested action.');
    	$this->redirect('/members/login');
    	exit();
    }
	if ($this->_checkAccess($model,$id, $object, $action)) {
		return true;
	}
	$this->Session->setFlash('You do not have permissions to carry out the requested action.');
	$this->redirect($redirect);
	exit();
}
</pre>
<p>This function first checks for logged in status, if the person is logged in, then I go to the next step, if not, then I would redirect to the login page to get the user to log in to perform this action. As a side note to this: <i>If you are using the Auth component, after the person logs in, the Auth component will redirect back to the prior page where this check was made.</i> </p>
<p>After checking logged in status, it makes a call to the _checkAccess() function and passes the parameters needed to check the ACL. If everything works out ok, and the person has the permission to do the requested action on the object, then the code sends it back to the controller to do any other scripts. The person is authorized, and so it lets them through. </p>
<p>If the person does not have the permission, then they are redirected to the page that is set as they redirect. If no page is given, then the default is just the top level page, or home page of the application. If you specify a redirect page. Either way, the error message is printed out for the end user. </p>
<p>In the _checkAccess() function, it requires the parameters to check the ACL:<br />
$model<br />
$id<br />
$object<br />
$action<br />
This function does the straightforward work. </p>
<pre>
function _checkAccess($model = null,$id = null, $object = null, $action = null) {
	// safety check just in case
	if ( !$this->loggedin ) {
		return false;
    }
    // Just checking for logged in status in this case
	if ( is_null($object) &#038;&#038; is_null($action) ) {
		return true;
	}
	// Check access to a specific record
	if ( !is_null($object) &#038;&#038; !is_null($action) ) {
		if ( $this->Acl->check(array('model' => $model, 'foreign_key' => $id), $object, $action) ) {
			return true;
		}
	}
	// Everything failed, so return false
	return false;
}
</pre>
<p>The first thing the function checks is a safety check. Just to make sure, we check to see if they are logged in. If they are not, return false. This is not really a necessary step, but for this application, one of the requirements was paranoid-like logged in checking. The next feature is to make sure logged in users are authorized. If there is no real check for permissions, and they just want to make sure the person is logged in, then this is one method I use to check this. Your application may be different, and that is ok. The final feature is to check a real object and action. We just put the ACL check here, and return true if it is allowed. If all of the IF statements do not get run, then it returns false. So when if you use this method, make sure that the needed checks are done, and the parameters that are passed have a real value and are not just NULL. </p>
<p>So this accounts for the checks I do now. I take out the calls in the controllers and replace them with this call. To see this in action, lets look at a few examples. </p>
<p>A member is logged in and would like to edit their friend&#8217;s profile:</p>
<pre>
function edit($id = null) {
    $info = $this->Member->read(null, $id);
    $this->_enforceAccess("Member", $this->Auth->user('member_id'),  $info['Member']['username'], 'update', array('controller' => "members"))
    // The rest of the action code goes here
}
</pre>
<p>This will do all the checks for you, and redirect to the members index page if the person does not have permission to edit other user&#8217;s account information. </p>
<p>Another example: a person who is logged in wants to view all posts. Posts are visible to only logged in accounts.</p>
<pre>
function view() {
    $this->_enforceAccess();
    // The rest of the action code goes here
}
</pre>
<p>Since this is open to everyone who is logged in, we do not need to send any parameters over, we just need to make sure they are logged in. Since the _enforceAccess() function already checks for this, we do not need to do any further checks in this function. </p>
<p>Another example: an admin wants to delete an account, and this account is the admin account, (yes this has happened before where an admin was &#8220;three sheets to the wind&#8221; and trying to perform an emergency delete of an employee who was terminated, and tried to delete their own account):</p>
<pre>
function delete($id = null) {
    $info = $this->Member->read(null, $id);
    $this->_enforceAccess("Member", $this->Auth->user('member_id'),  $info['Member']['username'], 'delete', array('controller' => "members"))
    // The rest of the action code goes here
}
</pre>
<p>Last example: A member is logged in and trying to view all events for the group they do not belong to:</p>
<pre>
function viewEvents($group_id = null) {
    $info = $this->Events->read(null, $group_id);
    $this->_enforceAccess("Event", $this->Auth->user('member_id'),  $info['Events']['group_id'], 'view', array('controller' => "events", 'action' => "comingup"))
    // The rest of the action code goes here
}
</pre>
<p>In this check, the code pulls in the groups events based on the foreign key of group_id in the Events table. We are enforcing the the access to view these events, based on the person&#8217;s ID. If the person&#8217;s ID does not have permission to view the events for that group, it will redirect the user to the page events/comingup. Which does it&#8217;s own little thing. Each example here will spit out the error message in the _enforceAccess() function. </p>
<p>Now, even though these two functions added some more lines of code, it has reduced what is needed to be done in each controller. Instead of doing a check in each function in each controller, with its accompanying lines of code, you have just one check to do, usually in one line of code. </p>
<p>What works so well for me in this, is that the _enforceAccess() method can be extended. If you want a generic error message, and then do special errors on certain cases, add a new parameter for the error message, and a check to see if it is filled out. If it is use the special error message, if not, then use the default. If you need additional permission checks, this method also provides a central point to do those. </p>
<p>Remember that in any application, it is all what is required by the business/client/needs. This may work in some instances, and not in others.</p>

<!-- Wordpress Connect Modules v1.05 -->]]></content:encoded>
			<wfw:commentRss>http://www.hirdweb.com/2008/11/17/central-acl-check/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
