<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3300153981717062813</id><updated>2011-11-27T17:06:45.620-08:00</updated><category term='PHP'/><category term='Grails'/><category term='Smarty'/><category term='Encryption'/><category term='CSV'/><category term='Apache'/><category term='MySQL'/><category term='Sphinx'/><category term='SEO'/><category term='Search'/><category term='Groovy'/><category term='HTML'/><title type='text'>Struggling Developers</title><subtitle type='html'>Fighting for survival</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3300153981717062813.post-5843277171760010939</id><published>2009-01-28T12:18:00.000-08:00</published><updated>2009-01-28T12:29:58.552-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title type='text'>Grails Tips Part I – Domain Classes</title><content type='html'>I have been working a lot with Grails lately and I have to say that I love it!&lt;br /&gt;&lt;br /&gt;It has allowed me to create some great web applications in a very fast and reliable way. While developing these applications, I learned a lot of useful things that I would like to share to you. Today I’ll give you some tips regarding Domain Classes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1) Date created &amp;amp; Last Updated&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you want Grails to handle the date in which an object is created and the last time it was updated, all you have to do is add the following attributes to your domain class:&lt;br /&gt;&lt;br /&gt;Date dateCreated&lt;br /&gt;Date lastUpdated&lt;br /&gt;&lt;br /&gt;As easy as that! Grails will automatically set the value for this two attributes when an object is created and every time it is updated.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2) Field order&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you want Grails to generate the fields for the create, edit &amp;amp; show views in a particular order, just define that order on the constraints. If the attribute doesn’t require a specific constraint (such as maxSize, unique, nullable, etc), just put the attribute on the constraints and leave the constraint empty.&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;static constraints = {&lt;br /&gt;    name()&lt;br /&gt;    address()&lt;br /&gt;    city(nullable:true, blank:true)&lt;br /&gt;    phone(nullable:true, blank:true)&lt;br /&gt;    mobile(nullable:true, blank:true)&lt;br /&gt;    email(email:true)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3) Unique by group&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you want an attribute on a domain class to be unique, but only grouped by another attribute, you can do it. In the following example, the company name will be unique only for companies from the same client:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;class Company {&lt;br /&gt;&lt;br /&gt;Client client&lt;br /&gt;String name&lt;br /&gt;String address&lt;br /&gt;&lt;br /&gt;static constraints = {&lt;br /&gt;    name(size:3..50, blank:false, unique:'client')&lt;br /&gt;    address()&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4) Change database mapping for String attribute&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Grails will map the String attributes on your domain class to varchar(255) by default. If you want a String attribute mapped to text, here’s how you do it:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;static mapping = {&lt;br /&gt;    columns{&lt;br /&gt;        attribute_name type:"text"&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Stay tuned for more Grails tips!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3300153981717062813-5843277171760010939?l=strugglingdevelopers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/5843277171760010939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3300153981717062813&amp;postID=5843277171760010939' title='43 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/5843277171760010939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/5843277171760010939'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/2009/01/grails-tips-part-i-domain-classes.html' title='Grails Tips Part I – Domain Classes'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><thr:total>43</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3300153981717062813.post-538049332287936526</id><published>2008-12-16T13:36:00.001-08:00</published><updated>2008-12-16T13:36:49.891-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Encryption'/><title type='text'>Text encryption on PHP</title><content type='html'>A long time ago I had to implement text encryption on Java for some messages that needed to be sent through a socket, and I found a very good encryption algorithm on the net.&lt;br /&gt;&lt;br /&gt;Recently I needed text encryption for a similar scenario, but this time the technology was PHP. So, I decided to "translate" this algorithm from Java to PHP and now I want to share it with you, in case you need it.&lt;br /&gt;&lt;br /&gt;Encrypt:&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;function encrypt($text, $seed) {&lt;br /&gt; $encText = "";&lt;br /&gt; $pwLength = strlen($seed);&lt;br /&gt; $i=6;&lt;br /&gt; for ($x=0; $x &lt; strlen($text); $x++) {&lt;br /&gt;  $i = ($i%$pwLength)+1;&lt;br /&gt;  $a = ord(substr($text, $x, 1));&lt;br /&gt;  $b = ord(substr($seed, $i-1, 1));&lt;br /&gt;  $encText .= ($a ^ $b);&lt;br /&gt;  $encText .= ",";&lt;br /&gt; }&lt;br /&gt; return $encText;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Decrypt:&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;function decrypt($text, $seed){&lt;br /&gt; if(!$text == ""){&lt;br /&gt;  if (strlen($text) == 1)&lt;br /&gt;   return "999999";       &lt;br /&gt;&lt;br /&gt;  $pwLength = strlen($seed);&lt;br /&gt;  $strText = "";&lt;br /&gt;  $hold;&lt;br /&gt;  $i = 6;&lt;br /&gt;  $crypt = explode("," ,$text);&lt;br /&gt;  for ($x = 0; $x &lt; sizeof($crypt) - 1; $x++) {&lt;br /&gt;   if (strlen($crypt[$x])&gt;2) {&lt;br /&gt;    $test=0;&lt;br /&gt;    $test = (int) $crypt[$x];&lt;br /&gt;    if ($test == 0) $crypt[$x] = substr($crypt[$x], 1,1);&lt;br /&gt;   }&lt;br /&gt;   $i = ($i % $pwLength) + 1;&lt;br /&gt;   $a = (int)($crypt[$x]);&lt;br /&gt;   $b = ord(substr($seed, $i-1, 1));&lt;br /&gt;   $hold = chr($a ^ $b);&lt;br /&gt;   $strText .= $hold;&lt;br /&gt;  }&lt;br /&gt;  return trim($strText);&lt;br /&gt; }else{&lt;br /&gt;  return "";&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;$msg = "This is the best blog!";&lt;br /&gt;$seed = "mySeed";&lt;br /&gt;echo $msg;&lt;br /&gt;$encrypted = encrypt($msg, $seed);&lt;br /&gt;echo $encrypted;&lt;br /&gt;$decrypted = decrypt($encrypted, $seed);&lt;br /&gt;echo $decrypted;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;This is the best blog!&lt;br /&gt;57,17,58,22,69,13,30,89,39,13,0,68,15,28,32,17,69,6,1,22,52,68,&lt;br /&gt;This is the best blog!&lt;br /&gt;&lt;br /&gt;I hope this algorithm helps you protect your information!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3300153981717062813-538049332287936526?l=strugglingdevelopers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/538049332287936526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3300153981717062813&amp;postID=538049332287936526' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/538049332287936526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/538049332287936526'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/2008/12/text-encryption-on-php.html' title='Text encryption on PHP'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3300153981717062813.post-3841340007198288015</id><published>2008-09-25T15:24:00.000-07:00</published><updated>2008-09-25T15:32:58.962-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sphinx'/><category scheme='http://www.blogger.com/atom/ns#' term='Search'/><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><title type='text'>MySQL full-text search optimization</title><content type='html'>A while ago we where developing a classified ads site for one of our most important clients. In this site, every ad belongs to a region (city, country) and a category (e.g. vehicles&gt;buy/sell&gt;cars).&lt;br /&gt;&lt;br /&gt;When the visitor accesses the homepage, the region is determined from their IP address so only the ads for that region are displayed (the visitor can change the region) and every search is performed only for the ads on that region as well.&lt;br /&gt;&lt;br /&gt;At first everything was working great, but when some regions started to have more than 500.000 ads, that’s when we started to get nervous. Every search on these regions took more than 30 seconds, which is obviously unacceptable. We tried everything: create a full-text field on the ads table, optimized the database queries, but could not bring the search time down to a reasonable amount. At this point I was considering fleeing the country, changing my name and closing all my email accounts so that our client couldn’t find me, and start a new life selling bananas in Brazil. I’m glad I didn’t do it (I think).&lt;br /&gt;&lt;br /&gt;After a lot of research over the internet, we came across a miracle. That miracle is called Sphinx Search (http://www.sphinxsearch.com). This is an open-source solution for all your MySQL full-text search problems.&lt;br /&gt;&lt;br /&gt;How does it work? You simply install the software on your server, create a configuration file for the table you want to perform the searches on and run the indexing process. This will create a dictionary file that allows you to perform searches in less than a second, on huge tables. You can also provide filters on any of the fields of the table as well as perform sorting on the result set. This software also provides a PHP API so that you can access it from your PHP pages and process the result set.&lt;br /&gt;&lt;br /&gt;An important side note: since now all searches are performed on the data dictionary (which is created by a process than can take several minutes, so it’s advisable to run it only once or twice a day) and users can be adding new rows to the original table, the data dictionary will not have all the current data.&lt;br /&gt;&lt;br /&gt;How can you solve this issue? Easy, you also create a delta dictionary file with the new rows and schedule a process to rebuild it many times a day (depending on how often new rows are added to your table). This delta dictionary is also included on the same configuration file as the master dictionary, but using a different query.&lt;br /&gt;&lt;br /&gt;How do you combine both dictionaries? You can have a process that runs at midnight rebuilding the master dictionary with the overall query (e.g. SELECT * FROM ad) and another that runs every fifteen minutes rebuilding the delta dictionary with the new rows added that day. When the process runs again at midnight to rebuild the master index, the data from the delta dictionary will be incorporated to the master index and the delta index will be reset.&lt;br /&gt;&lt;br /&gt;Now every search on the site is working great and we are even using it to obtain all the ads from a specific category without a keyword, because it also takes less than a second. It also allows you to extend the search filtering by fields, grouping and sorting.&lt;br /&gt;&lt;br /&gt;Here’s an example configuration file for my classified ads site:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="html"&gt;&lt;br /&gt;source ads {&lt;br /&gt;    type = mysql&lt;br /&gt;   &lt;br /&gt;    sql_host = localhost&lt;br /&gt;    sql_user = user&lt;br /&gt;    sql_pass = password&lt;br /&gt;    sql_db = myDb&lt;br /&gt;    sql_port = 3306&lt;br /&gt;&lt;br /&gt;    sql_query = \&lt;br /&gt;            SELECT \&lt;br /&gt;                    id, title, descr, \&lt;br /&gt;                    catid, UNIX_TIMESTAMP(hw_added) as hw_added, \&lt;br /&gt;                    UNIX_TIMESTAMP(exp_date) as exp_date \&lt;br /&gt;            FROM \&lt;br /&gt;                    ad;&lt;br /&gt;   &lt;br /&gt;    sql_attr_str2ordinal = v_title&lt;br /&gt;    sql_attr_uint = catid&lt;br /&gt;    sql_attr_timestamp = hw_added&lt;br /&gt;    sql_attr_timestamp = exp_date&lt;br /&gt;&lt;br /&gt;    sql_query_info = SELECT link_id FROM ec4_ad WHERE link_id=$id&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;source delta : ads&lt;br /&gt;{&lt;br /&gt;           SELECT \&lt;br /&gt;                   id, title, descr, \&lt;br /&gt;                   catid, UNIX_TIMESTAMP(hw_added) as hw_added, \&lt;br /&gt;                   UNIX_TIMESTAMP(exp_date) as exp_date \&lt;br /&gt;           FROM \&lt;br /&gt;                  ad \&lt;br /&gt;           WHERE (TO_DAYS(hw_added) = TO_DAYS(NOW()) ;&lt;br /&gt;}   &lt;br /&gt;&lt;br /&gt;index ads {&lt;br /&gt;    source = ads&lt;br /&gt;    path = /home/classifieds/sphinx/main/&lt;br /&gt;    # wordforms = /home/classifieds/wordforms.txt&lt;br /&gt;    # morphology = stem_en&lt;br /&gt;    min_word_len = 3&lt;br /&gt;    min_prefix_len = 0&lt;br /&gt;    min_infix_len = 3&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;index delta : ads {&lt;br /&gt;    source = delta&lt;br /&gt;    path = /home/classifieds/sphinx/delta/&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;indexer {&lt;br /&gt;    mem_limit = 256M&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;searchd {&lt;br /&gt;    port = 3312&lt;br /&gt;    log = /home/classifieds/searchd.log&lt;br /&gt;    query_log = /home/classifieds/query.log&lt;br /&gt;           pid_file = /home/classifieds/searchd.pid&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I hope this will be useful for you and keeps you from fleeing the country!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3300153981717062813-3841340007198288015?l=strugglingdevelopers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/3841340007198288015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3300153981717062813&amp;postID=3841340007198288015' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/3841340007198288015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/3841340007198288015'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/2008/09/mysql-full-text-search-optimization.html' title='MySQL full-text search optimization'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3300153981717062813.post-8771032082985052697</id><published>2008-09-10T19:23:00.000-07:00</published><updated>2008-09-27T09:36:00.347-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Smarty'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><title type='text'>Combining PHP and HTML pages</title><content type='html'>A while ago, one of my clients gave me the source code for one of his websites for me to make some adjustments. The first thing that shocked me when I was going through this code, was the fact that all of the HTML code was inside the PHP pages.&lt;br /&gt;&lt;br /&gt;This is just awful. It’s almost like having a toilet inside of your office (although many of you would like that). PHP pages must only contain the logic of your website and HTML pages must be used for the GUI (Graphical user interface).&lt;br /&gt;&lt;br /&gt;There is an easy way to combine PHP and HTML into a single output: Smarty (http://www.smarty.net). Smarty is a template engine which allows you to parse a HTML page from a PHP page. You don’t need to install anything. Just download the PHP code and include it on your project.&lt;br /&gt;&lt;br /&gt;Here’s a quick example:&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;index.php&lt;/span&gt;&lt;br /&gt;&lt;pre class="php" name="code"&gt; &lt;br /&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;// Smarty initialization&lt;br /&gt;require_once('Smarty.class.php');&lt;br /&gt;$smarty = new Smarty();&lt;br /&gt;&lt;br /&gt;$smarty-&gt;display(‘index.html’);&lt;br /&gt;&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;index.html&lt;/span&gt;&lt;br /&gt;&lt;pre class="html" name="code"&gt;&lt;br /&gt;&amp;lt;html&gt;&lt;br /&gt;&amp;lt;head&gt;&lt;br /&gt;&amp;lt;title&gt;Smarty test&amp;lt;/title&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt;This is a test!&lt;br /&gt;&amp;lt;/body&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Of course, there are many other many advanced uses for this tool which you can read about from the Smarty Manual. Here are some examples:&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Example 1: Variables&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let’s say you want the title of your page to be a variable which you can change from a PHP script. This is the way to do it using Smarty:&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;index.php&lt;/span&gt;&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;// Smarty initialization&lt;br /&gt;require_once('Smarty.class.php');&lt;br /&gt;$smarty = new Smarty();&lt;br /&gt;&lt;br /&gt;$smarty-&gt;assign(“title”, “My title”);&lt;br /&gt;$smarty-&gt;display(‘index.html’);&lt;br /&gt;&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;index.html&lt;/span&gt;&lt;br /&gt;&lt;pre class="html" name="code"&gt;&lt;br /&gt;&amp;lt;html&gt;&lt;br /&gt;&amp;lt;head&gt;&lt;br /&gt;&amp;lt;title&gt;{title}&amp;lt;/title&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt;This is a test!&lt;br /&gt;&amp;lt;/body&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can also assign arrays or objects and use them on you HTML page as well.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Example 2: Loop sentences&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Imagine you want to display a list of all your friends, which are stored in an array. This is how you could do that with Smarty:&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;index.php&lt;/span&gt;&lt;br /&gt;&lt;pre class="php" name="code"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;// Smarty initialization&lt;br /&gt;require_once('Smarty.class.php');&lt;br /&gt;$smarty = new Smarty();&lt;br /&gt;&lt;br /&gt;$myFriends = array(“Mike”, “Paul”, “Peter”, “John”);&lt;br /&gt;$smarty-&gt;assign(“myFriends”, $myFriends);&lt;br /&gt;$smarty-&gt;display(‘index.html’);&lt;br /&gt;&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="FONT-WEIGHT: bold"&gt;index.html&lt;/span&gt;&lt;br /&gt;&lt;pre class="html" name="code"&gt;&lt;br /&gt;&amp;lt;html&gt;&lt;br /&gt;&amp;lt;head&gt;&lt;br /&gt;&amp;lt;title&gt;My Friends&amp;lt;/title&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt; My friends are:&lt;br /&gt;&amp;lt;ul&gt;&lt;br /&gt;{foreach from=$myFriends item=friend}&lt;br /&gt;&amp;lt;li&gt;{$friend}&amp;lt;/li&gt;&lt;br /&gt;{/foreach}&lt;br /&gt;&amp;lt;/ul&gt;&lt;br /&gt;&amp;lt;/body&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;I hope this brief tutorial was useful for you. If you have any questions, please leave a comment and I’ll try to reply as soon as possible.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3300153981717062813-8771032082985052697?l=strugglingdevelopers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/8771032082985052697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3300153981717062813&amp;postID=8771032082985052697' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/8771032082985052697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/8771032082985052697'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/2008/08/combining-php-and-html-pages.html' title='Combining PHP and HTML pages'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3300153981717062813.post-8686700366847585454</id><published>2008-08-25T18:02:00.000-07:00</published><updated>2008-09-25T15:24:25.757-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='SEO'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><title type='text'>SEO Friendly URLs</title><content type='html'>Let’s say you have a site which has movie reviews. To display a unique review, you would have a PHP page, for example review.php, which obtains the id of the review and shows the title and description of that review. So, if you want to see the review with id 45, you need to access the following URL:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;http://yoursite.com/review.php?id=45&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Do you see a problem with this? No? Are you sure?  Ok, then I’ll have to explain it. With that type of URL, you are not able to know anything about the review. It could be a review for “Casablanca” just as easily as it could a review for “Ace Ventura: Pet Detective”. And that’s not the biggest problem; it is also a bad SEO URL!&lt;br /&gt;&lt;br /&gt;How can you fix this? Use SEO Friendly URLs.&lt;br /&gt;&lt;br /&gt;Requirements: Apache (with mod_rewrite module) installed on your server (most hosting services already have this).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 1&lt;/span&gt;: Insert the following code on you PHP script&lt;br /&gt;&lt;pre name="code" class="php"&gt;&lt;br /&gt;function StrToSearchFriendlyURL($s) {&lt;br /&gt;   if(!$s) return 'page';&lt;br /&gt;&lt;br /&gt;   $s = strtolower(htmlentities($s, ENT_QUOTES, $GLOBALS['CHARSET']));&lt;br /&gt;   $s = preg_replace('/&amp;amp;(.)(?:acute|cedil|circ|ring|tilde|uml|grave|elig|slash);/', '\\1', $s);&lt;br /&gt;   $s = preg_replace('/\W+/', '_', html_entity_decode($s));&lt;br /&gt;   $s = preg_replace('/_{2,}/','_',$s);&lt;br /&gt;   $s = trim($s,'_');&lt;br /&gt;&lt;br /&gt;   if(!$s) $s = 'page';&lt;br /&gt;&lt;br /&gt;   return $s;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Step 2:&lt;/span&gt; Apply the above function to your regular URLs to make them SEO Friendy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 3&lt;/span&gt;: When inserting the new URLs on your page, add a dash (-), the review id and html extension at the end.&lt;br /&gt;&lt;br /&gt;Example: &lt;br /&gt;&lt;pre name="code" class="html"&gt;&lt;br /&gt;&amp;lt;a href="{SEO_friendly_URL}-{id}.html"&gt;{$review_title}&amp;lt;/a&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 4&lt;/span&gt;: Create a .htaccess file with the following content.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code"&gt;&lt;br /&gt;Options +FollowSymLinks&lt;br /&gt;&lt;br /&gt;RewriteEngine On&lt;br /&gt;RewriteRule ^[^-]+-([0-9]+)\.html$ review.php?id=$1 [L]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 5&lt;/span&gt;: Place the .htaccess file on your site’s document root.&lt;br /&gt;&lt;br /&gt;That’s it! The URLs on your site will now look something like this: &lt;span style="font-style: italic;"&gt;http://yoursite.com/casablanca-45.html&lt;/span&gt; which will be interpreted by Apache like &lt;span style="font-style: italic;"&gt;http://yoursite.com/review.php?id=45&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;More about mod_rewrite: &lt;a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html"&gt;http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html&lt;/a&gt;&lt;br /&gt;More about .htaccess files: &lt;a href="http://httpd.apache.org/docs/1.3/howto/htaccess.html"&gt;http://httpd.apache.org/docs/1.3/howto/htaccess.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3300153981717062813-8686700366847585454?l=strugglingdevelopers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/8686700366847585454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3300153981717062813&amp;postID=8686700366847585454' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/8686700366847585454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/8686700366847585454'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/2008/08/seo-friendly-urls.html' title='SEO Friendly URLs'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3300153981717062813.post-1737120302021737775</id><published>2008-08-22T20:10:00.000-07:00</published><updated>2008-09-25T15:19:41.234-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='CSV'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><title type='text'>Obtaining a visitor’s country from its IP address</title><content type='html'>Sometimes, when you are building a site, you may want the content of the homepage or even the language to be used, to change depending on the country from which the visitor is accessing.&lt;br /&gt;&lt;br /&gt;How can you do this? It’s actually pretty simple, just follow these steps:&lt;br /&gt;&lt;br /&gt;1. Get an IP-Country database. Each row of these databases often has three columns: start and end range for the IP address and the country to which that range is associated (e.g. &lt;a href="http://www.ip2location.com/"&gt;http://www.ip2location.com&lt;/a&gt;). Most of these databases are not free, and the ones that are, are generally a little outdated. I recommend purchasing a database, mainly because you can download a new updated version every month.&lt;br /&gt;&lt;br /&gt;2. Import the IP-Country database into the database on your site. The IP-Country databases are generally in the .csv format (comma separted values), so you have to execute a query to import all the values. That query should look something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="sql"&gt;&lt;br /&gt;LOAD DATA LOCAL INFILE '/ip-country.csv'&lt;br /&gt;INTO TABLE ip_country&lt;br /&gt;FIELDS TERMINATED BY ','&lt;br /&gt;LINES TERMINATED BY '\n'&lt;br /&gt;(start_range, end_range, country);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;3. Include the following PHP code on the page that you want to use to obtain the Country:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="php"&gt;$IPaddr = "";&lt;br /&gt;if (getenv("HTTP_X_FORWARDED_FOR")) {&lt;br /&gt;  $IPaddr = getenv("HTTP_X_FORWARDED_FOR");&lt;br /&gt;} else {&lt;br /&gt;  $IPaddr = getenv("REMOTE_ADDR");&lt;br /&gt;}&lt;br /&gt;$ips = split ("\.", "$IPaddr");&lt;br /&gt;$ip_address = ($ips[3] + $ips[2] * 256 + $ips[1] * 256 * 256 + $ips[0] * 256 * 256 * 256);&lt;br /&gt;$sql = "SELECT country FROM ".TBL_IP_TO_CITY." WHERE ".$ip." BETWEEN IP_FROM AND IP_TO";&lt;br /&gt;$res = $db-&gt;query($sql);&lt;br /&gt;$row = mysql_fetch_row($res)&lt;br /&gt;$country = $row[‘country’];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That’s it! You can now obtain the name of the country from which you visitor is accessing from and display the appropriate content.&lt;br /&gt;&lt;br /&gt;P.S: If you think Ip2Location.com is paying me for each database bought from this Blog, you are wrong!&lt;br /&gt;&lt;br /&gt;P.S2: If you are working at Ip2Location.com, please consider paying me for all the referrals!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3300153981717062813-1737120302021737775?l=strugglingdevelopers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/1737120302021737775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3300153981717062813&amp;postID=1737120302021737775' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/1737120302021737775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/1737120302021737775'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/2008/08/obtaining-visitors-country-from-its-ip.html' title='Obtaining a visitor’s country from its IP address'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3300153981717062813.post-517913610704982420</id><published>2008-08-19T18:20:00.000-07:00</published><updated>2008-08-26T20:20:53.696-07:00</updated><title type='text'>About this Blog</title><content type='html'>Welcome to the Struggling Developers Blog!&lt;br /&gt;&lt;br /&gt;My name is Pablo, I have a small software development company together with two partners, and we have been struggling for about a year to keep our company alive. The three of us used to work as employees on different software companies until we decided to open our own. Since then, we had to deal with different types of projects, technologies and clients.&lt;br /&gt;&lt;br /&gt;In this Blog I will tell you about the obstacles that we had to face as a company, with both programming and clients, so that maybe you can learn from our experiences (and the lessons we got from them) and use them on your professional life.&lt;br /&gt;&lt;br /&gt;I know I might not have the best solution for every problem, so if you have something to add or a different approach for any of my posts, please leave a comment. I promise I’ll read all of them and (if needed) update my posts with your feedback.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3300153981717062813-517913610704982420?l=strugglingdevelopers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strugglingdevelopers.blogspot.com/feeds/517913610704982420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3300153981717062813&amp;postID=517913610704982420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/517913610704982420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3300153981717062813/posts/default/517913610704982420'/><link rel='alternate' type='text/html' href='http://strugglingdevelopers.blogspot.com/2008/08/about-this-blog.html' title='About this Blog'/><author><name>Pablo</name><uri>http://www.blogger.com/profile/01339836843089772250</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_a4BwX_hYRPM/SNwV4_DZEDI/AAAAAAAAAAM/Y96xM03w8Ao/S220/LogoDyn.JPG'/></author><thr:total>0</thr:total></entry></feed>
