Thursday, September 22, 2011

Install LAMP on a Mac

There are two ways to Install LAMP (Linux Apache MySQL PHP) on a Mac, Macbook, or IMac.


  1. XAMPP is the quickest and easiest to setup a standard install of Apache, Mysql, and PHP. It also includes phpMyAdmin and a number of common modules already installed. You can download it here.
  2. The second option for installing LAMP is to use MacPorts. This takes much longer, but it will allow you to get the latest versions, keep them up to date and install custom modules into apache. Here is how to install it.


Install Guide for MacPorts.

Install XCode

  • Download and Install XCode for your Mac.  This is pretty simple and self explanatory, however it is over 3 gigs. Sit back, get a cup of Starbucks, and enjoy your favorite tech manual while you wait.



  • Next Grab the MacPorts Source for which ever flavor of the Mac Operating System you are using. Lion, Snow Leopard, and Leopard are all three available here



  • Now simply update your macports by running this command in the Terminal:

    sudo port -v selfupdate


Install MySQL and MySQL Server


1) Install mysql server 
sudo port install mysql5-server-devel
2) Make mysql run at startup
sudo port load mysql5-server-devel
3) Setting up mysql
sudo -u _mysql mysql_install_db5
4) Start mysql for the first time
cd /opt/local ; sudo /opt/local/lib/mysql5/bin/mysqld_safe &
5) Change the root password for mysql
/opt/local/lib/mysql5/bin/mysqladmin -u root password 'MYPASSWORD'
6) Add commands to profile
echo "" >> ~/.profile
echo "# MacPorts MySQL alias" >> ~/.profile
echo "alias mysqlstart='sudo mysqld_safe5 &'" >> ~/.profile
echo "alias mysqlstop='mysqladmin5 -u root -pr0xv83s shutdown'" >> ~/.profile
echo "" >> ~/.profile
sh ~/.profile

Install PHP and Apache


1) Install php and apache (all on 1 line)
sudo port install php5 php5-curl php5-gd php5-mbstring php5-mcrypt php5-memcache php5-mysql php5-openssl php5-soap php5-zip
2) Run apache at statup 
sudo port load apache2 
3) Add command to profile
echo "" >> ~/.profile
echo "# MacPorts Apache2 alias" >> ~/.profile 
echo "alias apache2ctl='sudo /opt/local/apache2/bin/apachectl'" >> ~/.profile
echo "" >> ~/.profile
sh ~/.profile
4) Activate php in apache
cd /opt/local/apache2/modules;sudo /opt/local/apache2/bin/apxs -a -e -n "php5" libphp5.so
5) Create phpinfo
sudo sh -c 'echo "" >> /opt/local/apache2/htdocs/phpinfo.php'

Setup memcached
1) run memcached at startup
sudo port load memcached
Install GIT
1) install git
sudo port install git-core

And there you have it.  Your home apache directory is now at:

/opt/local/apache2/htdocs

You will also have a number of commands ready to start/stop/restart apache and mysql. *be sure to log out of the terminal and log back in so they work*

apache2ctl stop

apache2ctl start

apache2ctl restart


mysqlstart

mysqlstop

I hope you enjoy your new setup.  You can now read up on macports and learn how to keep all of your code current.

Wednesday, April 22, 2009

Cake PHP Set Class - overlay function

The CakePHP Set Class is a wonderful collection of functions that allow you to handle and process CakePHP arrays quickly and efficiently. It has features that deal with stripping out data, changing arrays to objects, and custom merge functionality.

Recently however I had a problem that was bothering me, and I thought some sort of set functionality would do the job. (Please tell me if this functionality has already been written).

Here's the problem:

I have a table that I download periodically and I want to update it into my database. The problem is that I have custom ID's for each row of my current table that are indexed throughout the rest of the database. I've found that I need to update existing records, delete any records that are not in my downloaded table, and I need to add new records that don't exist in my current table.

Here's an example:

On a regular basis, you get a list of 5000 products that your online store promotes from your affiliate. Once a week you need to download all of the products and update your products table. A standard drop and re-insert will not work, because you use custom id's in your products table that are referenced in your customers_products table and others. How do you update these 5000 records?

