PHP & MYSQL: NOVICE TO NINJA BY TOM BUTLER & KEVIN YANK BUILD YOUR OWN POWERFUL WEB APPLICATIONS Advocate best practice techniques Lead you through practical examples Provide working
Installation
In this book, I will help you transition from static web page creation using HTML, CSS, and JavaScript to a dynamic website-building experience We will delve into the exciting realm of dynamic tools and concepts, uncovering the vast possibilities they offer for enhancing your web development skills.
Whatever you do, don’t look down!
Okay, maybe you should look down After all, that’s where the rest of this book is. But remember, you were warned!
Before creating your first dynamic website, it's essential to assemble the necessary tools, similar to gathering ingredients before baking a cake This chapter will guide you through downloading and setting up the required software packages for your project.
If you have experience building websites using HTML, CSS, and JavaScript, you're likely familiar with the process of uploading your site files to a specific location This could be a paid web hosting service, space provided by your Internet service provider (ISP), or a web server managed by your company's IT department Once your files are uploaded to any of these platforms, a web server software can locate and deliver those files whenever requested by web browsers such as Microsoft Edge, Internet Explorer, or Google Chrome.
Chrome, Safari, or Firefox Common web server software programs you may have heard of include Apache HTTP Server (Apache), NGINX and Internet Information Services (IIS).
PHP is a powerful server-side scripting language that enhances web servers by allowing them to execute dynamic programs, known as PHP scripts These scripts can perform tasks such as fetching real-time data from databases and generating web pages on demand before delivering them to web browsers This article will primarily concentrate on writing PHP scripts for these purposes Additionally, PHP is completely free to download and use, making it an accessible option for developers.
To enable your PHP scripts to access data from a database, you need to set up a database, and that's where MySQL comes into play MySQL is a relational database management system (RDBMS) that efficiently organizes and manages vast amounts of information while maintaining the relationships between data It simplifies data access through server-side scripting languages like PHP, and like PHP, it is free for most applications.
This chapter aims to guide you in setting up a web server with PHP and MySQL I will offer detailed, step-by-step instructions compatible with the latest versions of Windows, macOS, and Linux, ensuring that you find the necessary guidance regardless of your operating system.
Most likely, your existing web host has PHP and MySQL pre-installed, contributing to their widespread popularity This means that if your host supports these technologies, you can easily launch your first website without needing to search for a compatible web hosting provider.
When creating static websites, you can easily view your HTML files by opening them directly from your hard drive in a web browser, without the need for web server software, as browsers are capable of interpreting HTML code independently.
Dynamic websites created with PHP and MySQL require assistance for web browsers, as they cannot interpret PHP scripts directly These scripts contain commands for a PHP-enabled web server, which processes them to produce HTML code that browsers can read and display.
Even if your current web host supports PHP, it's beneficial to run PHP scripts independently by setting up your own web server Contrary to the notion of a server being a large, air-conditioned room with racks of computers, you can easily use your existing laptop or desktop for this purpose.
To efficiently run PHP scripts, it's essential to upload your code to a web server using FTP or SSH, but this process can be time-consuming, especially when errors occur Instead, setting up a local server on your PC allows you to save files directly from your editor and instantly view changes in your browser with a simple refresh, eliminating the need for repeated uploads This method not only saves time but also enhances your coding workflow, making it a significant advantage even if you already have a reliable web host.
So how do you get a web server running on your PC? There are three methods of achieving this, each with its own advantages and disadvantages.
Server Setup 1: Manually Installing All the Software
Apache is a versatile web server that simplifies the process of setting up on your PC through its user-friendly installer While it allows for quick web page serving, navigating its extensive configuration options can be challenging for those unfamiliar with the system, particularly when developing PHP websites.
To effectively run PHP scripts, simply having a web server is insufficient; you must also manually install PHP, which lacks an installer, and configure it appropriately The default settings are optimized for live websites, which can hinder development by not displaying error messages Consequently, any coding errors, even minor ones like a missing brace or semicolon, may result in a blank page without any helpful feedback To address this issue, it is essential to adjust the PHP configuration to enable error reporting and other development tools, thereby enhancing the coding experience.
To enable Apache to process PHP files, you must configure it to communicate with PHP This ensures that when a user requests a file with a php extension, Apache sends the file to PHP for processing before delivering it to the client.
For this book, you’ll also want MySQL, which means manually installing and configuring that as well.
Setting up Apache, MySQL, and PHP can be challenging due to their numerous configuration options Even experienced users may require at least an hour to properly configure and ensure everything functions correctly.
Introducing PHP
With your virtual server successfully set up, you can now begin writing your first PHP script As a server-side language, PHP operates differently from client-side languages like HTML, CSS, and JavaScript, which may be a new concept for those familiar only with the latter.
A server-side language, like PHP, enables the integration of scripts into HTML code, enhancing control over browser content beyond what HTML can achieve alone Unlike JavaScript, which executes in the user's browser, PHP runs on the server before the web page loads, allowing for dynamic content generation.
Client-side languages, such as JavaScript, are executed by the web browser after the web page is downloaded from the server, allowing control over the page's behavior post-display In contrast, server-side languages like PHP run on the web server, generating customized pages before they are sent to the browser This distinction highlights how client-side scripting enhances user interaction, while server-side scripting enables dynamic content creation.
When a web server processes PHP code within a webpage, the output replaces the PHP code, resulting in standard HTML that the browser displays This characteristic defines PHP as a "server-side language." For instance, a simple PHP script can generate and display a random number between 1 and 10 on the screen.
Generating a random number between 1 and 10:
Most of this is plain HTML Only the line betweenis PHP code.
PHP scripts begin with , signaling the web server to process the code between these tags and transform it into HTML before delivering the webpage to the user's browser By right-clicking and selecting View Source in your browser, you can observe how the server presents the processed code.
Generating a random number between 1 and 10:
In this example, the PHP code has been replaced by the script's output, which resembles standard HTML, showcasing the benefits of server-side scripting.
PHP scripts are executed exclusively by the web server, eliminating concerns about browser compatibility This means developers can utilize any language features without worrying if they are supported by the visitor's browser.
Accessing server-side resources ensures that random numbers are generated securely on the web server rather than the browser This prevents users from manipulating the code to input a specific number, maintaining the integrity of the data displayed on the web page.
Granted, there are more impressive examples of the exploitation of server-side resources, such as inserting content pulled out of a MySQL database.
Minimizing client load is crucial for optimal web performance JavaScript can considerably slow down page loading times, particularly on mobile devices, since the browser needs to execute the script before rendering the content By utilizing server-side code, this processing demand shifts to the web server, allowing for enhanced performance that can be scaled according to the application's needs and budget.
When developing web applications, it's essential to use languages that browsers can interpret, namely HTML, CSS, and JavaScript While client-side code must be written in these languages, server-side code offers more flexibility, allowing developers to choose from various languages, including PHP, to generate HTML dynamically.
PHP syntax will be very familiar to anyone with an understanding of JavaScript,
If you're unfamiliar with programming languages such as C, C++, C#, Objective-C, Java, or Perl, there's no need to be concerned, especially if you're just starting your programming journey.
A PHP script is made up of a sequence of commands known as statements, with each statement serving as an instruction for the web server to execute Just like in other programming languages, PHP statements must end with a semicolon (;) to indicate their completion before the server can move on to the next instruction.
This is a typical PHP statement: echo 'This is a test!';
An echo statement is a PHP function that generates and outputs content, typically HTML code, to the browser It takes the provided text and seamlessly integrates it into the HTML structure at the specific location of the PHP script.
In this case, we’ve supplied a string of text to be output:This is a
test! Notice that the string of text contains HTML tags (and), which is perfectly acceptable.
So, if we take this statement and put it into a complete web page, here’s the resulting code:
If you place this file on your web server and then request it using a web browser, your browser will receive this HTML code:
Therandom.phpexample we looked at earlier contained a slightly more complex echostatement: echo rand(1, 10);
In PHP, text outside of quotes is interpreted as an instruction, while text within quotes is treated as a string and not processed For example, the code `echo 'This is a test!';` sends the string "This is a test!" directly to the echo command without any processing.
In PHP, a string is defined by a starting quote and an ending quote, with the first quote marking the beginning and the subsequent matching quote indicating the end of the string.
In contrast, the following code will first run the built-in functionrandto generate a random number and then pass the result to the echo command: echo rand(1, 10);
Introducing MySQL
In Chapter 1, we booted the Homestead Improved virtual machine The virtual machine contains all the software we need, including a MySQL server.
PHP is a powerful server-side scripting language that enables the integration of executable instructions into web pages, allowing the web server to process them before delivering the pages to users' browsers In previous discussions, we explored fundamental applications of PHP, such as generating random numbers and utilizing forms to collect user input.
In this chapter, we will explore the concept of databases and learn how to effectively manage your own MySQL databases using Structured Query Language (SQL).
A database server, such as MySQL, is a software application designed to store and organize extensive information, making it easily retrievable through programming languages like PHP For instance, you can instruct PHP to query the database for a collection of jokes to display on your website.
Storing jokes in a database offers significant advantages, as it allows for the use of a single PHP script to dynamically retrieve and display any joke as an HTML page, rather than creating individual pages for each joke Additionally, adding new jokes becomes effortless; simply inserting them into the database enables the PHP code to automatically display the updated list of jokes, streamlining content management on your website.
A database is structured with one or more tables, each containing a list of items For instance, a joke database would have a table named "joke" that lists various jokes Each table consists of columns, or fields, that hold specific information about the items In our joke table, one column could store the text of the jokes, while another might record the dates the jokes were added Each joke is represented as a row or entry in the table, creating a structured format of rows and columns.
3-1 A typical database table containing a list of jokes
In database design, each row in a table must be uniquely identifiable, which is why the joke table includes an 'id' column alongside the 'joketext' and 'jokedate' columns This is crucial because identical jokes may be entered on the same date, making it impossible to differentiate them using just the text and date The 'id' column assigns a unique number to each joke, facilitating easy reference and tracking Further exploration of such database design considerations will be provided in Chapter 5.
The table illustrated above consists of three columns and two rows, where each row features three fields: the joke's ID, the text of the joke, and the date it was created With this foundational understanding, you are now prepared to explore MySQL.
Using MySQL Workbench to Run SQL Queries
A MySQL database server functions similarly to a web server, responding to requests from client programs, much like a web server responds to requests from web browsers In this book, we will create our own MySQL client programs.
PHP scripts, but for now we can use a client program written by the same people who write MySQL: MySQL Workbench You can download MySQL Workbench for free.
There are various MySQL clients to choose from, with phpMyAdmin being a previously utilized web-based option that offers similar features However, MySQL Workbench is generally easier to use and performs better, as phpMyAdmin can often be slow and less user-friendly.
Once you’ve downloaded and installed MySQL Workbench, open it up, and you should see a screen that looks like this:
3-2 If you can see this, you have MySQL Workbench running
To add data to your database, you must first establish a connection MySQL operates on the server within the Vagrant box you downloaded in Chapter 1, and you can connect to it using a MySQL client like MySQL Workbench.
Connecting to the database requires three pieces of information: a server address a username a password
For the Homestead Improved Vagrant box, the information is:
The server IP address matches the one you use in your web browser to access your PHP scripts Since the virtual machine hosts both the web server and the database server, you only need to remember one IP address for your connections.
To establish a connection to a database in MySQL Workbench, click the plus icon located next to the "MySQL Connections" label in the center of the interface While the labeling may not be intuitive and its function might seem unclear, this step is essential for accessing your database.
When you press the plus button, you’ll see a new window that looks like this:
To set up your connection in MySQL Workbench, enter the server address and username, and assign a name for your connection, such as "Homestead" or any name of your choice for easy future reference.
After entering your username and server details, click the "Test Connection" button at the bottom of the window to connect to the database You will then see a password prompt box appearing on the screen.
If you don’t, follow these steps:
Ensure that your Vagrant box is operational; if you've restarted your computer since the initial setup, you may need to execute "vagrant up" in your project directory to reactivate it.
2 Make sure the username and server address are correct.
Publishing MySQL Data on the
Publishing MySQL Data on the Web
In this chapter, you will discover how to retrieve data from a MySQL database and effectively display it on a web page for public viewing.
So far, you’ve written your first PHP code and learned the basics of MySQL, a relational database engine, and PHP, a server-side scripting language.
Now you’re ready to learn how to use these tools together to create a website where users can view data from the database and even add their own.
To achieve our ultimate goal, we must first understand the synergy between two essential tools: the PHP scripting language and the MySQL database engine Recognizing how these technologies integrate will provide a clearer perspective on our objectives.
MySQL is utilized on our website to dynamically retrieve content from a database, enabling the creation of web pages for users to view in standard web browsers When a visitor requests a page, their browser anticipates a standard HTML document in response Meanwhile, the website's content is stored in multiple tables within a MySQL database, which processes SQL queries to deliver the requested information.
4-1 Relationships between the web server, browser, PHP and MySQL
The PHP scripting language acts as a bridge between the user and the MySQL database, processing page requests and retrieving data through SQL queries It dynamically generates a well-formatted HTML page that is displayed in the browser, similar to the table of jokes created in Chapter 3.
Just so it’s clear and fresh in your mind, this is what happens when there’s a visitor to a page on your website:
1 The visitor’s web browser requests the web page from your web server.
When a web server, such as Apache or NGINX, identifies a requested file as a PHP script, it activates the PHP interpreter to execute the code within that file.
3 Certain PHP commands (which will be the focus of this chapter) connect to the MySQL database and request the content that belongs in the web page.
4 The MySQL database responds by sending the requested content to the PHP script.
5 The PHP script stores the content into one or more PHP variables, then uses echostatements to output the content as part of the web page.
6 The PHP interpreter finishes up by handing a copy of the HTML it has created to the web server.
The web server transmits HTML to the web browser in the same manner as it would for a standard HTML file; however, the content is generated by the PHP interpreter rather than being retrieved from a static file The browser remains unaware of this distinction and treats the request and response as a typical web page interaction.
To connect PHP to your MySQL database server, a username and password are required While your joke database currently holds only humorous quotes, it may soon store sensitive user information, such as email addresses Therefore, MySQL prioritizes security, allowing you to maintain strict control over accepted connections and their permissions.
The Homestead Improved box already contains a MySQL user in Chapter 3, which you’ve already used to log in to the MySQL server.
To enhance security and manage access effectively, it's advisable to create individual database user accounts for each website hosted on your server, rather than using the default credentials (username: homestead, password: secret) This approach allows for better control over data access, enabling you to grant specific permissions to other developers, ensuring they only have access to the sites they are working on.
You should create a new user account with only the specific privileges it needs to work on theijdbdatabase that your website depends upon Let’s do that now:
1 To create a user, open up MySQL Workbench and connect to your server.
In the panel on the left-hand side of the window, there’s an option labeled
After clicking on the link, you’re able to add a user There’s already a few listed in the middle panel, including thehomesteaduser you used to log in.
To add a new user, simply click the Add Account button located at the bottom of the window, which will activate the fields on the right side You'll see four tabs that provide various options, but you can generally keep most of them set to their default values for simplicity.
To log in, simply enter your desired username and password in the first form while keeping all other settings at their default values.
When creating a user account for accessing a specific database, it's common practice to name the account after the database itself In this book, I've designated the user account as "ijdbuser" to clearly differentiate it from the database name "ijdb."
Limit to Hosts Matching | localhost
To enhance database security, restrict connections to a specific location by entering "localhost," which permits access solely from the computer hosting MySQL This measure ensures that even if an unauthorized individual obtains your database credentials, they cannot log in without access to the server.
In this book, I will use a specific password, but it's essential for you to create your own unique password Be sure to remember this password for future reference when writing your PHP scripts.
Enter your password again, just to verify that you typed it correctly the first time.
To grant your new user access to the database, press Apply to display the user in the central panel, then click on the user and select Schema Privileges By default, users can only log in without any read or write access to schemas To provide access to the jokes database, click Add Entry, choose Selected Schema, and select the ijdbschema from the list This action ensures that the new user has access solely to the ijdbschema, preventing visibility of data from any other websites hosted on the server, even if someone else gains access using the ijdbuseraccount.
To grant full access to your user, simply click OK to view the various checkboxes, which include SQL commands from the previous chapter Then, select all options and click Apply to finalize the changes.
Your user is now set up, and you’ll see the privileges in the box above the checkboxes:
Relational Database Design
In this chapter, we will enhance our initial joke database, which consists of a single table, to explore the more complex aspects of relational database design While our simple MySQL database has provided a solid foundation, there is much more to discover about the capabilities and strengths of relational databases By expanding our database and learning new MySQL features, we aim to fully appreciate the powerful potential that relational databases offer.
This article will explore various topics in a casual manner, acknowledging that database design is a complex field of study While it encompasses established principles that are rigorously tested and mathematically validated, this discussion will remain informal and not delve into those intricate details.
For a comprehensive understanding of database design concepts and SQL, consider reading "Simply SQL." If you are interested in exploring the fundamental principles of relational databases, "Database in Depth" by O'Reilly (2005) is highly recommended.
Giving Credit Where Credit Is Due
The structure of our joke table consists of three columns: id, joketext, and jokedate These columns enable us to uniquely identify each joke (id), maintain the text of the jokes (joketext), and record the date they were added (jokedate) Below is the SQL code used to create this table and insert initial entries.
# Code to create a simple joke table
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB;
# Adding jokes to the table
`joketext` = 'Why was the empty array stuck outside? It
'!false - It\'s funny because it\'s true',
To recreate your database from scratch using MySQL Workbench, simply drop all existing tables, then navigate to Data Import/Restore and select the appropriate database.sql file from the sample code provided Keep in mind that the specific database.sql file will vary based on the sample you are referencing This method allows you to utilize the sql files from this book's code archive as database snapshots for easy loading whenever necessary.
To enhance our joke database, we can track the names of the individuals who submitted each joke by adding a new column to our joke table This can be accomplished using the SQL ALTER TABLE command, which allows us to modify the existing table structure.
As I demonstrated earlier, you can either type out these queries yourself or have a tool such as MySQL Workbench do it for you When you use the GUI of MySQL
MySQL Workbench simplifies database interaction by automatically generating queries for users It allows you to preview these queries before executing them, ensuring you can make any necessary adjustments If you're uncertain about writing a query, MySQL Workbench can create one for you, which you can then modify to meet your specific requirements.
SQL Queries fall into two categories:
Data definition language (DDL) queries These are the queries that describe how the data will be stored These are theCREATE TABLEandCREATE
DATABASEqueries that I showed you in Chapter 3 along with the aforementionedALTER TABLEquery.
Data manipulation language (DML) queries These are the queries that you use to manipulate the data in the database You’ve seen some of these already: INSERT,UPDATE,DELETEandSELECT.
For PHP developers, understanding the syntax and variations of DML queries is essential, as these queries are frequently used in PHP scripts While it's beneficial to grasp the underlying processes, relying on MySQL Workbench to generate DDL queries can be advantageous This approach saves time and reduces the need to learn complex syntax, as DDL queries tend to be more intricate than DML queries.
To add a new column to a database table in MySQL Workbench, connect to your database, navigate to the schema named 'ijdb' created in Chapter 3, and expand the tables section to locate the 'joketable'.
To add a new column to your table, simply right-click on the table name and choose "Alter Table." This action will open the table editing interface, allowing you to add columns just as you did in Chapter 3.
To enhance the joke database, introduce a new column named "authorname" to store the names of the joke authors alongside each joke This column should be defined with the data type VARCHAR(255), allowing for variable-length character strings of up to 255 characters.
VARCHAR(255)—plenty of space for even very esoteric names Let’s also add a column for the authors’ email addresses, set the column name toauthoremail and the type toVARCHAR(255).
Once you press Apply, you’ll see a confirmation dialog appear with the following DDL queries:
ALTER TABLE `joke` ADD COLUMN `authorname` VARCHAR(255)
ALTER TABLE `joke` ADD COLUMN `authoremail` VARCHAR(255)
You could have typed these in yourself, but the GUI in MySQL Workbench provides some useful error checks, and it will always generate valid queries.
To verify the successful addition of the two columns, right-click on the table name in the Schemas panel and choose “Select Rows - Limit 1000.” You will find the two new columns displayed, although they currently do not contain any values for your jokes.
This should give you a table of results like the one below:
May Need to Boot the Server
To restart your server after logging out or rebooting your PC, simply use the vagrant up command, just as you did in Chapter 1.
5-1 Our joke table now contains five columns
Looks good, right? Obviously, to accommodate this expanded table structure, we’d need to make changes to the HTML and PHP form code we wrote in Chapter
We recently enhanced our database by adding new jokes and incorporating author details through UPDATE queries However, upon reflection, we realized that the new table design may not have been the best decision for our needs.
Rule of Thumb: Keep Entities Separate
As your expertise in database-driven websites expands, you may find that a personal joke list is insufficient, especially if you start receiving more submissions from others than you have original content This realization might inspire you to create a global platform for sharing jokes While including the author’s name and email address with each joke is logical, the approach previously mentioned could introduce potential issues.
Structured PHP Programming
Before diving into the upcoming improvements of our joke database, let's take a moment to refine your PHP skills by exploring some techniques for better code structuring.
Structured coding techniques are essential for PHP projects beyond the most basic level As discussed in Chapter 2, organizing your PHP code into separate files, such as a controller and related templates, helps maintain a clear distinction between server-side logic and the HTML used for displaying dynamic content This approach is facilitated by the PHP include command, which allows for efficient code management and improved readability.
PHP provides various features to enhance code structure, with object-oriented programming (OOP) being the most powerful option While OOP offers advanced capabilities, it's not necessary to master all its complexities to create complex and well-structured applications Additionally, PHP's basic features also present opportunities for effective code organization.
In this chapter, I will discuss effective strategies for ensuring your PHP code remains organized and easy to maintain As projects expand, the volume of code increases, making it challenging to locate specific areas for modification This complexity often necessitates adjustments in multiple locations within the codebase.
Programmers prefer efficiency and aim to minimize redundancy by centralizing code Utilizing the include statement enables developers to avoid repetitive tasks by placing code in a single location If you find yourself duplicating code, it's advisable to extract it into a separate file and reference it using the include statement in multiple places.
Computers execute instructions without regard for code structure, but programmers organize code to enhance readability and reduce repetition By breaking code into smaller, manageable tasks, developers simplify error detection and improve overall efficiency in coding.
1000-line PHP script that does a dozen different things is a lot more difficult than finding the same error in a 30-line file that only performs a single task.
Even very simple PHP-based websites often need the same piece of code in several places You’ve already learned to use the PHPincludecommand to load
Utilizing PHP templates within your controllers allows for efficient code reuse, similar to how you previously implemented layout.html.php By writing HTML code once, you can seamlessly apply it across multiple pages, eliminating the need to duplicate your efforts.
Include files (also known just as includes) also contain snippets of PHP code that you can load into your other PHP scripts instead of having to retype them.
The idea of include files predates PHP and has roots in server-side includes (SSIs), a widely available feature on web servers For those with experience in web development, particularly those over 30, SSIs allow for the integration of frequently used HTML, JavaScript, and CSS snippets into include files, enabling their reuse across multiple web pages.
In PHP, include files typically consist of either pure PHP code or a combination of HTML and PHP, as seen in PHP templates However, these files can also contain only static HTML, which is particularly beneficial for maintaining consistent design elements throughout your site, such as a copyright notice displayed at the bottom of each page.
The contents of this web page are copyright © 2017
Example LLC All Rights Reserved.
This file serves as a template partial, specifically an include file for PHP templates To clearly differentiate it from other files in your project, it's advisable to name it with a html.php extension, which is a standard practice in projects utilizing this template structure.
You can then use this partial in any of your PHP templates:
This page uses a static include to display a standard copyright notice below.
Finally, here’s the controller that loads this template:
Example LLC.
Most database-driven websites require each controller script to first establish a database connection before including the layout.html.php file This consistent pattern is followed by all our controllers.
$pdo = new PDO('mysql:host=localhost;dbname=ijdb; charset=utf8', 'ijdbuser', 'mypassword');
$pdo->setAttribute(PDO::ATTR_ERRMODE,
// do something unique for this page
// setting the $title and $output variables
$title = 'An error has occurred';
$output = 'Unable to connect to the database server: '
} include DIR '/ /templates/layout.html.php';
Repeating a 12-line code snippet in every controller script can be tedious for PHP developers, leading some to skip crucial error-checking elements, such as the try catch statement, which can cause significant time loss when errors arise To mitigate this, many developers resort to copying code from existing scripts or utilize text editor features that allow them to store and quickly access useful code snippets.
When the database password or other code details change, it can lead to a frustrating search for every instance of the code on your site that requires updating This task becomes even more challenging if multiple variations of the code have been used, making it a complex treasure hunt to ensure all necessary changes are made.
Using include files can streamline your coding process by allowing you to write a code fragment once and reuse it across multiple files, rather than duplicating the code in each one.
That file can then be included in any other PHP files that need to use it.
Let’s apply this technique to create the database connection in our joke list example to see how it works in detail.
Include files function similarly to standard PHP files, containing code snippets that are relevant only within a larger script context To prevent direct access via browser navigation, these files should remain hidden, as they do not generate meaningful output independently.
Improving the Insert and Update
Improving the Insert and Update Functions
In the previous chapter, I demonstrated how to decompose the code into easily reusable functions, which enhances readability and allows for the function to be utilized from any location within the code.
In this chapter, I will demonstrate how to create a versatile function applicable to any database table, while also illustrating how object-oriented programming can further streamline this process.
Improving the Update Function updateJoke($pdo, 1, 'Why did the programmer quit his job? He
To run this function, all of the arguments for the function must be provided: joke ID joke text author ID
If you only want to update the joke text or the author's information without changing both, the updateJoke function requires all details to be provided each time This can be inefficient if you only need to modify one aspect of the joke.
To improve data handling, utilize an array to represent field values, with keys denoting field names and the array elements containing the data intended for database storage For instance, you can implement this by using the function updateJoke($pdo, [ ]).
'joketext' => 'Why did the programmer quit his job?
The updated approach simplifies the process by requiring only the information that needs to be changed and the primary key to be sent to the function This method enhances readability, allowing users to easily identify what each field is being set to In contrast, the previous version necessitated knowledge of which parameter corresponded to each field, making it challenging to manage tables with numerous fields, as it required precise ordering of arguments and memory of each field's position.
To enable the function to accept an array, it requires an update The current structure of the function is as follows: function updateJoke($pdo, $jokeId, $joketext, $authorId).
':authorId' => $authorId, ':id' => $jokeId]; query($pdo, 'UPDATE `joke`
SET `authorId` = :authorId, `joketext` = :joketext
Modifying the function to accept an array as a second argument and execute the query is complex, as the current query requires parameters for :authorid, :joketext, and :primaryKey Omitting any of these parameters will result in an error.
To work around this error, we need to dynamically generate the query so it only contains the relevant fields (only the ones we actually want to update).
Theforeachloop (which we saw in Chapter 2) can loop over an array Take the following code:
'joketext' => 'Why was the empty array stuck outside?
It didn\'t have any keys'
]; foreach ($array as $key => $value) { echo $key ' = ' $value ',';
This will print the following: id = 1, joketext = Why was the empty array stuck outside? It
It’s possible to use aforeachloop to produce theUPDATEquery:
'joketext' => '!false - it\'s funny because it\'s true'
$query = ' UPDATE `joke` SET '; foreach ($array as $key => $value) {
$query = ' WHERE `id` = :primaryKey'; echo $query;
The code above will print this query:
UPDATE `joke` SET `id` = :id, `joketext` = :joketext,
The query is generated dynamically based on the contents of$array, and only the field names from the array will appear in the query.
You’ll notice that theidfield is included in the statement This isn’t needed, but having it here will simplify things later on.
Note the use of the = operator above It adds to the end of the existing string,rather than overwriting it!
The following code can be used to generate the query with just theauthorId:
$query = 'UPDATE `joke` SET '; foreach ($array as $key => $value) {
$query = ' WHERE `id` = :primaryKey'; echo $query;
The code above will print the following query:
UPDATE `joke` SET `id` = :id, `authorId` = :authorId,
This lets us generate almost the exact query that’s needed to update any field, or set of fields, in thejoketable.
I say almost, because if you sent this query to the database you’d get an error.
Unfortunately, there’s a subtle problem with this generated query You may have noticed that each time the loop runs, it adds a comma to each part of theSET clause, generating this:
SET `id` = :id, `authorId` = :authorId,
In the following section, I’ll show what to do about this.
The problem with this part of the query is that there’s an extra comma at the end of the clause betweenauthorIdandWHERE:
UPDATE `joke` SET `id` = :id, `authorId` = :authorId,
To be a valid query, it should actually be this:
UPDATE `joke` SET `id` = :id, `authorId` = :authorId
A single character distinction can determine whether a query is valid or invalid While it's possible to modify the foreach loop to eliminate the comma during the final iteration, a more straightforward approach is to remove the comma after generating the string.
The TRIM function is useful for removing specific characters, such as a comma, from the end of a string In this instance, we aim to eliminate the comma from the query string prior to adding the WHERE clause.
$query = 'UPDATE `joke` SET '; foreach ($array as $key => $value) {
$query = ' WHERE `id` = :primaryKey'; echo $query;
The line `$query = rtrim($query, ',');` effectively removes the trailing comma from the end of the `$query` string, ensuring a valid SQL UPDATE query This adjustment results in a clean query output without any unnecessary commas.
UPDATE `joke` SET `id` = :id, `joketext` = :joketext
By placing this code into the function, the improved version ofupdateJokecan now be used: function updateJoke($pdo, $fields) {
$query = ' UPDATE `joke` SET '; foreach ($array as $key => $value) {
$fields['primaryKey'] = $fields['id']; query($pdo, $query, $fields);
You’ll notice I set theprimaryKeykey manually with this line:
To ensure the WHERE clause in the query receives the correct ID for the update, the parameter :id cannot be reused, as each parameter must have a unique name.
With this version of theupdateJokefunction, it’s now possible to run it as we designed earlier: updateJoke($pdo, [
'joketext' => '!false - it\'s funny because it\'s true']
Or we could do this: updateJoke($pdo, [
Using this knowledge, we can do the same thing for theinsertJokefunction The INSERTquery can use a syntax different fromUPDATE’s, and it works like this:
$query = 'INSERT INTO `joke` (`joketext`, `jokedate`,
When creating a function, it's beneficial to draft example calls before implementing the code This approach provides a clear target for your development and allows you to run tests to verify the function's correctness.
To insert a joke into the database, we need to focus on two key components: the field names and their corresponding values Initially, we will address the column names Similar to the updateJoke function, we can utilize a loop combined with rtrim to generate the list of fields for the initial line of the SQL query.
$query = 'INSERT INTO `joke` (' foreach ($fields as $key => $value) {
This will generate the first part of the query, and$querywill store the following:
INSERT INTO `joke` (`authorId`, `joketext`) VALUES (
… when called with this array:
'joketext' => '!false - it\'s funny because it\'s true'
The next part of the query should be the placeholders for the values:
To insert a joke into the database, use the function `insertJoke($pdo, $fields)` This function utilizes a `foreach` loop to iterate through the column names and add placeholders before executing the query.
$query = 'INSERT INTO `joke` (' foreach ($fields as $key => $value) {
$query = ') VALUES ('; foreach ($fields as $key => $value) {
TheinsertJokefunction can now be used to insert data into any of the fields: insertJoke($pdo, [
'joketext' => '!false - it\'s funny because it\'s true'
Using the correct column names in code is essential, as incorrect names will lead to errors; however, clear naming enhances readability and understanding of which data is assigned to each column Additionally, this clarity simplifies the function's integration with forms in later stages.
For now, amend your website to use the two new functions by replacing the existing ones inDatabaseFunctions.php: function insertJoke($pdo, $fields) {
$query = 'INSERT INTO `joke` (' foreach ($fields as $key => $value) {
$query = ') VALUES ('; foreach ($fields as $key => $value) {
$query = ' UPDATE `joke` SET '; foreach ($fields as $key => $value) {
$fields['primaryKey'] = $fields['id']; query($pdo, $query, $fields);
Amendeditjoke.phpto use the newupdateJokefunction: updateJoke($pdo, [
You might try amendingaddjoke.phpto use the new function: insertJoke($pdo, ['authorId' => 1, 'jokeText' =>
This example can be found in Structure2-ArrayFunctions-Error.
If you try this, you’ll get an error:
Database error: SQLSTATE[HY000]: General error: 1364 Field
➥ 'jokedate' doesn't have a default value in
➥ /home/vagrant/Code/Project/includes/DatabaseFunctions.php:5
The reason for the error is that we haven’t supplied a value for thejokedate column.
The cause of the above error is that we’ve lost the ability to supply a date when inserting a joke.
Previously, we used theCURDATE()function Using the newinsertJokefunction, you may attempt to set the joke like so: insertJoke($pdo, ['authorId' => 1,
Objects and Classes
In this chapter, we will enhance the generic, reusable functions previously discussed by organizing them into a class structure, thereby reducing repetition and improving efficiency when manipulating any database table.
Functions require all necessary information to be passed as arguments, which can be a significant challenge For instance, the `delete` function we created needs four key pieces of information: the `$pdo` database instance, the name of the table from which to delete, the primary key field name, and the specific value to be deleted.
All functions, including findById, findAll, update, insert, and save, require the $pdo database instance and the table name as parameters Additionally, all functions except for findAll and insert must specify the primary key column name.
For example, the save function is used like this: if (isset($_POST['joke'])) {
$joke['authorId'] = 1; save($pdo, 'joke', 'id', $joke);
Each time one of the functions is called, it must be passed the$pdoinstance.
With up to four arguments for each function, it can be difficult to remember the order they need to be provided in.
A good method for avoiding this problem is putting the functions inside a class.
As each class needs a name, and ours will deal with functions that have something to do with database tables, we’ll call oursDatabaseTable.
Like variables, classes can contain any sequence of alphanumeric characters.
However, special characters like-,+,{or a space aren’t allowed.
In PHP, it is standard practice to use CamelCase for class names, beginning with an uppercase letter followed by lowercase letters While PHP permits variations like databasetable or DATABASETABLE, adhering to the widely accepted naming convention among PHP developers is recommended for consistency and clarity.
You can think of a class as a collection of functions and data (variables) Each class will contain a set of functions and some data that the functions can access.
OurDatabaseTableclass needs to contain all the functions we created for interacting with the database, along with any functions that those functions need to call.
As a first step, move all the database functions into a class wrapper:
{ private function query($pdo, $sql, $parameters = [])
$query->execute($parameters); return $query;
} public function total($pdo, $table)
$query = $this->query($pdo, 'SELECT COUNT(*) FROM
$row = $query->fetch(); return $row[0];
} public function findById($pdo, $table, $primaryKey, $value) {
$query = 'SELECT * FROM `' $table '` WHERE
$query = $this->query($pdo, $query, $parameters); return $query->fetch();
} private function insert($pdo, $table, $fields)
$query = 'INSERT INTO `' $table '` ('; foreach ($fields as $key => $value) {
$query = ') VALUES ('; foreach ($fields as $key => $value) {
$this->query($pdo, $query, $fields);
} private function update($pdo, $table, $primaryKey, $fields)
$query = ' UPDATE `' $table '` SET '; foreach ($fields as $key => $value) {
$this->query($pdo, $query, $fields);
} public function delete($pdo, $table, $primaryKey, $id) {
$this->query($pdo, 'DELETE FROM `' $table '` WHERE
} public function findAll($pdo, $table)
$result = query($pdo, 'SELECT * FROM `' $table '`'); return $result->fetchAll();
{ foreach ($fields as $key => $value) { if ($value instanceof DateTime) {
} public function save($pdo, $table, $primaryKey, $record) { try { if ($record[$primaryKey] == '') {
$this->insert($pdo, $table, $record);
$this->update($pdo, $table, $primaryKey, $record);
Like templates and include files, it’s good practice to store classes outside the publicdirectory Create a new directory calledclassesinside yourProject directory and save the code above asDatabaseTable.php.
The updated code includes two key modifications: first, functions within the class are now called using the prefix $this->, enhancing clarity and context Additionally, the line where results are retrieved has been changed from $result = query($pdo,… to $result =, reflecting the new structure of the code.
In this context, the term "this class" refers to the encapsulation of the query() function within a class structure Unlike a global function, the query() method must be invoked on an instance of the class, similar to how $pdo->prepare() is utilized As such, any method defined within a class can only be accessed through a variable representing that class instance.
It’s good practice to name your class files exactly the same as your classes The class
In a typical project structure, DatabaseTable is defined in DatabaseTable.php, while the User class is located in User.php Adhering to this naming convention is crucial, as it will facilitate the implementation of an autoloader in the future, making the code more manageable and efficient.
In object-oriented programming, a function defined within a class is referred to as a method While many developers and even the PHP language often use the term function to describe these subroutines, the accurate terminology is method, which will be consistently used in this discussion.
However, the difference between a function and a method is that a method is inside a class, while a function isn’t.
In programming, all actions performed with functions—such as handling arguments, returning values, and invoking other functions—can also be executed using methods A method is specifically called on an object, and within the class, the current object is referenced by the variable `$this` This `$this` variable is automatically created within any method and is always available without needing explicit declaration.
In my transition from functions to methods, I've implemented a crucial change by prefixing each method with either public or private This practice, known as visibility, enables programmers to control the accessibility of methods within their code.
In object-oriented programming, methods designated as private can only be accessed by other methods within the same class, while public methods can be accessed from both inside and outside the class For instance, the public method $pdo->prepare() can be called from outside the class, demonstrating the accessibility of public methods, unlike private methods which restrict access.
Private methods, such as query and processDates in the DatabaseTable class, serve a specific purpose by providing shared functionality for other public methods like save and findById These private methods are not intended for direct use by those utilizing the DatabaseTable class, as their standalone utility is limited.
Initially, it may appear to lack purpose, but it serves as a valuable tool When a method, like a query, is made private, it allows for a complete overhaul of its functionality, ensuring that it can only be accessed by other methods within the same class.
Understanding the origin of method calls is crucial when collaborating in large teams or sharing code online By releasing a new version of a class without the deprecated method, you ensure that it is not utilized elsewhere, allowing others to adopt the updated version without risking any disruptions to their code.
When dealing with public code, modifying the query function can be risky, as it may be utilized by other parts of the code Therefore, it's essential to proceed with caution to avoid inadvertently breaking other users' implementations.
You can think of a class as a recipe On its own, it’s just a series of instructions.
To make something from it that’s actually useful—something you can eat—you need to follow the instructions.
Creating an Extensible
Now that you've learned to write a controller with methods and call them from index.php, it's time to expand the website by adding more management pages Currently, you can add jokes to the database via index.php by using the action URL parameter, but a fully functional website requires more than just basic database operations for a single table.
In the upcoming website extension, users will have the opportunity to register as authors and share their own jokes Before implementing this feature, this chapter will guide you in creating a modern and flexible framework that serves as a solid foundation for any website By the end, you will gain valuable insights into the techniques and concepts utilized by professional PHP developers.
We won't be introducing new features; instead, I will demonstrate how to organize your code for optimal reuse across all your websites.
In the last chapter, we ended with this code inindex.php: