Title: A Guide to Modifying your User Page
Author: Sally (Lazuli) -- sally{AT}lunaescence{dot}com
Description: This is a guide to creating your own modifications to the user page. This includes discussions of PHP, MySQL, and other things you will need to know in order to modify your user page.
This guide is written as though you currently have user.php, viewuser.php, and your database open as you're reading.
Requirements: eFiction 2.0
Mod History:
29 June 2006 -- Created this guide.
09 July 2006 – Guide released
14 July 2006 – Edited for clarity
So you want to create a custom user page? Great! Customizations to the user page are probably one of the areas that receive the most modification requests for eFiction 2.0. While this page may look confusing, it's actually pretty straight forward once you get the hang of it.
As with any mod, making frequent backups is essential. If you want to be really safe, I suggest making multiple copies of your modifications as you progress through each step, for an easy return to that step should something go wrong.
Another thing to note is that eFiction 3.0 will allow you to add your own custom fields to the user profile. I'll update this guide or release a new one once it is released to explain how to customize your install and how to do further modifications.
To begin with, let's look at MySQL -- the driving force behind eFiction. SQL (pronounced either Sequel OR ess-cue-ell; both ways are correct) is short for "Structured Query Language." SQL runs what is called a "relational database."
To keep it simple (and because we're just talking about the user page), we'll skip the explanation of "relational" in this tutorial. A database is basically nothing more than a way to store data. For example, you could consider a phone book or filing cabinet a form of database.
Inside each database, you have tables that help to sort the information and store it in a meaningful way. You could consider that the same as each file folder in that filing cabinet or the white and yellow pages of the phonebook.
The table we're concerned with at the moment is the authors table.
The authors table is made up of fields that contain author information. Each field is assigned a name, a datatype, length, whether or not it allows for null values, and the default value. Some fields, like the UID, have another value that marks it as the "key" or "primary" field – which just means that field is supposed to contain a value that is unique to each member.
The name is pretty straight-forward. A unique, easily remembered name to identify each field.
The datatype is where things can get a little confusing. All a datatype is is a way to tell the database what kind of information we want to store in that field. There are numerous kinds of datatypes, but the ones we have to worry about are:
INT: Short for "integer", this is a field that only allows numbers. This is the datatype used to store your user's UIDs, since those are just a sequence of numbers. By default, MySQL will store up to 11 characters for any field marked this way.
VARCHAR:Short for "variable character", this is a datatype that allows for almost anything. Letters, numbers, and special characters – anything is allowed. This is what is used to store penname, realname, e-mail, password, userskin, contact information, and all kinds of other stuff. By default, MySQL will store up to 255 characters for any field marked this way.
TEXT: Just what it sounds like. This holds just a bunch of text. The bios are stored this way.
TINYINT: Short for "Tiny Integer", this is a much smaller version of the integer datatype. Basically, this means numbers. For eFiction, this is usually used with you only need to store only a very few numbers. By default, MySQL will only allow up to 3 - 4 characters in this field. An example would be their user level or whether they receive new story notifications if they're admin.
DATE: Another datatype that sounds exactly like it this. This datatype exclusively handles dates and times. The format is: DD-MM-YYYY HH:MM:SS. The time is stored in 24 hour time, usually to your server time but you also sometimes find it in GMT. An example would be 29-06-2006 22:02:15; which comes out to 29 June 2006 10:02:15pm.
CHAR: Short for "character", this is another short datatype. Like VARCHAR, we can store almost anything in this. This is used for beta reader, ageconsent, and favorite alerts.
(Interested in learning more about datatypes? The official MySQL website has a complete list.)
So where am I going with this?
If you want to add a new field to your user page, you need to store it in the database. In order to do this, you have to create the field in the database.
Knowing the difference between these datatypes will help you save space and use the database more effectively. Why use a field that allows HUGE amounts of data, when all you want to store is a yes or no answer?
Next up is length. Like I said above, sometimes there are limits as to how long a field can be. Sometimes while there is a limit, it's so huge that you'll probably never hit the ceiling. (For example, the limit on the TEXT datatype is about 65535 characters.) Try to hit for a length that will store what you need, without wasting extra space. I'll cover this in greater depth later in this article.
TRIVIA: When you delete something from a SQL database, the space is not freed up until you optimize the database. For most hosts, this can be done from either phpMyAdmin or your SQL control panel.
Null is a fancy way of saying "Can this field be left blank?" It can either be set to yes or no. Sometimes it matters and sometimes it doesn't. Most of the fields in our database say no, something has to be in it.
Default value just tells the database what to put in that field if there's no data. A good example would be the date, which just contains the way the date is stored.
Now that I've touched on the actual meat of the field, now you have to plan it. I suggest writing your plan down on a piece of paper or a notebook to keep things clear for yourself.
Name: First of all, what do you want to call your field? Keep it short, simple, and descriptive. (Do you really want to type out "usercontactinformation" everytime you call that field?) If you're adding a contact link that has a short nick-name or a popular acronym, go ahead and use it. It doesn't matter what case your name is in, just so long as you're going to remember it's in upper case, lower case, or mixed case when you go to write it. I usually do all mine in lower case to make it easier for me to remember.
Datatype: First ask yourself what kind of information you want that field to store.
Stuff like links, instant messenger names, contact information, user names for other sites could safely be stored in the VARCHAR datatype.
Notes, extra bios, and other things that could contain a large amount of data should be stored in the TEXT datatype.
Things like "yes" or "no" answers can be further simplified to "0" for "no" and "1" for "yes." Additions that offer multiple options like my gender mod or JanAQ's affiliation mod can also be shortened to numbers. You can store these in a short datatype, like CHAR or TINYINT.
Length: How much information do you need to store?
If you're storing only a single character or number in that field, you can safely make the length 1.
If you're allowing them to put in their user name from another archive or another Instant Messenger screen name, you should probably make it long enough to store the largest name allowed for that medium. Usually 200 to 255 characters are plenty.
Null or Not Null: As I said above, most of the fields in your eFiction database usually don't accept null values so we'll just say "No."
Where (After): If you're doing this by hand, you might also want to determine where you want the field to be. By "where", I mean what field do you want the new one to come after? Knowing where your field is placed is very important and I'll discuss why in a moment.
Now that you have your field planned, you have to add it.
I usually do mine through a program my host has on my site called phpMyAdmin, but you can also do this by hand.
To do it by hand, you would write: ALTER TABLE `fanfiction_authors` ADD `yourDatabaseName` DATATYPE( length ) DEFAULT 'your default value' NOT NULL AFTER `Field your new one comes after`;
Through phpMyAdmin, you would click on the author's table and then scroll down below the structure listing to add your field in there. Choose the number of fields you want to add and where you want to add it. You'll then be taken to a page where you can fill in your necessary information.
Step 1: Choose the number of fields you need and where you want the new field added

Step 2: Fill in your information

Now that your database has been updated with your new field, now we venture into user.php.
When you first open user.php, the first thing that you see is the comments Tammy has left us at the top of the page. In order to keep myself straight, I usually add a short list of what I've done either directly above or directly below these comments. To make sure you don't mess up your page, hide this list using a comment.
Version #1 -- //
// This will make only a single line a comment. Once you hit enter, your comment has ended.
Version #2 -- /* and */
/* This will make everything a comment until you close it.
This type of comment is great for hiding a large section of code if you seriously have to alter it, but don't want to lose it should something go wrong.
Just copy it that section and put these comment tags on either side. If you need the original back, erase your mod and remove the comment tags. */
Now, next up is stuff you probably shouldn't mess with since it checks to see if people are logged in and whether they should be there.
Starting at about line 133 or so is a spot that says:
function main( )
Welcome to the first part of the profile. This is the menu that appears when you click on the "Your Account" link. Here you can add icons to display next to the links, maybe even add another link.
function stats( )
After that begins the user stats section, which is the first area to add potential mods. Do you want to display person's choice for that new field?
The first few lines are all SQL statements that get the person's favorites, so ignore those. Under the include statement that calls timefunctions.php is a bunch of statements that call profile information. You shouldn't have to add anything to those statements.
However, if you added another website field, you should add in the replacement code so it displays properly.
Look closely at the statements until you find a line that begins $website. This line and the one below it are set to check to see if the URL has an http:// in front of it and add it in if it doesn't.
If you want the extra website link to display properly, you're going to have to write a similar statement. But wait! Why write, when you can copy and paste?
Highlight and copy the $website lines and paste them just below the original two lines. Put a couple line breaks above and below it if necessary to keep it separate while you're working on it. Remember to keep the lines intact, including the semi-colons, which tell the server that the statement is over.
TRIVIA: $userinfo is part a php statement (called a "variable") that stores the user information that was called from the Authors table. You can actually safely use it to call user information for display purposes in the stats function as well as viewuser.php. I'll show you the version for the editbio form later in this article.
For the sake of simplicity, pretend you've added a field called "blog" that is intended to store the URL to the user's Weblog. Replace all instances of website with blog.
Next, scroll down to where the results of the stats page is displayed. In php, this is always the output. Once again, find where it says website. Copy, paste, and rename to "blog.
But what if you want to add in the results from another field that doesn't require it to become a link, but just to display the data? That's easy. The format is always ".$userinfo['fieldname']."
What about an extra instant messenger link? Again, fairly easy. Look at the example for MSN.
It displays the icon of the messenger service and then a statement that looks similar to the format I showed you before. Except in this statement, there's a question mark followed by a repeat of that statement, a colon (:), and then _NONE. What this does is say "If they have an MSN contact, display the information." Otherwise, just return "None."
So if we're adding, say, Jabber it would look like this:
<img src=\"images/jabber.gif\" alt=\"Jabber\"> ".($userinfo['jabber'] ? $userinfo['jabber'] : _NONE)."
TRIVIA: Remember that if you're using quotation marks in HTML that has been embedded in php, you must precede each one with a backslash ( \ ) to escape them – meaning you have to tell the script to ignore them. Otherwise, you will get an error.
Let's move on to the editbio function. This controls the actual edit bio AND registration pages, where your users can create, update, and edit their profile information.
function editbio ()
First thing you should notice are lines that look like this:
$betareader = ($_POST['betareader'] == "on" ? 1 : 0);
This controls the yes or no type statements, such as betareader, contact, and favorites alert. This tells the script that when the betareader checkbox is checked, it is "on" equals 1 (yes), "off" equals 0 (no). If you've added a yes or no field, add it in now. As usual, just copy, paste, and rename.
Before you begin adding too many other things in, let's take a look at SQL statements.
SQL statements are basically a simple language that controls your database. In most eFiction mods, we usually only worry about three statements.
SELECT -- just looks up the information, usually to display it at some point.
INSERT -- adds a new record, such as when someone makes a new account.
UPDATE -- updates information that already exists, such as when they update their profile.
To look something up manually you would start with the command "SELECT."
Next, you have to designate what fields you want. You can specify multiple fields by placing a comma between each item.
Finally, use the "FROM" command to specify what table you want data from, ending with a semi-colon to indicate that the statement is complete.
Example:
SELECT uid, penname, bio FROM fanfiction_authors;
Say we want to look up everything in the authors table. We could write all the fields out by hand, but that's too much like work. So… we cheat. ^_^ An asterisk ( * ) tells the database we want the whole thing.
SELECT * FROM fanfiction_authors;
But wait, we're doing this through php rather than by hand. So, we have to create a query in php.
$result = mysql_query("SELECT * FROM fanfiction_authors");
$result stores the data from the SQL statement that asked for all the information.
mysql_query indicates to the script that we're going to use a SQL statement to do something.
We then enclose the SQL statement inside curved brackets and double quotation marks. We then tell the script that that particular section of code is complete with a semi-colon.
That's about the easiest MySQL gets. ^_^ However, we're not looking up information in a query; we want to write it into the database. It's the same principle, just slightly more complicated.
If this were just normal SQL that we were doing by hand we could insert a new record by writing:
INSERT INTO fanfiction_authors VALUES ('1', 'Lazuli', 'Sally', 'email@email.com'
And we'd continue the comma-separated list until we'd filled out the record for my account, and then close it with another ) and then a semicolon ( ; ) just like we did above to look data up.
However, since eFiction is a dynamic script, we have to make certain the values in the script are also dynamic and will add in the data from the form, no matter who is filling it out and when.
Scroll down to line 375 or about, until you see a line that begins:
$query = "INSERT INTO ".$tableprefix."fanfiction_authors
This is your first SQL statement and is set to add new a new record to the authors table when they register.
In order to prevent an error, you must add your field name in the order it appears in within the database or else you might get an error. (This doesn't always happen, but just when you think it's safe putting it out of order an error will come back and bite you in the butt.) Even worse, the wrong data could be written to the wrong field or even be given to the wrong user.
Read through the words that are inside the ( and ) and compare them to the author's table. Notice those are the same as the names of those fields? They're more or less in the same order they appear in the database too.
Next up is the statements that will take the information from the form fields, take out any extras that the database doesn't need or shouldn't have added to it, and add then add the data to the table. Once again, look closely and you'll see the same names as above, more or less in the same order.
Let's dissect one:
'".strip_tags($_POST['AOL'], $allowed_tags)."',
First of all, you have a single quotation mark, then a double, and a period. strip_tags simply removes any HTML tags you don't want the field to contain. Next up is the actions inside the (. First is $_POST, which tells to take the data from the form field marked 'AOL' when they submit the form. Next up is the field name inside two brackets ( [' and '] ). Then a comma, and the $allowed_tags statement, which looks up the tags you allow in your eFiction settings. Then another ), a period, a double quotation mark, single quotation mark, and a comma to set it off from the next item.
To add your own, first remember what field you placed your new field after. Inside the first bunch of statements inside the ( and ), add your's in the appropriate place.
Next, find the corresponding tag and make your new one. Remember that copy and paste is your friend. Just rename the copied code to your new field.
That example was for text/character fields like websites, instant messenger links, biographies, notes, etc. What if you need to add just numbers, like the 0 and 1 yes/no question? Then it becomes even simpler.
Then you just have to enclose it inside two single quotes, then add a $ sign, and your field name. Close it with another single quote and a comma to separate it from the next item. (Remember, we already inserted part of the control at the top of the edit bio function.)
Example:
'$betareader',
And you're done with the INSERT statement. If you did it right, your new field will now be included anytime someone registers to your site.
Now, you have to move on to the UPDATE statements.
Like SELECT and INSERT, UPDATE is simple too.
UPDATE fanfiction_authors SET realname = 'Sally' where uid = "1";
What this just did was search for the person whose UID is 1 and then change (called "set", just like you'd set your clock or wrist watch) their realname to "Sally."
In user.php, there are two of these. One if the password has been changed and one if it hasn't.
The first one begins at approximately line 394:
$query = "UPDATE ".$tableprefix."fanfiction_authors SET
Examine the statement once again and you'll notice that it's the field names again, except in a different format. Look at the way I updated my realname above. Again, since this is a dynamic environment, we have to pull the data from the form.
Here's one separate from the rest:
realname='".strip_tags(addslashes($_POST['realname']),
See the same format as the manual version? But since we're pulling it from the form, we have to add some stuff. First we have to remove any HTML tags using the strip_tags command, then we have to add slashes ( \ ) if necessary to protect any possible quotation marks, apostrophes, or accent marks the field may contain. Then we pull it from the form field marked "realname" when they submit the form.
Easy enough?
Just like the INSERT statement, determine the proper place to put your new field, copy, paste, and rename. Again, numerical values can be simplified, since there's nothing but numbers going in anyway.
Format is just like this: fieldname='$fieldname',
Example:
betareader='$betareader',
The next update statement is almost exact; it just begins a little differently (about line 410):
$update = "UPDATE ".$tableprefix."fanfiction_authors SET
Use the same format as you used for the first update statement.
Now that you've added the SQL statements, you can now play with the form. This is done with HTML that has been embedded into (meaning "it's been mixed with") the PHP.
Now, this is more or less where you have flexibility where you put the field. This works just like your regular HTML form, except for a few minor differences.
Here's the table cell that holds the website field. Notice that any double quotes in the HTML have a \ slash in them. Also notice that the name and value is both set to the same name as the database field. This is what the script will use to pull as well as display the information already stored in the database.
<tr><td colspan=\"2\">"._WEBSITE.": <INPUT type=\"text\" class=\"textbox=\" name=\"website\" value=\"".$user['website']."\" size=\"35\"></td></tr>
TRIVIA: The $user['field_name'] tells the script to pull the value stored in that particular field in the user table and display the data in the corresponding form field if it contains anything. This is what makes your edit bio display your information in the form fields after you've saved your profile.
Here's a checkbox, one of those items that will hold a yes or no answer:
<tr><td colspan=\"2\">"._BETANOTE." <INPUT name=\"betareader\" type=\"checkbox\" class=\"checkbox\"".($user['betareader'] ? " checked" : "")."></td></tr>
Radio buttons are a bit tougher, but not bad. (My Gender mod)
<tr><td colspan=\"2\">"._GENDER.":
<input type=\"radio\" class=\"radio\" value=\"2\" name=\"gender\" ".($user['gender'] == 2 ? " checked" : "")."> "._FEMALE."<input type=\"radio\" class=\"radio\" value=\"1\" ".($user['gender'] == 1 ? " checked" : "")." name=\"gender\"> "._MALE."
<input type=\"radio\" class=\"radio\" value=\"0\" ".($user['gender'] == 0 ? " checked" : "")." name=\"gender\"> "._UNDISCLOSED."
</td></tr>
Radio button number 1 (Female) has a value of 2. If it's checked, put a 2 in the gender field in the database. If radio button number 2 (Male) is checked, put a number 1 in the gender field. Finally, if radio button number 3 (Undisclosed gender) is checked, put a 0 in the gender field.
If you want more options, simply add more in the same format.
Dropdown field is pretty much done in the same way, though there may be minor differences depending on your mod. Simply add options like you would any select form, making sure the name of the select array is the same as your field, and assign a number to each option. The value is the is the same as with the radio box, except instead of "checked" you'd write "selected."
Example: (JanAQs affiliation mod)
<tr><td colspan=\"2\">"._HOUSE." : <SELECT NAME=\"house\">
<OPTION ".($user['house'] == 0 ? " selected" : "").">"._UNSORTED."</option>
<OPTION ".($user['house'] == 1 ? " selected" : "").">"._HUFFLEPUFF."</option>
<OPTION ".($user['house'] == 2 ? " selected" : "").">"._GRYFFINDOR."</option>
<OPTION ".($user['house'] == 3 ? " selected" : "").">"._RAVENCLAW."</option>
<OPTION ".($user['house'] == 4 ? " selected" : "").">"._SLYTHERIN."</option>
</SELECT></td></tr>
If option #1, Unsorted, is selected a 0 will be written to the house field. If option #3 is selected, a 2 will be written to the house field and so on.
So now that your users can update their data, now we have to display it.
Open up viewuser.php and examine the contents. Look near the top, do you see the SQL statement that calls everything stored in the fanfiction_authors table? *grin*
First of all, the easiest way to display something from the database:
$tpl->assign("template_tag", $userinfo['database_field']);
Here, you're assigning a new template variable field that will display a field from the database in plain text. That's fine if you're calling up something that has probably been written to the database in plain text, such as an unlinked instant messenger screenname.
Example:
$tpl->assign("membersince", $userinfo['date']);
That means you can use {membersince} to display the date the person joined your website in your copy of user.tpl.
An extra web site isn't much harder, especially since we've already covered it once before for the stats page. ^_^ As with the stats page, simply copy everything having to do with the website field, paste, and rename to your new field.
An instant messenger field looks like this:
$tpl->assign("template_tag", "<img src=\"images/messenger.gif\" alt=\""._LANGUAGE FILE TAG."\"> ".($userinfo['field'] ? $userinfo['field'] : _NONE));
What this will do is if they have filled out their contact information, it will return their name. Otherwise, it will simply return the word "None"
Example:
$tpl->assign("msn", "<img src=\"images/msntalk.gif\" alt=\""._MSN."\"> ".($userinfo['MSN'] ? $userinfo['MSN'] : _NONE));
A numerical field can be converted to a text answers or even graphics using something like this:
if($userinfo['field'] == 0) $tpl->assign("template_tag", ""._LANGUAGE FILE TAG."");
Or, for an image:
if($userinfo['field'] == 0) $tpl->assign("template_tag", "<img src=\"images/icon.gif\" alt=\""._LANGUAGE FILE TAG."\" title=\""._ LANGUAGE FILE TAG."\">");
Simply repeat for as many options as you've offered, changing the 0 to the number you need.
What about linking a user name to a different website? This only works well right now if the person's user name for that site is actually used as a part of the link. There are ways to work around it, but it may take more work.
Example: (My DeviantArt link)
$tpl->assign("deviant", <img src=\"images/da.gif\" alt=\""._DA."\"> $userinfo['DA'] ? "<a href=\"http://$userinfo['DA'].deviantart.com\" target=\"_blank\" rel=\"nofollow\">$userinfo['DA']</a>" : _NONE);
What this does is pull the person's DeviantArt user name from the database results and inserts it into the link I specified. If there's nothing there, it returns "None."
And there you've have it! Now all you have to do is insert you template variable into user.tpl and your mod is finished.