Sunday, December 20, 2009

PHP coding guidelines

PHP coding guidelines

The guidelines that I follow when writing my PHP scripts; can be helpful to have something like this if you're working on a joint project.


N.B. These are only the guidelines that I personally chose to follow for the code I write. This is not an indication that any other coding styles, guidelines or standards are wrong. Feel free to use this document as a template to manage your own coding guideline and change whatever you wish as you see fit.


Why are guidelines important?


First of all, let's make one point crystal clear: it doesn't matter what your guidelines are, so long as everyone understands and sticks to them. I've worked on a team where the person in charge preferred to put braces following the expression, rather than on a line all by themselves. Whilst I didn't necessarily agree with this convention, I stuck to it because it made maintaining the whole project much easier.


It cannot be emphasised enough that guidelines are only useful if they are followed. It's no use having a definitive set of coding guidelines for a joint programming project if everyone continues to write in their own style regardless. It is arguable that you can get away with different coding styles if every team member works on a different section which is encapsulated and therefore their coding style doesn't affect the other developers. Unfortunately, this only holds true until a developer leaves and someone else has to take over their role.


If you are running a joint project, you might consider putting your foot down and basically refuse to accept any code that does not conform to your published guidelines, regardless of its technical merit (or lack thereof). This may sound somewhat draconian and off-putting to developers at first, but once everyone begins to code to the guidelines you'll find it a lot easier to manage the project and you'll get more work done in the same time. It will require a lot of effort from some of your developers who don't want to abandon their coding habits, but at the end of the day different coding styles will cause more problems than they're worth.


Editor settings



Tabs v. spaces


Ahh, the endless debate of tabs v. spaces. To be honest, I recommend using tabs all the time for the simple reasons that it is much easier to align everything using them, and tabs require less space in a file than multiple spaces. Also, if you set your editor to display a tab character as 8 spaces, but another developer prefers to have them represented as 4 spaces, it doesn't matter in the slightest.


A mention needs to be made of the PEAR project, who insist on using four spaces instead of tabs in their guidelines. If you want to write code for them, just do it in tabs and then do a quick search/replace to change them all to four spaces.


Linefeeds


The three major operating systems (Unix, Windows and Mac OS) use different ways to represent the end of a line. Unix systems use the newline character (\n), Mac systems use a carriage return (\r), and Windows systems are terribly wasteful in that they use a carriage return followed by a line feed (\r\n).



I use simple newlines all the time, because the Windows way just doubles the size of your line breaks and the Mac OS way is technically incorrect in that a carriage return should only return you to the beginning of the line, ala the old typewriter systems.


If you develop on Windows (and many people do), either set up your editor to save files in Unix format or run a utility that converts between the two file formats.


Naming conventions


Variable names


A lot of textbooks (particulary those about Visual C++) will try to drum hungarian notation into your head. Basically, this means having rules such as pre-pending g_ to global variables, i to integer data types etc. Not only is a lot of this irrelevant to PHP (being a typeless language), it also produces variable names such as g_iPersonAge which, to be honest, are not easy to read at a glance and often end up looking like a group of random characters strung together without rhyme or reason.


Variable names should be all lowercase, with words separated by underscores. For example, $current_user is correct, but $currentuser, $currentUser and $CurrentUser are not.



Names should be descriptive, but also concise. Wherever possible, keep variable names to under 15 characters, although be prepared to sacrifice a few extra characters to improve clarity. There's no hard and fast rule when it comes to the length of a variable name, so just try and be as concise as possible without affecting clarity too much. Generally speaking, the smaller the scope of a variable, the more concise you should be, so global variables will usually have the longest names (relative to all others) whereas variables local to a loop might have names consisting only of a single character.


Constants should follow the same conventions as variables, except use all uppercase to distinguish them from variables. So USER_ACTIVE_LEVEL is correct, but USERACTIVELEVEL or user_active_level would be incorrect.


Loop indices


This is the only occassion where short variable names (as small as one character in length) are permitted, and indeed encouraged. Unless you already have a specific counting variable, use $i as the variable for the outermost loop, then go onto $j for the next most outermost loop etc. However, do not use the variable $l (lowercase 'L') in any of your code as it looks too much like the number 'one'.



Example of nested loops using this convention:



<?php
for ( $i = 0; $i < 5; $i++ )
{
    for (
$j = 0; $j < 4; $j++ )
    {
        for (
$k = 0; $k < 3; $k++ )
        {
            for (
$m = 0; $m < 2; $m++ )
            {
                
foo($i, $j, $k, $m);
            }
        }
    }
}
?>



If, for some reason, you end up nesting loops so deeply that you get to $z, consider re-writing your code. I've written programs (in Visual Basic, for my sins) with loops nested four levels deep and they were complicated enough. If you use these guidelines in a joint project, you may way to impose an additional rule that states a maximum nesting of x levels for loops and perhaps for other constructs too.


Function names


Function names should follow the same guidelines as variable names, although they should include a verb somewhere if at all possible. Examples include get_user_data() and validate_form_data(). Basically, make it as obvious as possible what the function does from its name, whilst remaining reasonably concise. For example, a_function_which_gets_user_data_from_a_file() would not be appropriate!



Function arguments


Since function arguments are just variables used in a specific context, they should follow the same guidelines as variable names.


It should be possible to tell the main purpose of a function just by looking at the first line, e.g. get_user_data($username). By examination, you can make a good guess that this function gets the user data of a user with the username passed in the $username argument.


Function arguments should be separated by spaces, both when the function is defined and when it is called. However, there should not be any spaces between the arguments and the opening/closing brackets.


Some examples of correct/incorrect ways to write functions:



<?php
get_user_data
( $username, $password ); // incorrect: spaces next to brackets
get_user_data($username,$password); // incorrect: no spaces between arguments
get_user_data($a, $b); // ambiguous: what do variables $a and $b hold?
get_user_data($username, $password); // correct
?>



Code layout


Including braces


Braces should always be included when writing code using if, for, while etc. blocks. There are no exceptions to this rule, even if the braces could be omitted. Leaving out braces makes code harder to maintain in the future and can also cause bugs that are very difficult to track down.



Some examples of correct/incorrect ways to write code blocks using braces:



<?php
/* These are all incorrect */

if ( condition ) foo();

if (
condition )
    
foo();

while (
condition )
    
foo();

for (
$i = 0; $i < 10; $i++ )
    
foo($i);

/* These are all correct */

if ( condition )
{
    
foo();
}

while (
condition )
{
    
foo();
}

for (
$i = 0; $i < 10; $i++ )
{
    
foo($i);
}
?>



Where to put the braces


