Hints to help optimise the performance of a PHP website (LAMP)

Over time, the websites I have been involved in have became more and more complex (and indeed carry more and more traffic).

And so the ever increasing need to optimise and increase the performance of your website (or web-application) becomes more crucial.

As you will appreciate this is a HUGE subject, so I aim to simply put you on the path to devising a better architecture and design. But I will attempt to introduce some ideas to assist…

Continue reading

Why does php not show errors? – How to display PHP errors when display_errors is disabled

OK, a simple thing I know. But one that always occurs.

When using shared hosting (or even your own dedicated servers), those managing those servers do their utmost to make them secure. Among many things this usually includes turning off ‘display_errors’ in the php.ini file.

However, when you’re trying to develop things it is usefull to display errors and warnings, but if ‘display_errors’ is off, you will be scratching your head wondering what’s going on and whats going wrong!
Continue reading

Beginning your journey in Object-Oriented Programming using PHP

Object-Orientated programming is not a new idea! It’s been around and available for a long time in many languages.

With each new version of PHP, new features appear, while existing features are improved. PHP’s object support has been hugley improved since it’s introduction in PHP3 (yes it has had it all this time!). And so with PHP’s object support maturing, the reasons developers might not take an object orientated approach are getting smaller. More recently PHP5′s take on objects is much more powerfull and usable than it ever has been for PHP users – but still not without it’s faults.

A common problem that experienced (and new) PHP developers have when embarking on their object-orientated (OOP) journey is thet they don’t know WHEN to use it properly! As with all things there is a time and place for everything.

For those who do not know about OOP I am not even going to attempt to explain what it is! But fact you have found this article means you probably do, but incase not Wikipedia has good general background info on OOP.

Continue reading

Session Handling in PHP

Traditionally HTTP is a stateless protocol. That is it is made up of requests and responses and there is no notion of a ‘persistent connection’. This means that there is no way to have consistency or personalisation on the web since there is no way of knowing whom the request came from.

There are 2 primary methods – regardless of platform – that are used as a work-around for this.

First is a cookie. A cookie is a text file that lives on the client’s computer that store values set by your application. In general the file can only be access by the website/domain that issued it. The main problem with cookies is that they are un-trusted. A malicious user could modify the data and cause you problems!

The second – and better – solution is sessions. Similar to cookies, but they reside on the server, and cannot be directly modified by the client. When sessions are used, a cookie is still issued, but this simply holds the ‘session id’. This session id is generally sent by any request after it is created by the app including actions such as form submission. This ‘session id’ is a link to either a file or record on the server – depending how they are stored.

Continue reading

Need to make PHP ‘stop’… PHP wait timer

AJAX is great… but sometimes it’s too quick if you’re updating… So… How can I make the page wait for a few seconds, then proceed?

Well there are 2 functions PHP has to pause execution. They are:

sleep(NUMBER_OF_SECONDS);

and:

usleep(NUMBER_OF_MS);

One thing you may want to keep in mind is that if you are using a for loop and wish to do this, then you might want to increase the timeout:

set_time_limit(NUMBER_OF_SECONDS);

PHP – Generate/Create strong passwords, uuid, random string

Very often the need to create passwords or some other ‘unique’ string be it a captcha or for use as unique identifier (UUID).

Here are a few functions I’ve used and refined over the years, 2 types, for password/random string generation and UUID generation.

Generating random strings is pretty simple as it’ll be a password.

However for a UUID there is always the slim chance it’s not unique.
Continue reading

Signs of poor PHP ‘products’

If you are a professional developer (or aspiring) you will inevitably get asked to customise or even better “extend” existing wares.

If it’s a product you are familiar with great! If not I heartilly reccomend spending a little time investigating prior to accepting a job ( ultimatley if they are happy to give

access to their code, if not atleast tell you what’s been used so you cam repliocate it to play with briefly). I know this sounds like a lot of work wich ultimatley – if you

don’t accept the job – you have done for free, but it will save you masses of grief, tears and late nights if you do.

So, I have a few pointers to ‘be aware of’ while evaluating the job and to (generally) identify crappy PHP products/solutions quickly…

Continue reading

Creating good passwords…

Recently I was reviewing the security practices for my users…

I like to get them to change their windows login regularly as it’s used via LDAP etc etc in some cases for loggin into web applications…

Anyway… all the passwords I keep getting from them are very poor, and so I put some guide-lines together for them and thought it’d be fun to share.

I suggest – actually force them – to include characters from all 5 of these rows in passwords…

0123456789
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
@#$%^&*()-_+=
~`[]{}|\:;’<>,.?/

Doing this will increase the time it takes to get cracked… Now… if you want a really really great password do the above and include an alt-character or two! Here is a table of them:

ALT-Characters

Dynamically sorting by a column in a Stored Procedure (SQL Server)

Have you ever needed to build a stored procedure that would take the name of a column as a parameter, and return the results ordered by that column?

So have I, so after researching it for a couple of days, and none of the forums had any good solutions; All that he was able to find was a reference from Microsoft that said that the only way to do it was to build your SQL statement dynamically as a string in the stored procedure and EXEC it (not very good, considering it wouldn’t be able to leverage the T-SQL code optimiser – you’d be as well building it in your given language). I spent some time working on this and came up with a much better solution. There is a way to accomplish dynamic column sorting, while still leveraging a fully compiled and optimised stored procedure.

Microsoft says that you can’t use a variable for the column in an ORDER BY statement, and most attempts gave us a “can’t convert this value to an int” error. There is a way to make it work, though.

Consider a table:

ID int,
FirstName nvarchar(20),
LastName nvarchar(20),
ApplyDate datetime

We want to call a stored procedure, passing the name of the column that we want the records to be sorted by:

GetApplications(@SortField nvarchar(20))

Here’s what the T-SQL stored procedure definition looks like:

create proc GetApplications
@SortField nvarchar(20)
as
select * from Applications
order by
case @SortField
when 'FirstName' then cast (FirstName as sql_variant)
when 'LastName' then cast (LastName as sql_variant)
when 'ApplyDate' then cast (ApplyDate as sql_variant)
else cast (ID as sql_variant)
end

That’s it! Be sure to put the ELSE clause in there as a catch-all, so that you handle columns that don’t exist or typos in the value passed into the stored procedure.

You also need to cast all the values to sql_variant so that the ORDER BY clause won’t get confused about the type of the column that we’re sorting by, and try to force our values into an int.

This is tried and tested SQL Server 2000, and it works just fine. No promises for expermmenting with older/newer versions!

I’m always looking to improve my own SQL (SQL Server, MySQL are my main databases but always keen to learn new things too!) knowledge… so contact me if you have other hints or tips!

ColdFusion Caching Explained

Configured in the ColdFusion administrator under the “Caching” section, server caching controls how much and when data is stored in memory. An effective server caching strategy can relieve stress on resources such as databases, CPUs, and file systems while dramatically improving application performance. This article explores server caching in ColdFusion, introducing its different pieces and providing examples of how server caching works and its benefits.

Template Cache

All ColdFusion templates are compiled into PCode before execution. This compilation process can be resource intensive and slow down an application. To avoid compiling a template on every request, ColdFusion caches its PCode into memory the first time that it is called. If the cache becomes full, the cache is forced to purge templates on a first in first out basis to accommodate new requests. As a result, the next time the purged template is called, it must be recompiled. This purging is referred to as a cache pop and can be seen when monitoring CFSTAT.

If ever CP/Sec is greater than 0, Allaire recommends that the “Template Cache Size” setting be increased. By default “Template Cache Size” is set to 1024 kilobytes, but a good rule of thumb is to set the template cache size two to five times the total template size. Note that this setting is a maximum limit and is not allocated until necessary. Each template is cached only once, even if it is included in several other templates.

Trusted Cache

Though a template’s PCode may be stored in the template cache, ColdFusion checks the actual file to see if it has been modified after it was cached. This check may increase I/O wait and can be avoided by turning on trusted cache, also in the ColdFusion administrator.

With trusted cache enabled, ColdFusion will only access the template cache—even if the template itself is modified. This can be problematic if developers expect to see changes when files are modified. To introduce modified templates into the cache with out restarting the ColdFusion server, disable trusted cache and make a request to each modified template. Trusted cache can then be turned back on.

Database Connection Caching

To avoid the highly expensive task of opening and closing a connection to the database for every request, ColdFusion caches database connections by default. This means that the connection to the database is only opened once for many requests, thereby dramatically improving performance.

If you are connecting to a clustered database configuration, it may be necessary to disable connection caching to allow failover to function properly. This can be accomplished by unchecking “Maintain Database Connections” in the attributes of the data source but will strongly degrade performance.

To avoid unused connections to the database remaining open for long periods of time, the “Limit cached database connection inactive time” setting can be adjusted. It is also possible to manually release all data source connections from the “Verify Data Source” section of the ColdFusion administrator.

Query Caching

Query caching greatly increases performance as result sets are retrieved from memory rather than from the database. Developers should consider caching queries whenever possible.

For example, the following query will be cached for two hours:

<CFQUERY Name="MyQuery" DataSource="dsn"
CachedWithin="#CreateTimeSpan(0,2,0,0)#">
Select * from Inventory where InventoryId =2
</CFQUERY>

While caching queries is controlled by code, the limit of allowable cached queries is set in the ColdFusion administrator. With the introduction of CF 4.5x, it became possible to cache more that 100 queries at a time. The amount of queries that can be cached is now limited only by the amount of memory available on the server. As the size of result sets, amount of available memory, and the use of cached queries in applications vary, this setting should be tested under expected load for optimal performance.

Improving scalability is about finding and removing bottlenecks that restrict the growth of a system. The most common bottlenecks for Web systems include:

  • Insufficient network bandwidth.
  • Insufficient CPU resources.
  • Inability to get data to/from the database.
  • Solving each problem seems simple:
    • Call the ISP.
    • Add servers.
    • Add more database server(s).
    • Decrease the time between a page request and the page view.
    • Reduce the amount of work generated for the database server for each page view.
    • There is a limit to the number of queries you can cache. This number is configured in the ColdFusion Administrator under”Caching.” In ColdFusion 4.01, you cannot set this number higher than 100. This limitation was removed in ColdFusion 4.5, but that is not an invitation to set the value to 30,000. Caching too many result sets will cause memory starvation and heavy virtual memory paging, negating the benefits.
    • If you have a dynamic query, such as “SELECT * FROM Catalog WHERE CatalogNumber = #val(FORM.CatalogNumber)#”, each permutation of that query counts as one cached query. Therefore, query caching should only be used for commonly accessed result sets. The CFML Language Reference defines a distinct result set by stating “…the current query must use the same SQL statement, data source, query name, user name, password, and DBTYPE. Additionally, for native drivers it must have the same DBSERVER and DBNAME (Sybase only).”
    • There is no easy way to invalidate a result set, if you detect that a result set should be invalidated. Therefore, the time span used for the result set cache should be chosen carefully. However, if you have a result set that is accessed four times per second, setting a timeout as low as a minute reduces the load on the database (for that query) by a factor of 240.
    • You cannot use query caching for parameterized queries (queries using <CFQUERYPARAM>.) Parameterized queries should be used for common non-cached queries, since they allow the query plan to be reused on some database systems (such as Oracle), and they are virtually immune to malicious query editing as documented in Allaire Security Bulletin ASB99-04 (http://www.allaire.com/handlers/index.cfm?ID=8728&Method=Full)
  • Unfortunately, the cost of adding database server(s), both in terms of money and administrative overhead, is very high. So, it seems that maximizing your existing investment in database hardware and software is warranted. Enter query caching.

    Query caching is designed to accomplish two goals:

    Implementing query caching is very simple. For example, examine the query below, which might be used to retrieve a list of states for a <SELECT> list.

    Before:
    <CFQUERY Name="qStates" DataSource="#Request.DSN#">
    SELECT StateCode
    FROM States
    ORDER BY StateCode
    </CFQUERY>

    After:
    <CFQUERY Name="qStates" DataSource="#Request.DSN#"
    CachedWithin="#CreateTimeSpan(0,1,0,0)#">
    SELECT StateCode
    FROM States
    ORDER BY StateCode
    </CFQUERY>

    You just empowered ColdFusion to hold on to the results of that query for up to an hour. ColdFusion will now stop repeatedly asking the database for the results of this query. In fact, ColdFusion will reuse the results of that query for up to an hour before asking the database for that result set again. The database is now relieved of the duty of fetching these rows and sorting them (which usually involves creating and dropping a temporary table) for each request to that page.

    Before you get too excited, there are a few details to consider:

    Keep in mind that queries are also global to the server, so if you use the same query with the same name in multiple pages, that cached result set is shared between the pages.

    The repetitive nature of Web pages often causes database servers to work very hard at producing the same results sets over and over again. However, by using the Query Caching capability included with ColdFusion, a significant amount of work can easily be moved from the database server to the ColdFusion servers. This allows for a much higher ratio of ColdFusion servers to database servers, enhances the performance and scalability of your Web system, and maximizes your investment in your database servers.

    When designing a server caching strategy, it is important to take into account available sever memory and the need for fully dynamic information. If poor application performance is an issue, these settings may make a world of difference. During implementation, testing should take place to ensure that the application and server reacts as expected. Be sure to monitor server memory and verify that application data is correct.

    Note: this article was created as a result of some research and training courses I have been on and recommendations from them. This article is likely to evolve :)