When projects require several developers (i.e. designers, developers, html coders, etc), they may run into situations where multiple people try to edit the same file at the same time. This could be problematic, since one developer could easily overwrite another's work.
To prevent one person from overwriting another's work, most teams of coders use version control software. Version control software allows multiple people to simultaneously work on the same files while not overwiting each other's work.
Subversion is probably the most popular version control software:
http://subversion.tigris.org/
CVS is an older version control software. Subversion considered to be the better successor to CVS.
http://ximbiot.com/cvs/wiki/
For our intents and purposes, they are equivalent. There are a few simple concepts for using Subversion or CVS:
The Repository
CVS and Subversion use a type of client/server architecture. The permanent location of all files is on the server, in what is called a Repository. The Repository has the current version of all files, as well as all the older versions of the files. It keeps a permanent record of any changes to the project. Clients can always get the latest copy of the files by copying them from the Repository. So developers generally make changes to files on their local machines, and then upload them to the Repository so that other developers can get the lastest version of the files.
The Client
Your local computer runs a Subversion client that automates the common tasks that you will need to do when using version control. The recommended client for Windows is TortoiseSVN. For Mac, you should check out the client recommendations on the subversion site.
Working Copies
When a developer downloads the latest copy of the files from the Repository, they are placed in what is called a Working Copy. This is exactly what it sounds like - a copy of the original files that a developer can use to work. Once a developer has finished working on them, she has to then upload them back to the Repository so other developers can see the changes.
Updating
To get the latest copy of files from the Repository, a developer runs a command called Update. This automatically downloads the latest files from the Repository.
Committing
When a developer has finished making changes to her Working Copy of the files, she first runs the Update command to make sure that nobody else has modified the same files she is about to upload, and then runs a Commit command that automatically uploads the changed files to the Repository.
Conflicts
When two developers have modified the same files at the same time, and then they both Commit their changes, the second developer to commit his changes will experience a Conflict. Usually the work the developers have done is in different parts of the file, so Subversion or CVS can automatically merge the two versions together. However, in some cases Subversion and CVS cannot figure out how to merge the two versions of the file, so it asks one of the developers to manually merge the two. Subversion will show you the difference between the two files, and you can usually easily see what has to be done to get the two versions to merge correctly.
Sunday, November 23, 2008
Reminder: Your Vote Counts
Please remember to vote for what material you want to cover in the next class. If you are viewing this in an RSS reader, you will have to visit my blog home page here in order to vote - the polling widget is on the right side of the page. If you prefer to learn something not included in this poll, add your ideas in the comments section for this post.
Speaking of votes, for something completely unrelated to web development, the PBS website has a vote going on for which short film to show on TV this Saturday. One of the contestants happens to be a film by my brother, so if you're interested, he could use your vote. Voting closes this Tuesday. Click here to watch and vote.
Please note that PBS is using the same Flash media player that I used in my Flash media examples - if you right-click on the videos you will see which media player they are using.
Speaking of votes, for something completely unrelated to web development, the PBS website has a vote going on for which short film to show on TV this Saturday. One of the contestants happens to be a film by my brother, so if you're interested, he could use your vote. Voting closes this Tuesday. Click here to watch and vote.
Please note that PBS is using the same Flash media player that I used in my Flash media examples - if you right-click on the videos you will see which media player they are using.
Overview of PHP/MySQL examples
Class 6 - Basic PHP
- how to put PHP code in your page
- how to define a function in PHP
- how to include one PHP file from another file
- how to pass data from a form to a PHP script
- how to defne arrays in PHP
- how to use phpinfo() to find out how PHP is set up on the server
- how to redirect a user to another page in PHP
- how to prevent the browser from caching a web page
- how to sanitize user data using a popular santization library
- examples of common PHP commands to transform strings
- two examples of how to run system commands from PHP
- how to send an email from a PHP script
- how to upload a file to the server from a form
- how to read and write to files
- how to read and write Cookies
- an example of how to use the file read/write code to create a mailing list
- how to paginate results retrieved from a database
- blog example - how to read and write to a database
- authentication example - how to compare what a user has entered to data stored in a database
- how to parse RSS feeds using the SimplePie library
- how to parse XML data using PHP's built-in XML functions
- how to write object-oriented code in PHP
- how to use PHP Sessions to maintain state between different pages
- an example of an object-oriented social network using sessions, encrypted user passwords, object-oriented santiization of user data, and a clear MVC architecture.
- how to use Flash to play media files using the embed tag
- how to use Flash to play media files using Javascript instead of the embed tag
Saturday, November 22, 2008
Playing Media Files with Flash
To play audio or video files consistently across all the browsers, you will want to use a Flash media player. Flash is the most widely supported application on the web for audio and video files.
There are a variety of Flash media players available online, some free, some not. Here is an example using the freely available JW FLV Media Player, which is the same player used by SimplePie to play podcasts.
The nice thing about the JW FLV Media Player, and other players of its ilk, is that you can relatively easily skin it to make it fit the design of your site.
There are two ways people generally embed Flash players into their XHTML: via the <embed> tag, or using Javascript. This page gives a good overview of the two methods, and the reasons for using the Javascript version.
This example is the same as the first example, but uses the Javascript SWFObject.js library to put the Flash player on the page instead of using the <embed> tag.
There are a variety of Flash media players available online, some free, some not. Here is an example using the freely available JW FLV Media Player, which is the same player used by SimplePie to play podcasts.
The nice thing about the JW FLV Media Player, and other players of its ilk, is that you can relatively easily skin it to make it fit the design of your site.
There are two ways people generally embed Flash players into their XHTML: via the <embed> tag, or using Javascript. This page gives a good overview of the two methods, and the reasons for using the Javascript version.
This example is the same as the first example, but uses the Javascript SWFObject.js library to put the Flash player on the page instead of using the <embed> tag.
Favicons
Favicons are the little icons that show up in the address bar of the web browser for some websites. For example, the favicon for blogger.com is the little orange square with the B in it.