Braces should always be placed on a line on their own; again there are no exceptions to this rule. Braces should also align properly (use tabs to achieve this) so a closing brace is always in the same column as the corresponding opening brace. For example:



<?php
if ( condition )
{
    while (
condition )
    {
        
foo();
    }
}
?>



I know that a lot of programmers prefer to put the first brace on the first line of the block they are encoding, to prevent wasting a line. However, I strongly disagree with this as it makes code much easier to read (in my opinion) if braces line up correctly.


Spaces between tokens


There should always be one space on either side of a token in expressions, statements etc. The only exceptions are commas (which should have one space after, but none before), semi-colons (which should not have spaces on either side if they are at the end of a line, and one space after otherwise). Functions should follow the rules laid out already, i.e. no spaces between the function name and the opening bracket and no space between the brackets and the arguments, but one space between each argument.


Control statements such as if, for, while etc. should have one space on either side of the opening bracket, and one space before the closing bracket. However, individual conditions inside these brackets (e.g. ($i < 9) || ($i > 16)) should not have spaces between their conditions and their opening/closing brackets.



In these examples, each pair shows the incorrect way followed by the correct way:



<?php
$i
=0;
$i = 0;

if((
$i<2 )||( $i>5 ))
if ( (
$i < 2) || ($i > 5) )

foo ( $a,$b,$c )
foo($a, $b, $c)

$i=($j<5)?$j:5
$i
= ($j < 5) ? $j : 5
?>




Operator precedence


I doubt very much that any developer knows the exact precedence of all the operators in PHP. Even if you think you know the order, don't guess because chances are you'll get it wrong and cause an unexpected bug that will be very difficult to find. Also, it will make maintaining your program a living nightmare for anyone who doesn't know the precedence tables in so much depth. Always use brackets to make it absolutely clear what you are doing.



<?php
$i
= $j < 5 || $k > 6 && $m == 9 || $n != 10 ? 1 : 2; // What *is* going on here?!?
$i = ( (($j < 5) || $k > 6)) && (($m == 9) || ($n != 10)) ) ? 1 : 2; // Much clearer
?>



N.B. If you are using expressions like the one above you should split them up into smaller chunks if possible, even if you are already laying them out in the correct format. No-one should have to debug code like that, there's too many conditions and logic operators.


SQL code layout


When writing SQL queries, capitialise all SQL keywords (SELECT, FROM, VALUES, AS etc.) and leave everything else in the relevant case. If you are using WHERE clauses to return data corresponding to a set of conditions, enclose those conditions in brackets in the same way you would for PHP if blocks, e.g. SELECT * FROM users WHERE ( (registered = 'y') AND ((user_level = 'administrator') OR (user_level = 'moderator')) ).



General guidelines


Quoting strings


Strings in PHP can either be quoted with single quotes ('') or double quotes (""). The difference between the two is that the parser will use variable-interpolation in double-quoted strings, but not with single-quoted strings. So if your string contains no variables, use single quotes and save the parser the trouble of attempting to interpolate the string for variables, like so:



<?php
$str
= "Avoid this - it just makes more work for the parser."; // Double quotes
$str = 'This is much better.' // Single quotes
?>



Likewise, if you are passing a variable to a function, there is no need to use double quotes:



<?php
foo
("$bar"); // No need to use double quotes
foo($bar); // Much better
?>



Finally, when using associative arrays, you should include the key within single quotes to prevent any ambiguities, especially with constants:



<?php
$foo
= $bar[example]; // Wrong: what happens if 'example' is defined as a constant elsewhere?
$foo = $bar['example']; // Correct: no ambiguity as to the name of the key
?>



However, if you are accessing an array with a key that is stored in a variable, you can simply use:



<?php
$foo
= $bar[$example];
?>


Shortcut operators



The shortcut operators ++ and -- should always be used on a line of their own, with the exception of for loops. Failure to do this can cause obscure bugs that are incredibly difficult to track down. For example:



<?php
$foo
[$i++] = $j; // Wrong: relies on $i being incremented after the expression is evaluated
$foo[--$j] = $i; // Wrong: relies on $j being decremented before the expression is evaluated
$foo[$i] = $j;
$i++; // Correct: obvious when $i is incremented

$j--;
$foo[$j] = $i; // Correct: obvious when $j is decremented
?>



Optional shortcut constructs


As well as the useful increment and decrement shortcuts, there are two other ways in which you can make your PHP code easier to use. The first is to replace if statements where you are assigning one of two values to a variable based on a conditional. You may be tempted to write something like this:



<?php
if ( isset($_POST['username']) )
{
    
$username = $_POST['username'];
}
else
{
    
$username = '';
}

if ( isset(
$_POST['password']) )
{
    
$password = md5($_POST['password']);
}
else
{
    
$password = '';
}
?>



Whilst the above code works and makes it obvious what you are doing, it's not the easiest or clearest way if you want to run through a list of different variables and do a similar thing to all of them. A more compact way would be to use the ternary operator ? : like so:



<?php
$username
= isset($_POST['username']) ? $_POST['username'] : '';
$password = isset($_POST['password']) ? md5($_POST['password']) : '';
?>



I would recommend using the latter notation wherever you are checking assigning a number of variables one of two values depending on a boolean expression, simply because it makes the code easier to scan and also makes it obvious what you are doing without being unnecessarily verbose.


Use constants where possible


If a value is not going to change throughout the execution of your script, then use a constant rather than a variable to define it. That way, if you do change the value by accident, the PHP parser will output an error and allow you to fix the problem, without it causing any unforeseen side effects.


Remember that constants should never be enclosed in strings, either single or double. You must always use concatenation if you wish to include a constant's value in a string.


Turn on all error reporting


A lot of code I've downloaded from the web and tried to use has failed on my machines because the developers switched off the E_NOTICE flag in their PHP configuration for some reason or another. As soon as I bring it onto my system, where error reporting is set to E_ALL (i.e. show all errors, including references to variables being used without being initialised), the PHP interpreter spews out dozens of error messages which I then have to fix before I can proceed to use the script.



What you need to remember as a developer is that the person who uses your script may not have exactly the same php.ini configuration as you so you aim for the worst possible case, i.e. when some awkard person like me has all error reporting enabled. If your code works with E_ALL set, then it will also work with any other error reporting configuration, including when all error reporting is turned off (e.g. on sites where PHP errors are logged to a file instead).


It's not impossible to get scripts to work with all error reporting turned on, because I've managed it for all the code on all the sites I've ever written PHP code for. Admittedly I've not written any major projects such as a CMS, but if you write proper object oreintated code and make sure that each class doesn't produce any errors, you should be able to make your program as a whole run without errors under normal circumstances.