The answer is to think of it in terms of sets...

In the diagram, Set A is my current table that I want to update. Set B is the new table. Everything that is in Set A and not in Set B, I want to delete (Yellow). Everything in Set B not in Set A, I want to insert (Dark Green). And Everything that exists in both I want to update (Light Green).

Breaking the problem into a sets will allow you to realize what you need to do. One way of looking at a possible solution is to find what you need. From the diagram, all you need is everything in green (light or dark). In our product example all you need is a set of new products while maintaining the light green Primary Keys. (the dark green will generate new id's).

Implementation:

function updateProducts() {
$products= $this->Product->query("select distinct(prodid) as `match_id` from import_products as `Product`");
// Make the products array look like cake arrays...
foreach($products as $i => $product) {
foreach($product as $model=>$this_data) {
unset($products[$i][$model]);
$products[$i]['Product'] = $this_data;
}
}
$current_products = $this->Product->find('all',array('recursive'=>-1));
$res = $this->overlay($current_products, $products, "{n}.product.match_id");
$this->Product->query("truncate table products");
$this->Product->saveAll($res);
}

// function overlay:
// This function returns the $to array with merged $from elements.
// $from - array[0..x] of cake based array structure
// $to - array[0..x] of cake based array structure
// Path field for the overlay using set::extract's strucure
// eg. $path = "{n}.TableName.fieldname"
// * the Path must exist in each element in the $to and $from array
function overlay($from, $to, $path) {
$from_ary = Set::extract($from, $path);
$to_ary = Set::extract($to, $path);
if (count($to_ary) != count($to)) return $to;
if (count($from_ary) != count($from)) return $to;
$flipped_from = array_flip($from_ary);
$cnt = 0;
$results = array();
foreach($to as $key => $val) {
if (!empty($flipped_from[$to_ary[$cnt]])) {
$fkey = $flipped_from[$to_ary[$cnt]];
$results[$cnt] = Set::merge($from[$fkey], $to[$cnt]);
} else {
$results[$cnt] = $to[$cnt];
}
$cnt++;
}
return $results;
}

What does all this do?

Put simply, I gather my SET B (the new updated products that I downloaded), and then my SET B (my current set of products). I then call my function overlay(). Overlay simply returns SET B with elements from SET A merged with it based on the Path field. What is nice about this concept is that it allows you to simply pass the results overlay() directly to a cake saveAll() function.

I would not suggest using this code for giant tables. I did it on a zip code table with 42000 records, and the saveAll took a few minutes to rebuild the table. This may not be the most efficient solution, but it's clean and useful for "once-in-a-while" updates on tables.

Thursday, February 19, 2009

How to Add CAPTCHA Security Images to Wildflower Comments

So you love Wildflower CMS for CakePHP, and you've used it to create a number of blogs. However you've noticed something. You are getting comment spammed.

Put simply, Wildflower doesn't have a good solution for preventing comment spam.

Initial Setup

1) Download the latest Wildflower development copy to your system. You can find the latest code for Wildflower on GitHub.

2) Set up your development environment. This includes:
  • Apache virtual host setup to point to your wildflower/app/webroot folder
  • Setup your local database called "wildflower"
  • Modify your hosts file so that it points to the Apache domain
  • Restart Apache.
3) At this point you should have a working copy of Wildflower.

Download Securimage CAPTCHA

You can download Securimage here:

Securimage Download
  • Grab the zip file and unpack it into your app/vendors/ directory.
  • Download the words.zip file and extract to app/vendors/securimage/words/
Building the Dynamic Image

  • Edit app/webroot/.htaccess and add the following line:

RewriteEngine On
RewriteRule ^img/captcha.jpg$ captcha.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-d
...
  • Test the image by going to http://yourvirtualhost/img/captcha.jpg

Create the Form View

Copy
  • ~/wildflower/views/wild_posts/view.ctp
to
  • /app/views/plugins/wildflower/wild_psts/view.ctp
(Create the directories as needed)
  • Now edit /app/views/plugins/wildflower/wild_psts/view.ctp and add the following two lines in the Comments Form.

$form->input('url', array('label' => 'Website URL (optional)')),
$form->input('content', array('label' => 'Message', 'type' => 'textbox')),
$html->image('captcha.jpg', array('alt'=>'Code', 'id'=>'security_image')),
$form->input('security_code', array('label' => 'Enter the word.')),
$form->hidden('post_id', array('value' => $post['WildPost']['id'])),


Process the Form


  • Open up ~/wildflower/models/wild_comment.php
  • Add the following Validation Rule:

public $validate = array(
'name' => VALID_NOT_EMPTY,
'email' => array('rule' => 'email', 'message' => 'Please enter a valid email address'),
'url' => array('rule' => 'url', 'message' => 'Please enter a valid URL', 'allowEmpty' => true),
'security_code' => array('rule'=>'validSecurityCode', 'message'=>'The word you entered was not correct.', 'allowEmpty' => false),
'content' => VALID_NOT_EMPTY
);
  • Add the following Function:
function validSecurityCode() {
if (!empty($this->data[$this->name]['security_code']) && strtolower($this->data[$this->name]['security_code']) != strtolower($_SESSION['securimage_code_value'])) {
unset($this->data[$this->name]['security_code']);
return false;
}
return true;
}

Try to add a comment to a blog post and see what happens.



Thursday, February 12, 2009

Writing Bad Test Cases


So, you spend days and days writing test cases and you find out that they become more of a hassle than you expected. Here are some common mistakes in writing test cases which may help you in your test case development.

1) Your test case creates live data. When you do a quick test case to try to make sure your function works, sometimes you simply set it up to create a new record in your database. This can happen in several ways.
  • You connect to a Live API with your test case. This could actually send credit card transactions, or send live records to your other application, which dilutes live data with fake records. This could lead to bad reporting in the long run.
  • You connect to your live database to test your functions. This is a really bad idea. Make sure your connection string points to a test database or you may end up losing mission-critical data.
2) You change your code to accommodate for test cases. This is a mistake as well. Your code should do what it was intended to do. If you need to add debug lines or incorporate new functionality into your code so that test cases will work, then chances are you either need to go back and study up on test case development or you need to redesign your code so that test cases will not interfere with the system process.

3) You make test cases depend on each other. This is a temptation that should be avoided. When you are running test cases, each function should be independent, even though test cases run linearly. You should not have one test function that presets data, and then assume that that function was called by the test suite.

For instance, let's say I have a test called testLoadUserData and that function loads user information into the variable $this->userdata for testing. Then under than I have a test for testShowUserData. It would be a mistake to assume that $this->userdata still exists in testShowUserData. Why? Because sometimes we comment out tests so the page doesn't take so long to load. This could breat testShowUserData if it depends on other tests. A better solution would be to write a loadVariables function and call it in each test case.

The goal of test cases is to help write modular functions. Often times poorly designed code will cause problems in developing test cases. If you write bad test cases, just consider it a learning experience, and keep at it until it works well.

Good code is poetic in nature.

Monday, February 09, 2009

5 Tips for Cake PHP Development

  1. Don't over-complicate your code.

  2. Work within the constraints of Cake.

  3. Make it work, then go back and make it work better.

  4. Skinny Controllers, fat models.

  5. Test Test Unit Test.

Friday, January 30, 2009

The Ultimate Windows PHP Development Environment

So, you are a PHP developer and you have windows. You've tried all kinds of different editors and setups on your system, but nothing works the way you want it to. Well, your answer is here. I've compiled a list of applications that are essential for PHP development.

Hardware

A Computer - Developers do not need fancy machines to develop. They just need something within the past few years that has enough ram to run modern browsers and a bunch of apps open at the same time. I would suggest a minimum Windows XP. Vista will do as well.

2 Monitors - While a single monitor is nice, having a large area to work is also very helpful. What I suggest is adding a video card that supports two monitors. Then plug the monitors in side by side, and configure them.

The reason I suggest 2 monitors rather than having a wide-screen display is because I would suggest that you virtually stack your monitors so that one screen is virtually "above" another.

Why above one another? Simple. Programmers are lazy! 1) By having your monitors placed above one another you simply need to slide the mouse up to get to the second screen. The advantage of this is that the mouse never needs to leave the mouse pad. 2) Having the monitors setup side-by-side makes closing programs more difficult. If I have my browser maximized on screen 1 and I use the mouse to close it, I move the mouse to the right wall, go up to the x and click it.


Basic Software Tools

Browser(s) - Of course you need a browser or two. Being a PHP programmer doesn't always require that you have awesome xhtml/css design skills, but it's worth at least having several different browsers available to test your system on. There are a number of options available, however a simple set of browsers would be most useful.
  • Firefox - This is a Must! If you don't use firefox the only excuse you have is to be using Google Chrome. Other than that, there is No excuse. Firefox has a few nice extensions that make web programming helpful. Often times we will need to integrate PHP back-end with Ajax, or something. For testing purposes in this situation, it would be helpful to add Firefox Firebug.
  • Google Chrome - As mentioned earlier, Google Chrome is a good alternate to firefox. It is still relitavely new, but has some good potential.
  • Internet Explorer - Ok, yes you need it. Not for browsing, but for testing. It is useless to have a site that looks great on Firefox when 90% of your users are using Internet Explorer. In addition to this it is important that you have multiple versions of IE. I would highly suggest: Multiple IE.
PHP Editors - I'm certain this may be one of the more contriversial sections of this post because everyone seems to have their own preferences for editors. However since I'm posting this, my editor picks are best. :-p You need different editors for different reasons. There are two primary editors I use for different reasons.
  1. Notepad++ - This is by far the best editor I've used in a long time, and it is my favorite. Why you may ask? I judge editors by a number of factors. 1) How little memory they use 2) Easy to use Tabs 3) Highlighting 4) Useful features. Notepadd++ has ranked #1 for all of these factors in my book. Here are a few things I like about it.

    - The Light Explorer plugin makes browsing my directories quick and easy.
    - It comes with the ability to edit files directly on a web server through the ftp_syncronize plugin
    - It opens very fast, takes very little memory, has nice highlighting, and tabs at the top.
    - It opens and closes function tabs letting me see only the code I'm working on at the time.

  2. gvim for Windows - Before coming across Notepad++ I used gvim for windows exclusively. Why? Having a background of using the command line, I learned Vi. When you ssh over to a server and need to edit a file, Vi is by far the best editor (sorry emacs lovers). Well, since I'm always using :wq or %s/.../../g and other vi commands, I found that using VI in a windows environment was great. It allowed me to quickly edit files and use my favorite vi commands.

    Why did I switch? Mainly because of tabs. While I know the basics of VI, I never could setup a good solution for adding and managing tabs. I know there is a VI solution, but I fell to the temptation of opening 10+ Vi windows while working on a project. The transition to Notepad++ was a careful one, but I still keep Vi around.

    Why should you consider keeping Vi around?
    - It again is light weight and fast.
    - It offers nice highlighting.
    - It's VI! So you have the great features of VI.

    What can you use it for?
    - Various projects with CSV Files or Excel files. For instance you can turn an excel sheet into a csv file by copying the data to VI and running the following command:

    %s/\t/,/g

    - Vim is great and fast for formatting data quickly and on the fly.
    - The latest version of VI can open very large files quickly.

    Oh, and don't forget, it's VI!
Other Editors - for those of you who are just getting into PHP or if you need help for function names, or if you want to pay for your editor, I suppose you could use apps like Dreamweaver or SciTE or Eclipse with PHP.

The Applications

PHP, MySQL, Apache - This is commonly known (on windows) as WAMP installation. You will need three basic applications for 90% of your PHP development.
  1. PHP - Of course you will need PHP. This is the application that you actually use to run the code you're developing. I would suggest keeping a browser open and making use of the PHP function search box on the top of the php site. I would not suggest installing php alone on your machine unless you have the time to configure it yourself. (see below for xampp installation)
  2. Apache - Apache is the most popular and most stable webserver out on the market. It is worth learning, because if you go to work for a new company, chances are that their web servers use apache. (again, see below for installation)
  3. MySQL - There are a number of databases out there, but by far, mysql is the best for mid or even high traffic sites. For many years it has been second to Oracle, but recent versions have made it highly competitive to Oracle. And of course, you can't beat the price
