Simon Holywell

Posts tagged php

Freelancers: Costing your work

Recently I have been a fly-on-the-wall in an interesting discussion on the Auckland PHP User Group regarding the process of costing freelance work. So I thought I would toss my hat in the ring and give my opinion and summarise the interesting aspects.

Let me just say now that I cannot tell you how much you should be charging or what you are worth, but I can help you avoid some pitfalls.

The lowest price submitted for a job will not necessarily get the job. Consider this example – say I would like to buy a washing machine. I would not opt to buy the cheapest one for any number of the following reasons:

Problem Translation
It only has three different wash cycles Your skill set is limited
Its load capacity is small You cannot handle a large project
It only comes in white You won’t compromise or go out of your way to help
Its energy rating is rubbish You are going to be slow to complete

So there a few reasons off the top of my head that mean you do not want to be pricing yourself below the mark. Whilst those assumptions about you maybe way off the mark and you are the best coder under the sun and the moon you will never get the chance to prove it. You will be discounted as an inexperienced hack and your proposal will be pushed to the side if you are lucky and into the bin if you are not.

The next problem you can easily get yourself into is non-paying clients. There is no silver bullet for this problem because quite often they will look like a legitimate business. One way to avoid getting shafted is to request credit references from the client. This way you can easily find out how they have dealt with other companies in the past, but it can be very insulting to your client so be careful. Always meet the client on their premises before beginning work on the project. Not only will you have a better idea of their business and what they need, but you will make personal contact. People are a lot less likely to stiff you if they feel you are a friend so do your best to talk about their favourite sports team or the latest car they bought or whatever it is that makes them tick.

Furthermore you should maintain regular friendly contact with your clients during and after the completion of the project. This allows you to keep abreast of the clients expectations and let them know of any problems or blocks you may have encountered that could affect the go live date. Through this regular contact you can further ingrain yourself as a reliable and honest friend. Plus they will be sure to call you when they have their next budget round or project!

So what should you do if you really do not trust the client? Well my advice would be to walk away and look for better clients, but if you really must complete as you are on tight constraints then I would try something like the following arrangement. Charge the client the full price of the project up front and do not begin work until they have paid. To help them trust that your intentions are to complete the project; place a large completion bonus at the end of the contract. Then should they not pay you at the end at least you have been paid your hourly rate and it is just your bonus that you miss out on. But as I stated already I would not get involved in this scenario.

Of course you can also find yourself pitching well above the average, which will illicit one of two very strong responses. The first being outright refusal and the second can get you hired instantly. Once again it goes back to the client’s concept of quality. The most expensive TV has the most features so therefore the most expensive developer must also be the best. The point to take away from this is that pricing yourself too high is less likely to lose you the job than pricing yourself too low.

Pricing yourself too low also brings with it other issues further down the line. You attract clients who cannot pay you what you are worth and end up supporting old projects for much lower rates. Clients will quite often balk at a sudden price hike and phone you up to remind you how much of a good friend you are why they deserve a discount. It is the usual human reaction that I am sure you have experienced yourself – your telephone company sends you a letter informing you that calls are to go up by 20% and you will feel a little cheated. Your clients will feel the same way. Yet if you were to charge them the higher price in the beginning then they would likely still have taken you on for the project anyway.

The human psyche can be a strange beast and you will surely run across clients who are exceptions to the norm. Over time you will become adept at reading potential clients, but these notes will hopefully help you avoid the worst of it. It is tough out there being a freelancer so good luck!

Common PHP Mistakes

PHP (elePHPant)

PHP (elePHPant)

A few common PHP mistakes:

  • Using require_once when a simple require would achieve the same result. Using require uses less system resources and therefore executes more quickly. You should engineer your code so you don’t need to use require_once. The same of course applies to include statements.
  • Failing to declare variables before attempting to use them.
  • Don’t use absolute paths and URLs where relative will suffice
  • Not opening code for peer review. Often others will have ingenuous just like you about how to optimise your code. Make use of the resources you have.
  • Using double quotes where an apostrophe will fit better. Only use “ where the string you are constructing contains ‘ or variables you wish to substituted. This saves the PHP parser from expanding text it doesn’t need to.
  • It is recommended that you place the value you wish to match before the variable you hope to find it in. Eg. if (‘test’ == $var) { } This prevents the value being assigned to the variable should you forget an =

SQL Server 2005 Dump to SQL statements

Say you have a development environment setup using SQL Server 2005 Express Edition and your customer has a SQL Server 2000 database accessible only via ODBC and you can only run a DB import via a script. How would you do it? Easy you might think just run msdbdump.exe on the command line, well this isn’t MySQL so you are not so fortunate.

Backing up your DB is easy with SQL Server using the following commands:

http://gist.github.com/294721

But this just gives you a binary file that can be restored if you have access privileges to the live database for restoring. If you are in a shared hosting environment or one where the paranoid admins won’t give you remote desktop access and the only access you have is to run a PHP script to import the data and schema via SQL you will need to export the DB to T-SQL format.

Microsoft have a little program to perform this very function: Microsoft SQL Server Database Publishing Wizard 1.1 It is difficult to find on the web so I aim to save you the time I spent hunting for it. When you run the wizard make sure to set:

  • Drop existing objects in script to false
  • Schema qualify to false
  • Script for target database to SQL Server 2000

It does seem to chew on the cud for quite some time so grab a beverage.

Now for the PHP portion of the process. So you have uploaded your lovely T-SQL dump file to a PHP accessible location on your webserver and now you are wondering how to get into your DB via ODBC. Well you will need a PHP script like the one I have supplied below.

A couple of the complexities to be aware of before you continue. It seems that the T-SQL dump file comes out as UTF16 and we need it in UTF8 so you will need to convert it to UTF8 before you can import. I used a neat little function available from Modular.org for this purpose. This may or may not meet your needs. If you need a more accurate conversion method then I recommend you start your search with the PHP module/function mbstring . T-SQL contains reference and keywords that ODBC/MS SQL cannot understand. I have included some regex to strip these out.

My script is by no means perfect or factored down so feel free to make suggestions or improvements.

http://gist.github.com/294720

Geographic Calculations in PHP

Recently I have been involved with a project that maps yachts during an ocean race, which got me thinking about basic calculations and conversions that would be useful to fellow developers. I envisage this being useful in projects leveraging Google or Yahoo maps. For the moment the class performs the following functions:

  • Calculate the distance between two coordinate points on the earth’s surface (using Vincenty, Haversine, Great Circle or The Cosine Law)
  • Conversion between units (metres to kilometres, nautical miles and miles).
  • Convert coordinate notation (decimals to degrees, minutes & seconds and back again).

That is all you get for the moment, but it is pretty powerful for getting a “as the crow flies” distance between two coordinates. Vincenty’s formula is the most accurate method for calculation, but it is also the most processor intensive.

The attached file package contains an extensive set of “api” documentation and PHPDoc comments throughout the class to make customisation and use easier. I have also included a demo php file in there so you can see how it is intended to be used. It should also be pointed out here that this class requires some of the new OO features only available in PHP5, but it could easily be edited to be backwards compatible with PHP4.

Geographic Calculations in PHP (ZIP file)

Form SPAM (not “HAM”) fighting tips

A site that I have up called Alfa Romeo Sprint QV has recently been the target of malicious spammers and/or their robots. The messages mainly consisted of porn and poker sites.

Now the script used to generate the Your Sprints section of the site was written a long time ago when spamming forms and blogs was not a common occurrence and my site had a relative small readership and no Google rank or anything like that. So I thought I would be safe to allow these cars to be posted un-moderated to the site. I knew I could trust the Alfa owners out there to do the right thing and I did not expect anybody else to visit the site. But as we all know obscurity is no defence against spammers or script kiddies.