Of course, on a production site you might want to turn off all errors, or at least redirect them to a file, to avoid admitting to users that your scripts are broken in some way (we know that scripts can't handle every possible error, but users often don't see things this way!). That's perfectly fine and in many cases the recommended action to take. So long as your scripts work with all error reporting turned on, it doesn't matter where they are deployed.

Friday, November 27, 2009

SQL Injection: How To Prevent Security Flaws In PHP / MySQL

Foreword: SQL injection is a very scary phrase. After all, it has single-handedly been responsible for putting down major government websites and thousands of personal home pages- and everything in between. (Something that has been increasingly popular after the “Techie” generation had puberty-riddled children.) Yet believe it or not, guarding against the attack is simple as a couple of lines of code.


SQL Injection: What It Is


There was once a famous doctor that had it completely right: never trust your patients. Now this doctor may have only been a sitcom doctor on the show “House,” but we’ll be taking a page from his book. Of course, in our case the patients will actually be Internet users. Don’t let your guard down! They are conniving, dastardly, plot-making fiends- and you’ll do well to remember it.


First, Let’s define an SQL Injection:


Define SQL Injection



  SQL Injection - \S-Q-L-in-'jek-shen\ - Noun
The technique of inputting malicious data into an SQL statement, which would therefore make the vulnerability present on the database layer. Surprisingly, it seems everyone who has recently taken up learning a web development language has to try the technique out on their favorite websites. Luckily for said websites, this technique isn't at all hard to protect against.

The technique of inputting malicious data into an SQL statement, which would therefore make the vulnerability present on the database layer. Surprisingly, it seems everyone who has recently taken up learning a web development language has to try the technique out on their favorite websites. Luckily for said websites, this technique isn’t at all hard to protect against.


SQL Injection: What It Looks Like


The vast majority of all SQL injections will take place on an input form. Contrary to popular belief, this isn’t the only place where we will see them- it’s also common to manipulate URLs to inject SQL code. (But we’ll get more into that later.)


The most basic of all SQL injections will look like the following:


The Basic SQL Injection


 Variable' or 1=1--


Let’s say we have a login form. By inputting the above code, we can use our SQL injection to gain login even without proper credentials! So how’s it work? Take a look at the “bigger picture” below:


What It Looks Like On The Back-End


 SELECT * FROM users WHERE username = 'Variable' or 1=1--'

See how our code is nicely injected into the query? The result of this query will grant us access regardless of the username, since the result of “1=1″ will always be true. In this case, we bypass the whole selection process.


You may have been wondering what the double dashes are for ( — ). These dashes at the end tell the SQL server to ignore the rest of the query. If the exploit isn’t being used on an SQL server, then omitting the double dashes and ending single quote will get the desired results.


Note that while this is the most standard way, it certainly isn’t the only way that malicious users will gain entry. SQL queries will differ greatly from one syntax to another, and thus, so too should the SQL injection. It’s also common to see the following:


More SQL Injection Syntax Fun



    ') or ('1'='1
"or "1"="1
' or '1'='1
Or 1=1--
" or 1=1--
' or 1=1--

SQL Injection: Attacking Via URLs


Did you know it was possible to attack an SQL server through a URL? Well, it’s possible, and usually much more dangerous to webmasters. When using PHP and SQL, there is commonly a URL such as the following:



  • http://YourWebsite.com/login.php?id=2


By adding a little SQL to the end of the URL, we can do some very mischievous mischief:



  • http://YourWebsite.com/login.php?id=2‘; DROP TABLE login; #



You might be confused by the hash. This little guy is just like the double dash we used earlier; it will tell the SQL query to halt after our input. And if you haven’t noticed, we just told the server to drop the entire table of users! This is an example of how powerful and dangerous SQL injections can be- and also shows that constant backups are a necessity.


Enough already! Let’s finally find out how to make sure that little script kiddies aren’t going to ruin the hard work webmasters and web developers set aside for their projects.


SQL Injection Prevention: Editing Lengths Of Form Components


The first step in the process is simple: simply restrict input fields to the absolute minimum- usually anywhere from 7-12 characters is fine. Doing so will make long queries unable to be input, since the field is only enough characters for smaller queries. This will actually not prevent an SQL injection, but will make work harder for those trying to make use of one.


PHP MySQL


Savvy SQL injection users can simply make a new form and remove the limits on the character length, since the length is in plain HTML and viewable (and editable) by anyone.


SQL Injection Prevention: Data Type Validation


Another good idea is to validate any data once it is received. If a user had to input an age, make sure the input is an actual number. If it was a date, make sure the date is in proper format. Again, this will not prevent an SQL injection in itself- it just makes work harder for those trying to exploit an SQL server.


sql injection prevent



Data type validation can be thwarted by modifying the query over a trial-and-error test period. This is still only slowing attackers down- but isn’t it much more satisfying to have them waste their time before finding out one’s own query is impervious to harm? Of course! An eye for an eye!


SQL Injection Prevention: User Privileges


It’s nice to be able to create a “super user” in one’s own database that can create, drop, and edit tables at will. The security-obsessive webmaster will want to make individual users that can only do one or two tasks at a time. In effect, this means that SQL injections will only be able to do one or two things at a time.


This is just a little prevention fun, it can certainly still cause a certain amount of danger. If a user is made for deleting tables, than an SQL injection can do the same thing- it just won’t be able to do much else. Regardless, deleting a table is a very big privilege to handle. This method is still useful for throwing attackers off track, as well as minimizing risk from areas of a website that aren’t critical to the security of the database.


SQL Injection Prevention: Magic Quotes (Which Aren’t So Magical)


We all love magic. Heck, magic is downright cool. It serves as the basis for great children books (Harry Potter, anyone?) and even has been used for themes in nerdy card games everyone seems to enjoy (Ah, we’re looking at you, Magic The Gathering!)


One thing that just doesn’t live up to the magic name is magic quotes. PHP developers thought it would be a wonderful idea to make a process that escapes all incoming data in a PHP script. Sounds like it would fix our problem with SQL injections, but alas, there are better ways.


Anyone who has recommended a fix with magic quotes doesn’t know what they are talking about. After all, magic quotes are considered deprecated and removed as of PHP version 6. So why such hostility over a process that is seemingly beneficial to our predicament?


The short answer: magic quotes are horrible for portability issues, performance issues, and they mess with other data that doesn’t need to be escaped.




  1. Many scripts made with magic quotes won’t work on servers that have (intelligently) turned the feature off.

  2. Performance loss is observed because not all of the data is being input into a database- we’re wasting process time.

  3. Lastly, magic quotes are just inconvenient. They add an extra slash (”\”) to all of our form data, even when it might not be needed. To fix this, we have to use another process to fix it (If you are unfortunate enough to have used magic quotes, look up the stripslashes() function, and consider switching if possible)