Of course, you will want to create a favicon for your own sites. Favicons are in a special .ico image format that is not natively supported by Photoshop. This article has a good explanation of how to download a Photoshop plugin that lets you save favicons in .ico format using Photoshop.
If you don't have Photoshop, you can still create favicons by using a variety of website services that convert standard .jpg, .gif, or .png image files into .ico format. For example, here is one such site.
To use your favicon once you have created it, make sure the file is named favicon.ico, and put it in the root folder of your website. Then add the following code into the <head> of your XHTML code:
<link rel="shortcut icon" href="./favicon.ico" />
Of course, you will want to create a favicon for your own sites. Favicons are in a special .ico image format that is not natively supported by Photoshop. This article has a good explanation of how to download a Photoshop plugin that lets you save favicons in .ico format using Photoshop.
If you don't have Photoshop, you can still create favicons by using a variety of website services that convert standard .jpg, .gif, or .png image files into .ico format. For example, here is one such site.
To use your favicon once you have created it, make sure the file is named favicon.ico, and put it in the root folder of your website. Then add the following code into the <head> of your XHTML code:
<link rel="shortcut icon" href="./favicon.ico" />
Monday, November 17, 2008
Photoshop Alternatives
Saturday, November 15, 2008
Class 9 - In-Class Assignment
Your assignment from class 7 was to make an image uploading service. Hopefully you have completed that assignment.
Your in-class-assignment for this class is to publish an RSS feed for that site. Now that you are familiar with the concept of an MVC architecture, you will realize that if your site is set up in an MVC style, you will easily be able to apply different Views to the same data.
So your image uploading service will have two views: one in XHTML for web browsers, and another in RSS for RSS feed readers. I have retrofitted the blog example from class 8 so that it now has both an XHTML and an RSS view. Obviously this should be your reference for this assignment.
Additionally, your XHTML view will have a link tag that tells an RSS reader, like Google Reader, Esprsso, or NetVibes, where to find the rss version of your site.
The link tag syntax for RSS feeds is:
<link rel="alternate" type="application/rss+xml" title="NY Times RSS Feed" href="http://nytimes.com/HomePage.xml" />
Any site that has an RSS feed specified in the link tag will show the orange rss icon in the right side of the location bar of your Firefox browser. Clicking that icon will bring you to the RSS feed in Firefox.
Your in-class-assignment for this class is to publish an RSS feed for that site. Now that you are familiar with the concept of an MVC architecture, you will realize that if your site is set up in an MVC style, you will easily be able to apply different Views to the same data.
So your image uploading service will have two views: one in XHTML for web browsers, and another in RSS for RSS feed readers. I have retrofitted the blog example from class 8 so that it now has both an XHTML and an RSS view. Obviously this should be your reference for this assignment.
Additionally, your XHTML view will have a link tag that tells an RSS reader, like Google Reader, Esprsso, or NetVibes, where to find the rss version of your site.
The link tag syntax for RSS feeds is:
<link rel="alternate" type="application/rss+xml" title="NY Times RSS Feed" href="http://nytimes.com/HomePage.xml" />
Any site that has an RSS feed specified in the link tag will show the orange rss icon in the right side of the location bar of your Firefox browser. Clicking that icon will bring you to the RSS feed in Firefox.
SimplePie: an RSS Parser Library for PHP
In class, we've seen an example of how you can use the SimplePie PHP library to pull content from any site's RSS feed and display it on your own pages.
In this example, SimplePie is acting as the Model in our MVC architecture. index.php is theController, and index_view.php is the View.
In the example files, you will notice that there is a folder called "cache". This is where SimplePie temporarily stores copies of the RSS feeds that you load. It keeps each cached copy of the RSS feed for several minutes, so that if you reload your page, it doesn't have to always reload the same data from the site that publishes the RSS feed.
In fact, some sites will ban your site from accessing their RSS feeds forever unless you store cached copies of their feeds. This is because they want to minimize the number of requests that are made to their servers. SimplePie does this by default if you have a "cache" folder available.
So if you use SimplePie, you will need to make sure you have the simplepie.inc file (which holds the main SimplePie code), the cache folder (which stores cached copies of all RSS feeds), and the idn folder (which holds other misc SimplePie files).
In this example, SimplePie is acting as the Model in our MVC architecture. index.php is theController, and index_view.php is the View.
In the example files, you will notice that there is a folder called "cache". This is where SimplePie temporarily stores copies of the RSS feeds that you load. It keeps each cached copy of the RSS feed for several minutes, so that if you reload your page, it doesn't have to always reload the same data from the site that publishes the RSS feed.
In fact, some sites will ban your site from accessing their RSS feeds forever unless you store cached copies of their feeds. This is because they want to minimize the number of requests that are made to their servers. SimplePie does this by default if you have a "cache" folder available.
So if you use SimplePie, you will need to make sure you have the simplepie.inc file (which holds the main SimplePie code), the cache folder (which stores cached copies of all RSS feeds), and the idn folder (which holds other misc SimplePie files).
Monday, November 10, 2008
Sanitizing User Input
We've discussed the need to sanitize any user-generated data before storing it in your database. This is primarily necessary to make sure users don't accidentally or intentionally wipe out your entire database with a variety of database hacks. But it's also useful to prevent users from trying a variety of other nuisance attacks or hacks, such as putting HTML or Javascript code where it doesn't belong on your site.
The sanitization of data we have seen in class so far is really the bare minimum necessary to protect your database from the most obvious attacks. However, to more thoroughly protect your database, you can use libraries created by security experts that offer a stronger level of protection.
Here is an example of a page that uses one such sanitization script. As with many 3rd party libraries, we don't have to fully understand how this sanitization script works, but we need to know how to use it.
This example has three files: index.php, process_sanitize.php, and sanitize.inc.php
index.php is just an HTML form, where users can enter data. The data a user enters is then submitted to process_sanitize.php
process_sanitize.php then takes this data and sanitizes it. It does so by including the sanitize.inc.php file, and calling a function, sanitize() that is defined therein.
sanitize() takes two parameters: the data to sanitize, and flags that indicate what level of sanitization you want.
The possible flags are: PARANOID, SQL, SYSTEM, HTML, INT, FLOAT, LDAP, UTF8. Because of the smart way these flags are defined by this PHP library, you can combine multiple flags by adding them together, for example SQL + HTML. This would strip out all SQL and HTML commands that a user might try to put into your database. The PARANOID flag is a combination of all the other flags.
Rather than creating your own sanitization scripts, you can include sanitize.inc.php into your own scripts and use it to sanitize your users' data.
The sanitization of data we have seen in class so far is really the bare minimum necessary to protect your database from the most obvious attacks. However, to more thoroughly protect your database, you can use libraries created by security experts that offer a stronger level of protection.
Here is an example of a page that uses one such sanitization script. As with many 3rd party libraries, we don't have to fully understand how this sanitization script works, but we need to know how to use it.
This example has three files: index.php, process_sanitize.php, and sanitize.inc.php
index.php is just an HTML form, where users can enter data. The data a user enters is then submitted to process_sanitize.php
process_sanitize.php then takes this data and sanitizes it. It does so by including the sanitize.inc.php file, and calling a function, sanitize() that is defined therein.
sanitize() takes two parameters: the data to sanitize, and flags that indicate what level of sanitization you want.
The possible flags are: PARANOID, SQL, SYSTEM, HTML, INT, FLOAT, LDAP, UTF8. Because of the smart way these flags are defined by this PHP library, you can combine multiple flags by adding them together, for example SQL + HTML. This would strip out all SQL and HTML commands that a user might try to put into your database. The PARANOID flag is a combination of all the other flags.
Rather than creating your own sanitization scripts, you can include sanitize.inc.php into your own scripts and use it to sanitize your users' data.
Sunday, November 9, 2008
Homework Assignment
This week, there are 3 homework assignments:
1) Finish the Class 8 - In-Class Assignment. Additionally, you should add authentication so that users have to log-in in order to create blog posts and comments. New users must be able to register, and their username and password should be stored in a database table. Each blog post or comment should show the username of the user who posted it.
2) Read the MySQL tutorial
3) Decide what you will be doing for your Final Project. Post your idea to your blog.
...
4) And if you haven't already finished the Class 7 - In-Class Assignment, please do so. Wireframes are here.
1) Finish the Class 8 - In-Class Assignment. Additionally, you should add authentication so that users have to log-in in order to create blog posts and comments. New users must be able to register, and their username and password should be stored in a database table. Each blog post or comment should show the username of the user who posted it.
2) Read the MySQL tutorial
3) Decide what you will be doing for your Final Project. Post your idea to your blog.
...
4) And if you haven't already finished the Class 7 - In-Class Assignment, please do so. Wireframes are here.
Saturday, November 8, 2008
Final Project Requirements
DEADLINE
*All final projects must be completed by the last day of class (December 13).
*This means you have approximately 5 weeks to complete your projects.
REQUIREMENTS
*Final projects must show your mastery of the technologies we have learned in this class: XHTML, CSS, Javascript, PHP, and MySQL.
*Final projects must be completely information architected before you start programming.
*Projects must involve at least 3 distinct web pages.
*You will be required to present your site to the class on December 13
*All filenames must be lowercase with no spaces or special characters
*All variable names in PHP and Javascript must be written in camelCase.
*All CSS class names and IDs must be written in lowercase.
*Final projects must be accessible and working on the web, and must be linked to from your blog.
GRADING
*Grades will be loosely based on your ability to exhibit mastery of Information Architecture and programming techniques.
Information Architecture (20%)
Programming (50%)
Ability to conceptualize and realize a fully-functioning, well thought-out site (30%)
PRESENTATIONS
*You will be required to present your work to the class on December 13th.
*Presentations should be no more than 10 minutes
*Questions to answer in your presentation:
-Who are you, and what is your background?
-What's the purpose of your site and why did you decide to build it?
-Show your information architecture diagrams. Why did you choose this particular navigation structure and why did you place the various bits of information where you did in the wireframes?
-Show your completed site. What do you think works and what doesn't?
-What are problems you had, solutions you arrived at (or didn't), and any other issues you encountered when building the site?
-Is the site a good representation of what you had originally planned?
-What are your plans for the site (if any) once the class is over?
-What are your plans (if any) for continuing on with web development in the future?
-What did you or didn't you learn in this class that you had originally wanted to learn?
*All final projects must be completed by the last day of class (December 13).
*This means you have approximately 5 weeks to complete your projects.
REQUIREMENTS
*Final projects must show your mastery of the technologies we have learned in this class: XHTML, CSS, Javascript, PHP, and MySQL.
*Final projects must be completely information architected before you start programming.
*Projects must involve at least 3 distinct web pages.
*You will be required to present your site to the class on December 13
*All filenames must be lowercase with no spaces or special characters
*All variable names in PHP and Javascript must be written in camelCase.
*All CSS class names and IDs must be written in lowercase.
*Final projects must be accessible and working on the web, and must be linked to from your blog.
GRADING
*Grades will be loosely based on your ability to exhibit mastery of Information Architecture and programming techniques.
Information Architecture (20%)
Programming (50%)
Ability to conceptualize and realize a fully-functioning, well thought-out site (30%)
PRESENTATIONS
*You will be required to present your work to the class on December 13th.
*Presentations should be no more than 10 minutes
*Questions to answer in your presentation:
-Who are you, and what is your background?
-What's the purpose of your site and why did you decide to build it?
-Show your information architecture diagrams. Why did you choose this particular navigation structure and why did you place the various bits of information where you did in the wireframes?
-Show your completed site. What do you think works and what doesn't?
-What are problems you had, solutions you arrived at (or didn't), and any other issues you encountered when building the site?
-Is the site a good representation of what you had originally planned?
-What are your plans for the site (if any) once the class is over?
-What are your plans (if any) for continuing on with web development in the future?
-What did you or didn't you learn in this class that you had originally wanted to learn?
PHP Sessions - Maintaining State
In your readings, you may have come across mention of PHP Sessions. Sessions are another mechanism, in addition to GET, POST, and COOKIE parameters that allow you to "maintain state", meaning to pass data from one page to another.
PHP provides a set of functions that allow you to create Session variables. These are variables that are stored on the server, and last for a limited amount of time. They are very similar to Cookies, and in fact PHP does use Cookies to perform some of the tasks involved with Sessions. But PHP hides the internals of how Sessions work, so all you need to do is set the Session variables, and PHP handles the rest.
Here are some pages that cover sessions, and explain how to write PHP code to deal with them:
http://php.about.com/od/advancedphp/ss/php_sessions.htm
http://www.tizag.com/phpT/phpsessions.php
http://www.htmlgoodies.com/beyond/php/article.php/3472581
http://us3.php.net/session
PHP provides a set of functions that allow you to create Session variables. These are variables that are stored on the server, and last for a limited amount of time. They are very similar to Cookies, and in fact PHP does use Cookies to perform some of the tasks involved with Sessions. But PHP hides the internals of how Sessions work, so all you need to do is set the Session variables, and PHP handles the rest.
Here are some pages that cover sessions, and explain how to write PHP code to deal with them:
http://php.about.com/od/advancedphp/ss/php_sessions.htm
http://www.tizag.com/phpT/phpsessions.php
http://www.htmlgoodies.com/beyond/php/article.php/3472581
http://us3.php.net/session
Hint for Class 8 - In-Class Assignment
By now, you're wondering "Where in my code should I retrieve all the comments associated with each blog post?"
Good question. What I recommend is first of all you make a separate Model file for your comments. This will have functions to do all the database CRUD operations, just like the Model for the blog posts does for blog posts.
Just as the blog post Model has a getAllPosts() function, your comment Model will have a getAllComments() function. But unlike the getAllPosts() function, your getAllComments() function will take one parameter: the id of the blog post for which you want to retrieve the comments.
In other words, the function definition will start out like this:
This function will get all comments associated with the blog post that you specify in $blogPostId. I'll leave it up to you to figure out what the exact MySQL query is that will get those results. But what I recommend is that you return an array of all the comments as the return value for that function.
Then, you will have to call that function from somewhere. The easiest thing is to do that in the View that displays the blog posts.
In your blog View, you have code like this:
This code is looping through each blog post and displaying it, so it's the perfect place to add some code to get the comments for the current blog post and display them. So I would do something like this:
This gets an array of all the comments for each blog post, and then loops through each element of that array. So inside that foreach statement where you are looping through all the comments, you put the code to display the comments.
Good question. What I recommend is first of all you make a separate Model file for your comments. This will have functions to do all the database CRUD operations, just like the Model for the blog posts does for blog posts.
Just as the blog post Model has a getAllPosts() function, your comment Model will have a getAllComments() function. But unlike the getAllPosts() function, your getAllComments() function will take one parameter: the id of the blog post for which you want to retrieve the comments.
In other words, the function definition will start out like this:
...
function getAllComments($blogPostId) { ... }
...
This function will get all comments associated with the blog post that you specify in $blogPostId. I'll leave it up to you to figure out what the exact MySQL query is that will get those results. But what I recommend is that you return an array of all the comments as the return value for that function.
Then, you will have to call that function from somewhere. The easiest thing is to do that in the View that displays the blog posts.
In your blog View, you have code like this:
<?php foreach ($posts as $post) : ?>
...
<?php endforeach ?>
This code is looping through each blog post and displaying it, so it's the perfect place to add some code to get the comments for the current blog post and display them. So I would do something like this:
<?php foreach ($posts as $post) : ?>
...
<?php foreach (getAllComments($post['id']) as $comment) : ?>
...
<?php endforeach ?>
...
<?php endforeach ?>
This gets an array of all the comments for each blog post, and then loops through each element of that array. So inside that foreach statement where you are looping through all the comments, you put the code to display the comments.
Debugging MySQL
There are two very easy ways to debug your MySQL queries. If you are trying to do a MySQL query and it isn't working, you will want to try these:
1) If you are trying to create queries dynamically by inserting PHP variables into your MySQL queries, such as
$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
$result = mysql_query($myQuery);
where $blogPostId is a PHP variable you are trying to insert into your MySQL statement, make sure that the variable has the value you think it does. You can easily check this by printing out that whole statement to the browser.
$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
echo $mQuery; //print what this query really looks like after the variable is inserted
$result = mysql_query($myQuery);
If the query shows up as "select * from blogcomments where blogpost_id= order by created asc", you now know that the $blogPostId variable is empty.
2) use PHP's mysql_error() function to display any errors thrown by MySQL after you run the query:
$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
$result = mysql_query($myQuery);
echo mysql_error(); //print out any errors thrown by MySQL
1) If you are trying to create queries dynamically by inserting PHP variables into your MySQL queries, such as
$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
$result = mysql_query($myQuery);
where $blogPostId is a PHP variable you are trying to insert into your MySQL statement, make sure that the variable has the value you think it does. You can easily check this by printing out that whole statement to the browser.
$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
echo $mQuery; //print what this query really looks like after the variable is inserted
$result = mysql_query($myQuery);
If the query shows up as "select * from blogcomments where blogpost_id= order by created asc", you now know that the $blogPostId variable is empty.
2) use PHP's mysql_error() function to display any errors thrown by MySQL after you run the query:
$myQuery = "select * from blogcomments where blogpost_id={$blogPostId} order by created asc";
$result = mysql_query($myQuery);
echo mysql_error(); //print out any errors thrown by MySQL
Making Timestamps User-Friendly
When we set our MySQL tables to have a "created" field of the type TIMESTAMP with the CURRENT_TIMESTAMP option selected, this records the exact date and time that each row is created in the table.
The format that MySQL uses to record this data is "YYYY-MM-DD HH:MM:SS". However, this is not usually the format that you want to use to display the data on the web page. It's not so easy to read, and definitely is not how most people think of dates.
In order to convert the MySQL TIMESTAMP to a more user-friendly date format, you want to use PHP's built-in date() function. However, PHP's date() function only allows you to change the format of dates that are in Unix Timestamp, which is significantly different from MySQL's TIMESTAMP format.
So, in order to get PHP's date() function to work with MySQL's TIMESTAMP, you first have to convert MySQL's TIMESTAMP format to Unix Timestamp format. To do that, you use PHP's strtotime() function.
Here's the code that does this, from my blog example:
<p>posted <?= date("F j, Y, g:ia", strtotime($post['created'])) ?></p>
This displays on the page as, for example, "posted November 8, 2008, 12:19pm". You can use the date() function to format the date in a wide variety of other formats.
The format that MySQL uses to record this data is "YYYY-MM-DD HH:MM:SS". However, this is not usually the format that you want to use to display the data on the web page. It's not so easy to read, and definitely is not how most people think of dates.
In order to convert the MySQL TIMESTAMP to a more user-friendly date format, you want to use PHP's built-in date() function. However, PHP's date() function only allows you to change the format of dates that are in Unix Timestamp, which is significantly different from MySQL's TIMESTAMP format.
So, in order to get PHP's date() function to work with MySQL's TIMESTAMP, you first have to convert MySQL's TIMESTAMP format to Unix Timestamp format. To do that, you use PHP's strtotime() function.
Here's the code that does this, from my blog example:
<p>posted <?= date("F j, Y, g:ia", strtotime($post['created'])) ?></p>
This displays on the page as, for example, "posted November 8, 2008, 12:19pm". You can use the date() function to format the date in a wide variety of other formats.
Class 8 - In-Class Assignment
Your assignment is to take the blog example we went over in class, and allow users to add comments to any blog post.
To do this, you will have to first create database tables to hold all the data. You will need a database table for blog posts, and one for blog comments. For this exercise, you can copy the the database tables that I have set up already for the example.
Your blogposts table should have the following structure:

