a_simple_php_sqlite_download_counter
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
a_simple_php_sqlite_download_counter [2020/06/27 19:59] – waxphilosophic | a_simple_php_sqlite_download_counter [2024/08/31 19:27] (current) – %%h hc9 | ||
---|---|---|---|
Line 3: | Line 3: | ||
===== Summary ===== | ===== Summary ===== | ||
- | If you host downloadable content on SDF, you may want to get an idea of how many people have downloaded things and which are the most popular. In this tutorial, I will focus on an example of tracking PDF formatted ebooks. After completing this tutorial, you should be able to modify things to suit your needs, even if your downloads are not ebooks. You will need to have PHP access to do this, so check your membership level before you get started. | + | If you host downloadable |
===== The Download Script ===== | ===== The Download Script ===== | ||
Line 49: | Line 49: | ||
</ | </ | ||
- | + | ===== Explanation of Parts ===== | |
+ | |||
+ | For a better understanding of how this works, I'll dissect the parts of the script one by one and explain each bit. | ||
+ | |||
+ | ==== Where to Find the Files ==== | ||
+ | |||
+ | First, there is the '' | ||
+ | |||
+ | < | ||
+ | // Set the location holding the download content. | ||
+ | $content_dir = basename(__FILE__) . "/ | ||
+ | </ | ||
+ | |||
+ | This needs to be set to where the downloadable files are kept. The way things are set up by default assumes you have a directory hierarchy that looks like this: | ||
+ | |||
+ | < | ||
+ | html/ | ||
+ | |-- download.php | ||
+ | |-- download/ | ||
+ | |-- ebook.pdf | ||
+ | </ | ||
+ | |||
+ | In other words, your downloadable content is all kept in a directory called download and it is a subdirectory residing next to the download.php script we're putting together. | ||
+ | |||
+ | < | ||
+ | |||
+ | __FILE__ in PHP means the filesystem path to the PHP script being executed. This is not the URL path, but the filesystem path. So it will not be '' | ||
+ | |||
+ | So now you know where to store you content and what to change if it's located somewhere else. | ||
+ | |||
+ | ==== Knowing What Was Requested ==== | ||
+ | |||
+ | Next, there is the section that decodes the query string. | ||
+ | |||
+ | < | ||
+ | // The query string passed indicates the filename. | ||
+ | if (isset($_SERVER[' | ||
+ | $file = rawurldecode($_SERVER[' | ||
+ | $path = $content_dir . DIRECTORY_SEPARATOR . $file; | ||
+ | </ | ||
+ | |||
+ | Inside your HTML, you might have a hyperlink that looks like this: '' | ||
+ | |||
+ | To use the download counter, the link needs to look like this: '' | ||
+ | |||
+ | With the new format, each hyperlink will call the download.php script and pass the name of the desired file as a query string. The PHP variable '' | ||
+ | |||
+ | You may have also noticed the '' | ||
+ | |||
+ | If you have an ebook called '' | ||
+ | |||
+ | The %20 is a URL safe encoding of the space character. Guess what '' | ||
+ | |||
+ | ==== Delivering the file ==== | ||
+ | |||
+ | Now that we know what file the user wants, it's time to send it to their browser. That's what the next section of code is for. | ||
+ | |||
+ | < | ||
+ | // Deliver the file if it exists, otherwise error. | ||
+ | if (file_exists($path)) { | ||
+ | header(" | ||
+ | header(" | ||
+ | header(" | ||
+ | echo file_get_contents($path); | ||
+ | </ | ||
+ | |||
+ | The first thing it will do is to check to make sure the file actually exists. If there' | ||
+ | |||
+ | The script delivers three HTTP headers to let the user's browser know what's coming. | ||
+ | |||
+ | The first is the content type (aka MIME type.) I mentioned that I use this script for PDF ebooks, so my content type is hard coded to '' | ||
+ | |||
+ | If you are delivering more than one type of file, you could use an associative array to choose the content-type based on file extension. This is beyond the scope of the tutorial. | ||
+ | |||
+ | The next HTTP header tells the browser and any proxy servers in between, not to cache the content. | ||
+ | |||
+ | Finally, we have some specifics about the actual file. | ||
+ | |||
+ | One being that it should be displayed inline. (The alternative is having the browser prompt to save.) I use inline because most browsers have a PDF reader built in and it's less jarring to the user to have everything appear in the same window. | ||
+ | |||
+ | The other is the filename. This is a courtesy to the user and will pre-fill any save dialog with the filename if they choose to save it. | ||
+ | |||
+ | ==== Recording the Download ==== | ||
+ | |||
+ | The next bit of code is where we get down to the business of making a tally in the database about what was downloaded and when. | ||
+ | |||
+ | < | ||
+ | // Record the download in the hit count database. | ||
+ | $pdo = new PDO(" | ||
+ | if ($pdo) { | ||
+ | $create = " | ||
+ | $pdo-> | ||
+ | $insert = " | ||
+ | $prepared_sql = $pdo-> | ||
+ | $prepared_sql-> | ||
+ | $prepared_sql-> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The "hit counter" | ||
+ | |||
+ | The first step is to create a PDO object that we can use. A nice feature of this is that the backing file '' | ||
+ | |||
+ | This is further enhanced by the first SQL statement. '' | ||
+ | |||
+ | Finally, there is a SQL insert using a prepared statement. It will insert a new row with a date-time stamp and the name of the file that was downloaded. This lets you see what is downloaded and when it was downloaded. | ||
+ | |||
+ | ==== Handling Errors ==== | ||
+ | |||
+ | There' | ||
+ | |||
+ | < | ||
+ | else { | ||
+ | http_response_code(404); | ||
+ | header(" | ||
+ | header(" | ||
+ | echo "404: Not Found"; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This last little bit is associated with the earlier '' | ||
+ | |||
+ | ===== Counting Your Downloads ===== | ||
+ | |||
+ | There' | ||
+ | |||
+ | ==== SQLite3 on Command-Line ==== | ||
+ | |||
+ | If you want to query the database directly, simply use the command '' | ||
+ | |||
+ | This will give you everything downloaded in date order. | ||
+ | |||
+ | ==== A PHP/SQLite Script ==== | ||
+ | |||
+ | If you want to get a little fancier, the following PHP script will do the query for you and show not only downloads by date, but also give an indication of the most popular files based on total number downloaded. I won't go into detail on how it works. If you understand the download.php script, this one will be easy. | ||
+ | |||
+ | < | ||
+ | <?php | ||
+ | $dbfile = " | ||
+ | |||
+ | header(" | ||
+ | if (file_exists($dbfile)) { | ||
+ | $pdo = new PDO(" | ||
+ | if ($pdo) { | ||
+ | echo " | ||
+ | echo " | ||
+ | $sql = " | ||
+ | foreach ($pdo-> | ||
+ | printf(" | ||
+ | } | ||
+ | echo " ----\n"; | ||
+ | $sql = " | ||
+ | printf(" | ||
+ | |||
+ | echo " | ||
+ | echo " | ||
+ | $sql = " | ||
+ | foreach ($pdo-> | ||
+ | printf(" | ||
+ | } | ||
+ | } | ||
+ | else { | ||
+ | echo " | ||
+ | } | ||
+ | } | ||
+ | else { | ||
+ | echo " | ||
+ | } | ||
+ | ?> | ||
+ | </ | ||
+ | |||
+ | ===== Database Management ===== | ||
+ | |||
+ | The more downloads there are from your site, the more the download.sl3 file will grow. My assumptions have always been for a low volume of traffic and we're not storing a ton of information. My experience with tracking my own downloads is that I only need to prune one or two times a year. Most of that is removing ebook titles that I have removed. | ||
+ | |||
+ | There is no fancy PHP page for database pruning. It can be done with the '' | ||
+ | |||
+ | SQLite also has the advantage that it will assign each row an index number. This is normally hidden from queries, but can be seen with the statement, " | ||
+ | |||
+ | Even if you're not a SQL expert, you can prune by simply picking a rowid and delete everything before it. " | ||
+ | |||
+ | ===== Go Forth and Conquer ===== | ||
+ | |||
+ | Now that you know what people are downloading from your site, you'll have better insight into what's popular and what's not. | ||
+ | |||
+ | It's your call, but I like to let people know I'm tracking downloads. Even though I'm not gathering any personal information with it, I like to be transparent about it. I put it in a privacy statement on my site and even offer a link to the PHP query that shows what's been downloaded. |
a_simple_php_sqlite_download_counter.1593287953.txt.gz · Last modified: 2020/06/27 19:59 by waxphilosophic