We came close to finding a real solution there- almost! But we did learn something: don’t use magic quotes, and instead find an alternative that can escape the input data based on what we need: not what we don’t.


SQL Injection Prevention: The Solution In Preventing SQL Attacks


We could’ve given you the answer right away, but what fun would that have been? Too often, PHP developers are becoming lazy and not following proper security tactics the way they should. By reaching this point in the lecture, you’ve increased your knowledge on how SQL injections are used, how not to prevent the attacks, and finally: you’ll learn the right way to keep injection attacks at bay.


We’ll accomplish this last feat with a simple function that the developers of PHP made especially for SQL injections. We call this function mysql_real_escape_string() – take a look at it below:



mysql_real_escape_string() In Action!


    $name = "John";
$name = mysql_real_escape_string($name);
$SQL = "SELECT * FROM users WHERE username = '$name'";

Although for a more practical use, we would have the $name variable pointed to a POST result, as seen below:



$_POST Can Dig In On The Action Too!


    $name = mysql_real_escape_string($_POST['user']);

And we can even make things easier by putting it into one line:


All In One Line Now; Here We Go!


$SQL = "SELECT * FROM users where username = "mysql_real_escape_string($POST['user']);


So what’s the output like if malicious users try to get access to our SQL server? Well glad you asked! Their attempts may look something like this:


Cause And Effect With mysql_real_escape_string()


    $malcious_input = "' OR 1'";
// The Above Is The Malicious Input. Don't Be Scared!
// With The mysql_real_escape_string() usage, the following is obtained:


\' OR 1\'
// Notice how the slashes escape the quotes! Now users can't enter malicious data

And the best part is, they just wasted their time and effort for nothing. Now how’s that for vindication!


SQL Injection: Closing Comments



We’ve learned quite a bit today. SQL injections are bad. All Internet users are equally as bad. Protecting against both ensures a happy and stable web application. And above all else, never use magic quotes! Despite their cleverly disguised name, we’ve found no evidence of magic.


Lastly, note that there are libraries and classes that can help aid in the fight against SQL injection. Prepared statements are plausible as well, but as for us, we enjoy sticking to the mysql_real_escape_string() function for less headaches.


Bottom Line: mysql_real_escape_string() – It doesn’t have a magically awesome name, but it’s 24 characters worth of SQL injection-protection goodness.








Curls error and their specifications

CURLcode


Almost all "easy" interface functions return a CURLcode error code. No matter what, using the curl_easy_setopt(3) option CURLOPT_ERRORBUFFER is a good idea as it will give you a human readable error string that may offer more details about the cause of the error than just the error code. curl_easy_strerror(3) can be called to get an error string from a given CURLcode number.

CURLcode is one of the following:

CURLE_OK (0)

All fine. Proceed as usual.

CURLE_UNSUPPORTED_PROTOCOL (1)

The URL you passed to libcurl used a protocol that this libcurl does not support. The support might be a compile-time option that you didn't use, it can be a misspelled protocol string or just a protocol libcurl has no code for.

CURLE_FAILED_INIT (2)

Very early initialization code failed. This is likely to be an internal error or problem.

CURLE_URL_MALFORMAT (3)

The URL was not properly formatted.

CURLE_COULDNT_RESOLVE_PROXY (5)

Couldn't resolve proxy. The given proxy host could not be resolved.

CURLE_COULDNT_RESOLVE_HOST (6)

Couldn't resolve host. The given remote host was not resolved.

CURLE_COULDNT_CONNECT (7)

Failed to connect() to host or proxy.

CURLE_FTP_WEIRD_SERVER_REPLY (8)

After connecting to a FTP server, libcurl expects to get a certain reply back. This error code implies that it got a strange or bad reply. The given remote server is probably not an OK FTP server.

CURLE_REMOTE_ACCESS_DENIED (9)

We were denied access to the resource given in the URL. For FTP, this occurs while trying to change to the remote directory.

CURLE_FTP_WEIRD_PASS_REPLY (11)

After having sent the FTP password to the server, libcurl expects a proper reply. This error code indicates that an unexpected code was returned.

CURLE_FTP_WEIRD_PASV_REPLY (13)

libcurl failed to get a sensible result back from the server as a response to either a PASV or a EPSV command. The server is flawed.

CURLE_FTP_WEIRD_227_FORMAT (14)

FTP servers return a 227-line as a response to a PASV command. If libcurl fails to parse that line, this return code is passed back.

CURLE_FTP_CANT_GET_HOST (15)

An internal failure to lookup the host used for the new connection.

CURLE_FTP_COULDNT_SET_TYPE (17)

Received an error when trying to set the transfer mode to binary or ASCII.

CURLE_PARTIAL_FILE (18)

A file transfer was shorter or larger than expected. This happens when the server first reports an expected transfer size, and then delivers data that doesn't match the previously given size.

CURLE_FTP_COULDNT_RETR_FILE (19)

This was either a weird reply to a 'RETR' command or a zero byte transfer complete.

CURLE_QUOTE_ERROR (21)

When sending custom "QUOTE" commands to the remote server, one of the commands returned an error code that was 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command.

CURLE_HTTP_RETURNED_ERROR (22)

This is returned if CURLOPT_FAILONERROR is set TRUE and the HTTP server returns an error code that is >= 400. (This error code was formerly known as CURLE_HTTP_NOT_FOUND.)

CURLE_WRITE_ERROR (23)

An error occurred when writing received data to a local file, or an error was returned to libcurl from a write callback.

CURLE_UPLOAD_FAILED (25)

Failed starting the upload. For FTP, the server typically denied the STOR command. The error buffer usually contains the server's explanation for this. (This error code was formerly known as CURLE_FTP_COULDNT_STOR_FILE.)

CURLE_READ_ERROR (26)

There was a problem reading a local file or an error returned by the read callback.

CURLE_OUT_OF_MEMORY (27)

A memory allocation request failed. This is serious badness and things are severely screwed up if this ever occurs.

CURLE_OPERATION_TIMEDOUT (28)

Operation timeout. The specified time-out period was reached according to the conditions.

CURLE_FTP_PORT_FAILED (30)

The FTP PORT command returned error. This mostly happens when you haven't specified a good enough address for libcurl to use. See CURLOPT_FTPPORT.

CURLE_FTP_COULDNT_USE_REST (31)

The FTP REST command returned error. This should never happen if the server is sane.

CURLE_RANGE_ERROR (33)

The server does not support or accept range requests.

CURLE_HTTP_POST_ERROR (34)

This is an odd error that mainly occurs due to internal confusion.

CURLE_SSL_CONNECT_ERROR (35)