And your blogcomments table should have the following structure:

As with all tables you will create in this class, these two have both an "id" and a "created" field. The "id" field should be the Primary Key, and should be type INT, and make sure it is set to Auto-Increment. The "created" field will be a TIMESTAMP type, and should be set to have the "Current Timestamp".
You will notice that the blogcomments table has a "blogpost_id" field, which is a foreign key that points to the primary key (i.e. the "id" field) of the blogposts table. So If you have a comment that is supposed to be associated with blogpost #5, this "blogpost_id" field will have the number 5 in it for that row in the blogcomments table. That's how you know it is supposed to be associated with blogpost #5.
So for each blog post, you will load all the comments from the blogcomments table where "blogpost_id" is equal to the "id" field of the current blog post. This is the main idea behind relational databases, such as MySQL.
Here is a wireframe of approximately how the page should look:
To do this, you will have to first create database tables to hold all the data. You will need a database table for blog posts, and one for blog comments. For this exercise, you can copy the the database tables that I have set up already for the example.
Your blogposts table should have the following structure:

And your blogcomments table should have the following structure:

As with all tables you will create in this class, these two have both an "id" and a "created" field. The "id" field should be the Primary Key, and should be type INT, and make sure it is set to Auto-Increment. The "created" field will be a TIMESTAMP type, and should be set to have the "Current Timestamp".
You will notice that the blogcomments table has a "blogpost_id" field, which is a foreign key that points to the primary key (i.e. the "id" field) of the blogposts table. So If you have a comment that is supposed to be associated with blogpost #5, this "blogpost_id" field will have the number 5 in it for that row in the blogcomments table. That's how you know it is supposed to be associated with blogpost #5.
So for each blog post, you will load all the comments from the blogcomments table where "blogpost_id" is equal to the "id" field of the current blog post. This is the main idea behind relational databases, such as MySQL.
Here is a wireframe of approximately how the page should look:
MySQL Tutorial
Please go through this MySQL Tutorial:
http://www.tizag.com/mysqlTutorial/
Bear in mind that we are using phpMyAdmin to set up and administer our databases.
http://www.tizag.com/mysqlTutorial/
Bear in mind that we are using phpMyAdmin to set up and administer our databases.
MVC Architecture
Today we talked about the MVC Architecture, which is a design pattern that nicely separates database operations, logic, and presentation into separate components.
In our blog example, we saw how the blog Model code had separate functions for each CRUD operation. By keeping all direct interaction with the MySQL database in the blog Model, we can separate it from the business logic, contained in the Controller, that determines what to do for each page. This makes our code cleaner, easier to read, and easier to maintain if. If, for example, we decide to change the structure of our database tables, we only have to modify the code in the Model.
Once the Controller has determined what to do on any page, it fetches the appropriate data from the Model, and sends that data to the View, which has all the XHTML code necessary to display the page properly.
One of the nice things about common PHP Frameworks is that they offer clear MVC architecture. For example, I've been using Symfony recently, which forces my code to adhere to strict MVC principles.
In our blog example, we saw how the blog Model code had separate functions for each CRUD operation. By keeping all direct interaction with the MySQL database in the blog Model, we can separate it from the business logic, contained in the Controller, that determines what to do for each page. This makes our code cleaner, easier to read, and easier to maintain if. If, for example, we decide to change the structure of our database tables, we only have to modify the code in the Model.
Once the Controller has determined what to do on any page, it fetches the appropriate data from the Model, and sends that data to the View, which has all the XHTML code necessary to display the page properly.
One of the nice things about common PHP Frameworks is that they offer clear MVC architecture. For example, I've been using Symfony recently, which forces my code to adhere to strict MVC principles.
Sunday, November 2, 2008
No Class November 29th
There will be no class on November 29th due to the Thanksgiving holiday break. The syllabus is incorrect.
Cookies - Reading, Writing, and Deleting
Here's a decent page about reading, writing, and deleting cookies in PHP:
http://www.w3schools.com/PHP/php_cookies.asp
http://www.w3schools.com/PHP/php_cookies.asp
Saturday, November 1, 2008
File Permissions
Most servers have settings that prevent just anyone from uploading or modifying files on the server. If everyone was allowed to edit every file, the server would have a serious security issue.
However, when you are making a website that allows people to upload files to your server, or to append data to an existing file, you need to make sure that the server knows to allow anyone to do that. Usually, when allowing file uploads, you set aside a particular sub-directory that anyone can modify.
For example, in the upload example we went over in class where users can upload images to the server, we allowed them to put the images into a directory called "files". This directory needs to have permissions settings that allow anyone to write to it. In another example we went over in class, when users save their Contact info into a text file, we need to make sure that text file has the proper permissions settings to allow that.
The easiest way to do this is to use WinSCP or some other file transfer program to set the permissions. In WinSCP, you can right-click on any file or folder on the server, and click "Properties". This pops up a dialog that allows you to modify the permissions settings for that file or folder.
Make sure that the folder where users can upload files on your server has Write permissions for both the Owner of the folder and Others.
However, when you are making a website that allows people to upload files to your server, or to append data to an existing file, you need to make sure that the server knows to allow anyone to do that. Usually, when allowing file uploads, you set aside a particular sub-directory that anyone can modify.
For example, in the upload example we went over in class where users can upload images to the server, we allowed them to put the images into a directory called "files". This directory needs to have permissions settings that allow anyone to write to it. In another example we went over in class, when users save their Contact info into a text file, we need to make sure that text file has the proper permissions settings to allow that.
The easiest way to do this is to use WinSCP or some other file transfer program to set the permissions. In WinSCP, you can right-click on any file or folder on the server, and click "Properties". This pops up a dialog that allows you to modify the permissions settings for that file or folder.
Make sure that the folder where users can upload files on your server has Write permissions for both the Owner of the folder and Others.
Class 7 In-Class Assignment
Your job is to make an image-uploading service. Users of the service can upload images that then show up on the site home page. The home page should show the latest 50 images that have been uploaded.
Users have to log in to see your site. If they are not logged in, they are redirected to the login page.
-this means you need a sign-up page that allows users to register with username/password
The home page displays a list of the 50 latest images that were uploaded
-all images should show the image, a one-line caption, and the username of the user who uploaded it
Here is a step by step breakdown of the tasks that you have to accomplish in order to get this to work:
LOGIN PAGE
-if the user is already logged in, they are redirected to the home page
-otherwise...
-show one text input for username
-show one password input for password
-and a submit button
-this page submits data to a script that checks the login info
SCRIPT TO CHECK THE LOGIN INFO
-receive the data the user entered from the Login Page
-open the users.txt file and see if there are any rows in that file that match the username/password the user entered
-if there is a match, you set a cookie called "loggedin" and set it equal to "true", and then redirect them to the home page
-otherwise, if the login failed, you redirect them to the login page with a user-friendly error message
HOME PAGE
-checks to see if the "loggedin" cookie is equal to "true"
-if it is, you let them see the page
-if it's not, you redirect them to the login page, and show a user-friendly error message
-if they are logged in, you open the "images.txt" file, and load all the data in there
-loop through each line of the text file, and get the image filename, caption, and username associated with that image
-display each image with the caption underneath it along with the username of the user who uploaded that image
UPLOAD PAGE
-users must be logged in to see this page, otherwise they are redirected to the login page with a user-friendly error message
-has a file input for the file the user wants to upload
-has a text input for the caption
-you have to figure out how to get and store the username of the user who is uploading this file
-submits the data to a script called process_upload_image.php that does the actual uploading and storing of the data
PROCESS_UPLOAD_IMAGE.PHP SCRIPT
-checks to make sure the "loggedin" cookie is equal to "true"
-if the user is not logged in, they are redirected to the login page with a user-friendly error
-if they are logged in....
-this script receives the caption and file that the user uploaded
-this script moves that image file to a permanent directory
-you need to make sure you have a variable that stores the path of the where the file was moved to
-this script needs to store the caption, image file path, and username to a text file called "images.txt"
-each new uploaded image will create a new line in the text file
-if there is an error uploading, this page shows a nice user-friendly error message
-if the upload succeeds, it redirects them to the home page with a user-friendly error indicating that their upload succeeded
Users have to log in to see your site. If they are not logged in, they are redirected to the login page.
-this means you need a sign-up page that allows users to register with username/password
The home page displays a list of the 50 latest images that were uploaded
-all images should show the image, a one-line caption, and the username of the user who uploaded it
Here is a step by step breakdown of the tasks that you have to accomplish in order to get this to work:
LOGIN PAGE
-if the user is already logged in, they are redirected to the home page
-otherwise...
-show one text input for username
-show one password input for password
-and a submit button
-this page submits data to a script that checks the login info
SCRIPT TO CHECK THE LOGIN INFO
-receive the data the user entered from the Login Page
-open the users.txt file and see if there are any rows in that file that match the username/password the user entered
-if there is a match, you set a cookie called "loggedin" and set it equal to "true", and then redirect them to the home page
-otherwise, if the login failed, you redirect them to the login page with a user-friendly error message
HOME PAGE
-checks to see if the "loggedin" cookie is equal to "true"
-if it is, you let them see the page
-if it's not, you redirect them to the login page, and show a user-friendly error message
-if they are logged in, you open the "images.txt" file, and load all the data in there
-loop through each line of the text file, and get the image filename, caption, and username associated with that image
-display each image with the caption underneath it along with the username of the user who uploaded that image
UPLOAD PAGE
-users must be logged in to see this page, otherwise they are redirected to the login page with a user-friendly error message
-has a file input for the file the user wants to upload
-has a text input for the caption
-you have to figure out how to get and store the username of the user who is uploading this file
-submits the data to a script called process_upload_image.php that does the actual uploading and storing of the data
PROCESS_UPLOAD_IMAGE.PHP SCRIPT
-checks to make sure the "loggedin" cookie is equal to "true"
-if the user is not logged in, they are redirected to the login page with a user-friendly error
-if they are logged in....
-this script receives the caption and file that the user uploaded
-this script moves that image file to a permanent directory
-you need to make sure you have a variable that stores the path of the where the file was moved to
-this script needs to store the caption, image file path, and username to a text file called "images.txt"
-each new uploaded image will create a new line in the text file
-if there is an error uploading, this page shows a nice user-friendly error message
-if the upload succeeds, it redirects them to the home page with a user-friendly error indicating that their upload succeeded
Subscribe to:
Posts (Atom)