So what is the best way to get these apps onto my windows machine? I've tried a number of applications that try to tie php, apache, and mysql into a windows environment where it is seamless and allows you to not have to install individual elements. By far, I have found that Xampp is the best of the best.

Xampp is an easy installation process that installs a fully working and functional WAMP server onto your system. It comes with a handy little control panel to allow you to stop and restart the apache and mysql processes. Not only that, it comes with PHPMyAdmin pre-installed to allow you to quickly get your database up and running. Note: Besides the default install, I would suggest making one additional modification to your xampp install. Open C:\xampp\apache\conf\httpd.conf in your favorite editor (Notepadd++ of course) and uncomment the line that starts with "LoadModule rewrite_module"... around 118 or so. This will turn on Mod Rewrite to allow a number of applications work with/nice/urls.

Frameworks

CakePHP - A while back I spent some time looking into frameworks. Out of all the frameworks I came across, CakePHP stood out above all the rest as a fast, reliable, well-designed framework. After spending a year and a half writing code in CakePHP, I've found that it is one of the most flexible frameworks I've used. Since then I've released over 20 sites using CakePHP that get hundreds of thousands of unique visitors per month. It has bee completely stable and reliable. It also has a growing community of developers who are constantly coming up with different uses, plugins, and add-ons.

Forgive me for not adding other frameworks, but feel free to explore your own.

Useful Utilities

VirtuaWin - This is a Must have. I keep a copy of this program on a zip drive in my wallet and install it on any computer that I'm using. Basically VirtuaWin allows you to have up to 20 desktops on your computer. You setup your shortcut key () to navigate to the desktop you are working. This allows me to work on several projects at the same time along with having one reserved for email and music controls. Once you use this, you'll never go back to a single desktop. Plus if you have dual monitors, you double your desktop capacity up to 40! Yikes!

CoreFTPLite - Of course you need an extra FTP utility. I found that Core FTP Lite does everything I want it to do. Fast loading, fast transfers, SFTP, doesn't crash, easy to use, etc. What else can you say? Filezilla is nice too.

Putty - Never go anywhere without putty. Putty is a small executable terminal window that allows you to ssh anywhere on the web. You don't install it, you just open it. I usually copy it to program files / putty and create shortcuts to it for consistancy.

RealVNC - If you have multiple windows computers and again you are too lazy to get up and log into that computer, VNC is the way to go. Vnc lets you open the desktop of another machine on your computer. It's a fairly simple setup, and works great.

Windows XP Tricks to save time - This is a video that suggests additional cool features to help you save time when programming on windows. I use a few of these techniques as well.

And Finally... The best for last...

Git

Git - I put git in its own category because it's so awesome and it is a must-have for ALL development. Git is a version control repository, but far better and faster than CVS or SVN. Git allows you to store snapshots of the files you are working on and easily recover bad changes. Take a look at one of my previous post about using Git with SVN for help in this area.


The End.


Tuesday, January 27, 2009

Unit Testing Cookies in Cake PHP


One problem I came across when building unit tests was trying to check to see if my cookies were setup properly. (Yes I still use cookies.) The problem with trying to unit test a cookie in Cake PHP is that you are only allowed a single page load for the test. A cookie doesn't exist until it is sent to the browser and the browser sends the cookie back with a new page load.

My first thought was to place a conditional in the test case. This would basically be something like:

if (!empty($_COOKIE['id'])) {
$this->assertTrue($_COOKIE['id'] == 100);

}


This method would require you to have to reload the page to properly test cookies. The first page load will consist of 0 tests. The next page load will consist of 1 test. But this method didn't seem like the best way to go about it.

Then I discovered the PHP function: headers_list().

Headers List will return all the headers that you are about to send to the browser in an array format. This was the solution!

Now I can test what the function is expected to send to the browser (which is independent of the browser actually accepting the cookie or not). Here's a sample of what I did.

function testStoreCookie() {
$this->Controller->storeCookie(100);
$header_list = headers_list();
$cookie_true = false;
foreach($header_list as $item) {

$cookie_true = is_string(stristr($item, "Set-Cookie: id=100")) || $cookie_true;
}

$this->assertTrue($cookie_true);
}


There you have it! You can now test setting cookies without reloading the page.