A problem occurred somewhere in the SSL/TLS handshake. You really want the error buffer and read the message there as it pinpoints the problem slightly more. Could be certificates (file formats, paths, permissions), passwords, and others.

CURLE_FTP_BAD_DOWNLOAD_RESUME (36)

Attempting FTP resume beyond file size.

CURLE_FILE_COULDNT_READ_FILE (37)

A file given with FILE:// couldn't be opened. Most likely because the file path doesn't identify an existing file. Did you check file permissions?

CURLE_LDAP_CANNOT_BIND (38)

LDAP cannot bind. LDAP bind operation failed.

CURLE_LDAP_SEARCH_FAILED (39)

LDAP search failed.

CURLE_FUNCTION_NOT_FOUND (41)

Function not found. A required zlib function was not found.

CURLE_ABORTED_BY_CALLBACK (42)

Aborted by callback. A callback returned "abort" to libcurl.

CURLE_BAD_FUNCTION_ARGUMENT (43)

Internal error. A function was called with a bad parameter.

CURLE_INTERFACE_FAILED (45)

Interface error. A specified outgoing interface could not be used. Set which interface to use for outgoing connections' source IP address with CURLOPT_INTERFACE. (This error code was formerly known as CURLE_HTTP_PORT_FAILED.)

CURLE_TOO_MANY_REDIRECTS (47)

Too many redirects. When following redirects, libcurl hit the maximum amount. Set your limit with CURLOPT_MAXREDIRS.

CURLE_UNKNOWN_TELNET_OPTION (48)

An option set with CURLOPT_TELNETOPTIONS was not recognized/known. Refer to the appropriate documentation.

CURLE_TELNET_OPTION_SYNTAX (49)

A telnet option string was Illegally formatted.

CURLE_PEER_FAILED_VERIFICATION (51)

The remote server's SSL certificate or SSH md5 fingerprint was deemed not OK.

CURLE_GOT_NOTHING (52)

Nothing was returned from the server, and under the circumstances, getting nothing is considered an error.

CURLE_SSL_ENGINE_NOTFOUND (53)

The specified crypto engine wasn't found.

CURLE_SSL_ENGINE_SETFAILED (54)

Failed setting the selected SSL crypto engine as default!

CURLE_SEND_ERROR (55)

Failed sending network data.

CURLE_RECV_ERROR (56)

Failure with receiving network data.

CURLE_SSL_CERTPROBLEM (58)

problem with the local client certificate.

CURLE_SSL_CIPHER (59)

Couldn't use specified cipher.

CURLE_SSL_CACERT (60)

Peer certificate cannot be authenticated with known CA certificates.

CURLE_BAD_CONTENT_ENCODING (61)

Unrecognized transfer encoding.

CURLE_LDAP_INVALID_URL (62)

Invalid LDAP URL.

CURLE_FILESIZE_EXCEEDED (63)

Maximum file size exceeded.

CURLE_USE_SSL_FAILED (64)

Requested FTP SSL level failed.

CURLE_SEND_FAIL_REWIND (65)

When doing a send operation curl had to rewind the data to retransmit, but the rewinding operation failed.

CURLE_SSL_ENGINE_INITFAILED (66)

Initiating the SSL Engine failed.

CURLE_LOGIN_DENIED (67)

The remote server denied curl to login (Added in 7.13.1)

CURLE_TFTP_NOTFOUND (68)

File not found on TFTP server.

CURLE_TFTP_PERM (69)

Permission problem on TFTP server.

CURLE_REMOTE_DISK_FULL (70)

Out of disk space on the server.

CURLE_TFTP_ILLEGAL (71)

Illegal TFTP operation.

CURLE_TFTP_UNKNOWNID (72)

Unknown TFTP transfer ID.

CURLE_REMOTE_FILE_EXISTS (73)

File already exists and will not be overwritten.

CURLE_TFTP_NOSUCHUSER (74)

This error should never be returned by a properly functioning TFTP server.

CURLE_CONV_FAILED (75)

Character conversion failed.

CURLE_CONV_REQD (76)

Caller must register conversion callbacks.

CURLE_SSL_CACERT_BADFILE (77)

Problem with reading the SSL CA cert (path? access rights?)

CURLE_REMOTE_FILE_NOT_FOUND (78)

The resource referenced in the URL does not exist.

CURLE_SSH (79)

An unspecified error occurred during the SSH session.

CURLE_SSL_SHUTDOWN_FAILED (80)

Failed to shut down the SSL connection.

CURLE_AGAIN (81)

Socket is not ready for send/recv wait till it's ready and try again. This return code is only returned from curl_easy_recv(3) and curl_easy_send(3) (Added in 7.18.2)

CURLE_SSL_CRL_BADFILE (82)

Failed to load CRL file (Added in 7.19.0)

CURLE_SSL_ISSUER_ERROR (83)

Issuer check failed (Added in 7.19.0)

CURLE_OBSOLETE*

These error codes will never be returned. They were used in an old libcurl version and are currently unused.

CURLMcode


This is the generic return code used by functions in the libcurl multi interface. Also consider curl_multi_strerror(3).

CURLM_CALL_MULTI_PERFORM (-1)

This is not really an error. It means you should call curl_multi_perform(3) again without doing select() or similar in between.

CURLM_OK (0)

Things are fine.

CURLM_BAD_HANDLE (1)

The passed-in handle is not a valid CURLM handle.

CURLM_BAD_EASY_HANDLE (2)

An easy handle was not good/valid. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle.

CURLM_OUT_OF_MEMORY (3)

You are doomed.

CURLM_INTERNAL_ERROR (4)

This can only be returned if libcurl bugs. Please report it to us!

CURLM_BAD_SOCKET (5)

The passed-in socket is not a valid one that libcurl already knows about. (Added in 7.15.4)

CURLM_UNKNOWN_OPTION (6)

curl_multi_setopt() with unsupported option (Added in 7.15.4)

CURLSHcode


The "share" interface will return a CURLSHcode to indicate when an error has occurred. Also consider curl_share_strerror(3).

CURLSHE_OK (0)

All fine. Proceed as usual.

CURLSHE_BAD_OPTION (1)

An invalid option was passed to the function.

CURLSHE_IN_USE (2)

The share object is currently in use.

CURLSHE_INVALID (3)

An invalid share object was passed to the function.

CURLSHE_NOMEM (4)

Not enough memory was available. (Added in 7.12.0)








Tuesday, November 17, 2009

Easy steps to start with magento

Why Use Magento?


Well there are quite a few very good reasons to use Magento:




  • A Simple Intuitive Interface

  • Easy To Download, Install & Maintain

  • Built on current technologies unlike other systems.

  • Multiple Site Functionality

  • And best of all...It's free and open source!




Preparation


As with all successful things in life, preparation is key! Before we can install Magento we must set up a database on our server. Using phpmyadmin we create a new database called "magento". We will use this later when we come to install Magento.





Downloading/Installing Magento


Once our database has been set up on our server the next step is to download Magento itself. To do that we need to go to the download page on the Magento website. For this tutorial we will be downloading the Full Release in ZIP format. Once you have it downloaded unzip it to the folder of your choice.




Now that we have the files on our server it’s time to install Magento, to do this we go to http://localhost/magento (or whichever folder your using) in your web browser.



Accept the TOC's and continue onto the next page.



Pick the settings that apply to you and click continue.



Going well so far...Now fill in the database connection settings. Make sure that you hit Use Web Server (Apache) Rewrites for added SEO friendliness and if you want to change the default access address for your backend from /admin edit the Admin Path field.



Fill in the login details you'd like to use for your account and enter an custom encryption key if you like, otherwise leave it blank and Magento will make one for you.




Great, now Magento has been installed on your server, if you have installed locally there is one last step you need to take before you can login...


In your Magento folder go to app/code/core/Mage/Core/Model/Session/Abstract/Varien.php


Find the session_set_cookie_params code block (Line 78) and replace it with this code:


  1. session_set_cookie_params(  
  2.           $this->getCookie()->getLifetime(),  
  3.           $this->getCookie()->getPath()  
  4.           //$this->getCookie()->getDomain(),  
  5.           //$this->getCookie()->isSecure(),  
  6.           //$this->getCookie()->getHttponly()  
  7.       );  

On a proper webhost you do not need to do this! However as we are working on localhost we need to do this to address an cookie issue.





Tax Rules


To set up our different levels of tax we need to go to the Manage Tax Zones & Rates tab under Sales » Tax. If the rule for your state doesn't exist or has been changed recently then hit the "Add New Tax Rate".






Save your new tax rule and you are good to go!



Categories


To create a new category we need to go to the Catalog tab on the navigation and select Manage Categories. From there we can manage and add new categories.



To create our new category we need to click Add Subcategory and fill in the details like the picture below, making sure to change Is Active to Yes.




Products



Products are key to a site but in Magento there was multiple product types as shown below...To create a new product we need to Catalog tab on the navigation and select Manage Products. And finally click Add Product



Simple Products


These are the products that have no options, such as DVD. To create our Simple product select Default for the attribute set and Simple Product for the Product Type and click Continue.


General Tab





  1. Name: The name of our new product

  2. Description: The main body description of the product; the place to really sell the product and all of its features!

  3. Short Description: The quick overview that appears just below the price on the product page; the place to grab the attention of buyers

  4. SKU: The stock code for the product

  5. Weight: The weight of the product. This can be kilos, tonnes or whatever you want as long as you keep uniformity across all your products

  6. Manufacturer: Blank by default but manufacturers can be added through the Manage Attributes Tab.


  7. Colour: Blank by default but again like the manufactures can be added through the Manage Attributes Tab

  8. Set Product As New From Date: Sets the product to new from the date you enter.

  9. Set Product as New to Date: Sets when the product ends being new.

  10. Status: If the product is Enabled and showing on the website or if it's disabled.

  11. URL key: The custom option for how the URL for your product is written.

  12. Visibility: Where the product can be found by your visitors;


    • Nowhere: The product does not appear on the website.

    • Catalog: The product will appear on the website but not in search results.

    • Search: The product will not appear on the website but will appear in search results.

    • Catalog, Search: The product will appear on the website and in search results.



  13. Allow Gift Message:


    • Yes: Allows a gift message

    • No: Doesn't allow a gift message

    • Config: Use the site's configuration




Price Tab





  1. Price: The price of our product

  2. Special Price: Offers on products for limited times.

  3. Special Price From Date: The date in which the special price starts.

  4. Special Price To Date: The date in which the special price ends.

  5. Cost: The cost of the product.

  6. Tax Class: If your product requires Tax added then Taxable Goods must be selected.


  7. Tier Price: Allows for bulk discounts to be set up. Click Add Tier to add quantity discounts.

  8. Google Checkout: Can visitors buy this product using Google Checkout.


Meta Information Tab




  1. Meta Title: Information that appears in the <title> tag.


  2. Meta Keywords: keywords that apply to your product.

  3. Meta Description: A short description of your product that appears on Search Engine Result Pages.


Images Tab



Images are a key part of your product and the better quality you can get the more chance you have of making a sale, Magento allows for multiple images to be uploaded and specific images to be uploaded for the Base Image, the Small Image and the Thumbnail, as well as allowing for a label. If you want to remove an image simply click the Exclude to hide or the Remove to delete checkbox(s).



  • Base Image: The main image that appears on the product page.

  • Small Image: The image that appears in the categories/search view.


  • Thumbnail: The thumbnail of the product.


Design Tab


Unless you are using a template for your Magento store it's best to give this one a miss, but for anyone who is curious the Design tab allows you to use themes that you have set up and allows you to choose active to and from dates as well as changing the page layout into different column blocks and so on.


Inventory Tab




  1. Manage Stock: If you'd like to track and manage stock levels then leave this set to Yes

  2. Qty: The amount of product you have.


  3. Stock Availability: If the product is in stock or not. Setting this to Out of Stock will not hide the product on the website!


The other options are best left to the site configuration however are all pretty self explanatory if you wish to set them to your needs.



Categories Tab



Your product can appear in multiple categories; simply click the checkbox of the category you want it to appear in!



Related Products / Up-sells / Cross-sells



With related products, up-sells and cross-sells the interface to add is same, to add a product simply select a field you wish to search by and click the search button, a list of products matching your criteria will appear. Click the checkbox next to the product and it will appear as a related product/up-sell or cross-sell as applicable.



Product Reviews / Product Tags / Customers Tagged Product


These are all added by users and can viewed from the tabs.



Custom Options


These are custom options that you can add to your product. To add a custom option click Add New Option and fill in the details.



Managing Attributes & Attribute Sets



Attributes are the options that make up your products, for example colour, weight and so on. Attribute sets are sets of attributes that make a whole product and allow us to make configurable products.


Attributes



To create a new attribute/view our current attributes we need to go to the Catalog tab on the navigation and select Attributes and then Manage Attributes. To view a attribute simply click on the row, to create a new attribute click the Add New Attribute Tab.



Properties Tab


It's best to use an convention when you are naming your attributes, as your list grows it will make it easier to find what you are looking for. I like to use options_option_product which for this product would be options_colour_nettuts_shirt. We must set our scope to global and Catalog Input Type to Dropdown in order to create our configurable product(s). We are only applying our Attribute to Simple Products and Configurable Products. In order to use this attribute in our configurable products we must choose Yes on the Use To Create Configurable Product field. We must also select Yes on the Visible on Product View Page on Front-end field in order to make the attribute visible.




Manage Label / Options Tab


Next we need to set up the options for our user to select from when choosing there product. In our example we are using Colour as our product option.


The title is what the visitor will see above the dropdown, with Magento we can define what the admin sees and what the user sees making it easier to track options with additional information, in the example we have called our Title, Colour. If we leave the Default Store View blank it will copy what we have entered into Admin.


To add the options for our product click the Add Option button for the number of options you require, in our example 3. Like the title if we leave the Default Store View blank it will copy what we have entered into Admin but we can use the Admin field to add more information, making it easy to fulfill orders for example. We use position to order our options and the Is Default radio box to define which option is default. We can easily delete any option using the button to the right. Once we have all the options we want click Save to return to the attributes page.


Attribute Sets



Next we need to set up our Attribute Set in order to create our configurable product. We navigate to the Catalog tab on the navigation and select Attributes and then Manage Attribute Sets. Like the Attributes page we have a list of our Current Attribute Sets; Default should only be appearing. Click Add New Set.



Again like our Attribute we should use a convention to name our Attribute Set...so matching our Attribute; options_size_tshirts. Since we have no other Sets we are going to base the new one on Default.




To include our Attribute into our Set we simply need to click and drop it into the General group from the right hand list. Click save and our set is complete. Going well so far...



Creating A Configurable Product


Creating a configurable product is very similar to creating a Simple Product. To start we create a new product. But we need to change the Attribute Set to the one we just created and the product type to Configurable Product and click continue.



Next we need to pick the Attributes we would like to use in our product. Only attributes with a scope of Global, type of dropdown and the option to create a configurable product set to yes can be used.



The only tabs that change are the Inventory tab and an new tab has been added called Associated Products which is where we will add our options. Once we have filled in all our details we need to save and continue edit before we can begin to add our Associated Products. Unlike some other ecommerce systems Magento creates simple products that are hidden in order to create a configurable product.



To create the options we are going to use the "Quick simple product creation" tool to make our Simple Product options. For the name and SKU fields you can let Magento auto generate these but for added control I suggest that you fill these in yourself. In the example we are creating a green shirt option. We have filled in the Name, SKU, Weight and have set the product to Enabled. However we must set the visibility of our product to nowhere. From the drop-down we select the attribute option we are creating for and set the price. For the default option we don't enter a value and it will use the price we set on our configurable product but for the other options we enter the difference between the configurable product and the option. So if the Green top is $15 and our configurable product is $20 then we have to enter -5.00 as our price. We then need to set the Qty for the option and the Stock Availability to In Stock and click Quick Create. We repeat this process until we have added all of our options and click save. Our configurable product is now complete. If we view our products page we can see that Magento has created the options as simple products for us that have been hidden. Making tracking stock much easier!





Congratulations


Well done, you have just downloaded and installed Magento to your localhost, you have created a simple product, a custom attribute and attribute set, a configurable product using your custom attribute and a category. I hope that you have learned some of the basics of Magento and I wish you all the best during your endeavors. If you have any questions please leave a comment below and i'll try my best to help you out!


If you a real go getter and would like to get into some of the more advanced topics or would like to learn more than I suggest that you check out the Knowledge Base on the Magento website as well as Designers Guide if you’re interested in customizing Magento more.








Monday, November 16, 2009

install magento in easy steps

Why Use Magento?


Well there are quite a few very good reasons to use Magento:




  • A Simple Intuitive Interface

  • Easy To Download, Install & Maintain

  • Built on current technologies unlike other systems.

  • Multiple Site Functionality

  • And best of all...It's free and open source!




Preparation


As with all successful things in life, preparation is key! Before we can install Magento we must set up a database on our server. Using phpmyadmin we create a new database called "magento". We will use this later when we come to install Magento.





Downloading/Installing Magento


Once our database has been set up on our server the next step is to download Magento itself. To do that we need to go to the download page on the Magento website. For this tutorial we will be downloading the Full Release in ZIP format. Once you have it downloaded unzip it to the folder of your choice.




Now that we have the files on our server it’s time to install Magento, to do this we go to http://localhost/magento (or whichever folder your using) in your web browser.



Accept the TOC's and continue onto the next page.



Pick the settings that apply to you and click continue.



Going well so far...Now fill in the database connection settings. Make sure that you hit Use Web Server (Apache) Rewrites for added SEO friendliness and if you want to change the default access address for your backend from /admin edit the Admin Path field.



Fill in the login details you'd like to use for your account and enter an custom encryption key if you like, otherwise leave it blank and Magento will make one for you.




Great, now Magento has been installed on your server, if you have installed locally there is one last step you need to take before you can login...


In your Magento folder go to app/code/core/Mage/Core/Model/Session/Abstract/Varien.php


Find the session_set_cookie_params code block (Line 78) and replace it with this code:


  1. session_set_cookie_params(  
  2.           $this->getCookie()->getLifetime(),  
  3.           $this->getCookie()->getPath()  
  4.           //$this->getCookie()->getDomain(),  
  5.           //$this->getCookie()->isSecure(),  
  6.           //$this->getCookie()->getHttponly()  
  7.       );  

On a proper webhost you do not need to do this! However as we are working on localhost we need to do this to address an cookie issue.





Tax Rules


To set up our different levels of tax we need to go to the Manage Tax Zones & Rates tab under Sales » Tax. If the rule for your state doesn't exist or has been changed recently then hit the "Add New Tax Rate".






Save your new tax rule and you are good to go!



Categories


To create a new category we need to go to the Catalog tab on the navigation and select Manage Categories. From there we can manage and add new categories.



To create our new category we need to click Add Subcategory and fill in the details like the picture below, making sure to change Is Active to Yes.




Products



Products are key to a site but in Magento there was multiple product types as shown below...To create a new product we need to Catalog tab on the navigation and select Manage Products. And finally click Add Product



Simple Products


These are the products that have no options, such as DVD. To create our Simple product select Default for the attribute set and Simple Product for the Product Type and click Continue.


General Tab





  1. Name: The name of our new product

  2. Description: The main body description of the product; the place to really sell the product and all of its features!

  3. Short Description: The quick overview that appears just below the price on the product page; the place to grab the attention of buyers

  4. SKU: The stock code for the product

  5. Weight: The weight of the product. This can be kilos, tonnes or whatever you want as long as you keep uniformity across all your products

  6. Manufacturer: Blank by default but manufacturers can be added through the Manage Attributes Tab.


  7. Colour: Blank by default but again like the manufactures can be added through the Manage Attributes Tab

  8. Set Product As New From Date: Sets the product to new from the date you enter.

  9. Set Product as New to Date: Sets when the product ends being new.

  10. Status: If the product is Enabled and showing on the website or if it's disabled.

  11. URL key: The custom option for how the URL for your product is written.

  12. Visibility: Where the product can be found by your visitors;


    • Nowhere: The product does not appear on the website.

    • Catalog: The product will appear on the website but not in search results.

    • Search: The product will not appear on the website but will appear in search results.

    • Catalog, Search: The product will appear on the website and in search results.



  13. Allow Gift Message:


    • Yes: Allows a gift message

    • No: Doesn't allow a gift message

    • Config: Use the site's configuration




Price Tab





  1. Price: The price of our product

  2. Special Price: Offers on products for limited times.

  3. Special Price From Date: The date in which the special price starts.

  4. Special Price To Date: The date in which the special price ends.

  5. Cost: The cost of the product.

  6. Tax Class: If your product requires Tax added then Taxable Goods must be selected.


  7. Tier Price: Allows for bulk discounts to be set up. Click Add Tier to add quantity discounts.

  8. Google Checkout: Can visitors buy this product using Google Checkout.


Meta Information Tab




  1. Meta Title: Information that appears in the <title> tag.


  2. Meta Keywords: keywords that apply to your product.

  3. Meta Description: A short description of your product that appears on Search Engine Result Pages.


Images Tab



Images are a key part of your product and the better quality you can get the more chance you have of making a sale, Magento allows for multiple images to be uploaded and specific images to be uploaded for the Base Image, the Small Image and the Thumbnail, as well as allowing for a label. If you want to remove an image simply click the Exclude to hide or the Remove to delete checkbox(s).



  • Base Image: The main image that appears on the product page.

  • Small Image: The image that appears in the categories/search view.


  • Thumbnail: The thumbnail of the product.


Design Tab


Unless you are using a template for your Magento store it's best to give this one a miss, but for anyone who is curious the Design tab allows you to use themes that you have set up and allows you to choose active to and from dates as well as changing the page layout into different column blocks and so on.


Inventory Tab




  1. Manage Stock: If you'd like to track and manage stock levels then leave this set to Yes

  2. Qty: The amount of product you have.


  3. Stock Availability: If the product is in stock or not. Setting this to Out of Stock will not hide the product on the website!


The other options are best left to the site configuration however are all pretty self explanatory if you wish to set them to your needs.



Categories Tab



Your product can appear in multiple categories; simply click the checkbox of the category you want it to appear in!



Related Products / Up-sells / Cross-sells



With related products, up-sells and cross-sells the interface to add is same, to add a product simply select a field you wish to search by and click the search button, a list of products matching your criteria will appear. Click the checkbox next to the product and it will appear as a related product/up-sell or cross-sell as applicable.



Product Reviews / Product Tags / Customers Tagged Product


These are all added by users and can viewed from the tabs.



Custom Options


These are custom options that you can add to your product. To add a custom option click Add New Option and fill in the details.



Managing Attributes & Attribute Sets



Attributes are the options that make up your products, for example colour, weight and so on. Attribute sets are sets of attributes that make a whole product and allow us to make configurable products.


Attributes



To create a new attribute/view our current attributes we need to go to the Catalog tab on the navigation and select Attributes and then Manage Attributes. To view a attribute simply click on the row, to create a new attribute click the Add New Attribute Tab.



Properties Tab


It's best to use an convention when you are naming your attributes, as your list grows it will make it easier to find what you are looking for. I like to use options_option_product which for this product would be options_colour_nettuts_shirt. We must set our scope to global and Catalog Input Type to Dropdown in order to create our configurable product(s). We are only applying our Attribute to Simple Products and Configurable Products. In order to use this attribute in our configurable products we must choose Yes on the Use To Create Configurable Product field. We must also select Yes on the Visible on Product View Page on Front-end field in order to make the attribute visible.




Manage Label / Options Tab


Next we need to set up the options for our user to select from when choosing there product. In our example we are using Colour as our product option.


The title is what the visitor will see above the dropdown, with Magento we can define what the admin sees and what the user sees making it easier to track options with additional information, in the example we have called our Title, Colour. If we leave the Default Store View blank it will copy what we have entered into Admin.


To add the options for our product click the Add Option button for the number of options you require, in our example 3. Like the title if we leave the Default Store View blank it will copy what we have entered into Admin but we can use the Admin field to add more information, making it easy to fulfill orders for example. We use position to order our options and the Is Default radio box to define which option is default. We can easily delete any option using the button to the right. Once we have all the options we want click Save to return to the attributes page.


Attribute Sets



Next we need to set up our Attribute Set in order to create our configurable product. We navigate to the Catalog tab on the navigation and select Attributes and then Manage Attribute Sets. Like the Attributes page we have a list of our Current Attribute Sets; Default should only be appearing. Click Add New Set.



Again like our Attribute we should use a convention to name our Attribute Set...so matching our Attribute; options_size_tshirts. Since we have no other Sets we are going to base the new one on Default.




To include our Attribute into our Set we simply need to click and drop it into the General group from the right hand list. Click save and our set is complete. Going well so far...



Creating A Configurable Product


Creating a configurable product is very similar to creating a Simple Product. To start we create a new product. But we need to change the Attribute Set to the one we just created and the product type to Configurable Product and click continue.



Next we need to pick the Attributes we would like to use in our product. Only attributes with a scope of Global, type of dropdown and the option to create a configurable product set to yes can be used.



The only tabs that change are the Inventory tab and an new tab has been added called Associated Products which is where we will add our options. Once we have filled in all our details we need to save and continue edit before we can begin to add our Associated Products. Unlike some other ecommerce systems Magento creates simple products that are hidden in order to create a configurable product.



To create the options we are going to use the "Quick simple product creation" tool to make our Simple Product options. For the name and SKU fields you can let Magento auto generate these but for added control I suggest that you fill these in yourself. In the example we are creating a green shirt option. We have filled in the Name, SKU, Weight and have set the product to Enabled. However we must set the visibility of our product to nowhere. From the drop-down we select the attribute option we are creating for and set the price. For the default option we don't enter a value and it will use the price we set on our configurable product but for the other options we enter the difference between the configurable product and the option. So if the Green top is $15 and our configurable product is $20 then we have to enter -5.00 as our price. We then need to set the Qty for the option and the Stock Availability to In Stock and click Quick Create. We repeat this process until we have added all of our options and click save. Our configurable product is now complete. If we view our products page we can see that Magento has created the options as simple products for us that have been hidden. Making tracking stock much easier!