So the other night I spent quite a large amount of time trying to secure the forms in the site. First of all, it is now a moderated affair without anything going live until I have approved it. Although robots don’t understand this and will submit the form anyway creating a lot of spam to sort through so this is only beginning of the measures I took.

I then made it so the form had rolling names on all the input fields. Whilst it is not good for accessibility (sorry) it does make it a lot harder for a script to get hold of the from via commonly used names like email_address or name. For accessibility purposes I strongly suggest you make use of the label element of html. If you are interested in creating good forms then I highly recommend this series of articles: Accessible HTML/XHTML Forms by Ian Lloyd of the Web Standards Group.

Every time the page loads new names are generated for the inputs so you cannot take a source snapshot and use that to submit the form either. I store the field names in a session array which is deleted upon submission, but allows me to extract the data from the post array. So if you try posting something with different names the script will not access it and of course if no session is set then you will be sent back to form, which obviously regenerates the field names at the same time.

Now that may sound complex but it really boils down to this:

  1. Generate field name: $_SESSION['form']['field1'] = rand(0, 9999999);
    you will need to make sure that you have some way of ensuring that the input names are unique
  2. Label for accessibility: <label for=?<?=$_SESSION['form']['field1']?>?>Field 1</label>
  3. Apply to form: <input name="<?=$_SESSION['form']['field1']?>" type="text" size="20" />
  4. After submission grab the data: $data1 = $_POST[$_SESSION['form']['field1']];
  5. Sanitise the data (strip_tags etc.)
  6. unset($_SESSION['form']);

Now to help slow down people who are posting rubbish and separate them from those genuinely trying to post I added a simple mathematical problem that must be completed. The script randomly chooses two numbers between 0 and 10 which the user must correctly add together for the form data to be inserted into the database.

I should also add a note here; although I have used disabled textboxes to hold the numbers that must be added together, when the form is submitted I only use the values stored in the session to determine if they were correct. This way it stops someone from creating their own form and supplying their own numbers. If you took the values from the form then it would be very easy to circumvent the protection.

Anyway these are just some ideas I have had to help deal with the problem of form spam. Obviously you cannot use some of the protections in some forms and you have to weigh up the pros and cons of the additions. But for my little personal site becoming inundated with spam these little changes have made a big difference. So I hope you find some of the ideas useful.

Flickering Images

I have been asked numerous times in the past how I create this effect in some forum signatures so now I am releasing the code so you can see. It could equally be used as a background image in CSS (like the photo of the excavator above) so you could have a circulating series of background or in this case header images. I am sure you can think of many other neat uses for this script.

Flickering Images Demo
refresh the page to see the above image change

Demo rar’d archive (includes demo ‘Disgraceful Alfa’ gallery images) can be found at the end of the article.

  1. Extract into a new directory
  2. Open image.jpg in your favourite editor
  3. Change the BASE_DIR to reflect the absolute path to the directory containing the image.php file eg. /home/simon/flickering/
  4. chmod the storage.dat file to 777
  5. Then open the url in your browser….enjoy!

This is the PHP script (image.jpg is the file name):

http://gist.github.com/294723

You also need to add a line to .htaccess:
ForceType application/x-httpd-php

Due to the change in the .htaccess file Apache now treats .jpg files as PHP in this directory. This then allows us to execute some php code which ultimately outputs a JPEG header and JPEG data, which shows up as an image when its linked to. The browser is none the wiser as it does not look like remote script invocation like some previous methods that have been released. So this can be used anywhere an image can without anyone knowing until they see it changing!

Flickering Images (RAR file)

ADODB

During a recent project I ended up using ADODB and found it very effective. Especially the wrapper it places around PHPs sessions, it stores them in the DB instead of in the temp directory, which can be less secure. It also handles encryption of the session variables contents, but only using MD5 originally and I prefer to use SHA1. So I hacked the following to allow me to do so and I contributed it to ADODB.

adodb-encrypt-sha1.php (new file):

http://gist.github.com/294724

Add to crypt.inc.php:

http://gist.github.com/294725

This code has now been added to the stable release of ADODB.