How to Build a Website from Scratch with PHP

If you gain a basic understanding of how to build a website using PHP, you will have knowledge of file inclusions and producing output – the very basics of customizing a web page. You may be wondering where to start or what are the next steps to incorporate more functionality into your site.

In this tutorial, I present a simple site structure that allows for simple updates. It also shows some useful PHP functions to add value.

The website you are going to create in PHP

The sample website, available in a GitHub repository-is a simple site about birds in all their feathery goodness. There are a few sections, a few information pages, and a homepage. The final site is not as important as the techniques you read about and the ideas they may inspire.

enter 2022-02-14 at 11.28.25

If you can, download the site from GitHub and install it on your local computer before reading on.

General structure of the site

Here are some of the key files and directories you should investigate.

  • Each page corresponds to a PHP script in the to place phone book. This introduces some redundancy, but it simplifies things. When setting up your web server, be sure to point your DOCROOT to the to place phone book.
  • the Maryland The directory contains Markdown source files that store the main content for some individual pages.
  • the dwt The directory contains templates and files that define the overall HTML structure that multiple pages can share.
  • Most PHP features are in funcs.php.


Related: How to Setup Your Own WAMP Server

How does the site work


Prime is a front-end framework for building websites. It has built-in styles and JavaScript functionality, covering the most common web development needs. It’s a great way to get a site up and running quickly before spending time tweaking the design.

You can install and host the Bootstrap files on your server, but for maximum speed you can simply reference them from a CDN. Take a look at tpl/head.php and you should see an example like:

href="[email protected]/dist/css/bootstrap.min.css"

Basic models

start with site/index.php. This is the file that represents the home page of the site. Depending on how your web server is configured, you should be able to access it at or, failing that,

Note the two includes right at the beginning of this file: funcs.php and TPL_DIR.”/home.php”. the funcs.php file defines that TPL_DIR constant as the full absolute path of the dwt directory at the top level of the site.

Take a look at tpl/home.php. It is the outermost skeleton of an html document: it only includes a doctype and an HTML element. In the HTML element, it uses two includes for the models representing the head and the body.

In contrast, the birds section model loads a different body model, tpl/birds/body.tpl. This contains a different layout for the pages in this section, one with a sidebar.

Analyze Markdown

In the composer.json file, a third-party library called erusev/analyze is required. It is a Markdown parsing library. It allows you, very easily, to convert Markdown text to HTML.

Many static sites generate final HTML code from documents written in another language, such as Markdown. It offers a nicer syntax for creating, more readable than HTML. The sample site shows it as an option. Take a look at the show content() function in funcs.php:

function show_content() {
$file = MD_DIR.PAGE.'.md';
if (file_exists($file)) {
$Parsedown = new Parsedown();
echo $Parsedown->text(file_get_contents($file));
} else if (function_exists("content")) {
echo content();

If a Markdown file corresponding to the requested page exists, a Parsedown object converts its content to HTML and outputs it. If there is no Markdown file, it looks for a function named contents() in place. Individual pages can define this function (see site/index.php for example) if their content needs to go beyond what static Markdown can achieve.

Loading metadata

Take a look at the get_json function in funcs.php:

function get_json($file) {
$data_file = DATA_DIR."/".$file;
if (!file_exists($data_file)) {
return array();
if (($json = file_get_contents($data_file)) === false) {
return array();
if (($out = json_decode($json, true)) === null) {
return array();
return $out;

Essentially, the function calls two more to retrieve and parse data from a given file. It dresses this up with lots of error checking to return an empty array if something goes wrong. Call json_decode() like this returns an associative array which makes it easy to work with the data right away. This approach is so convenient that you might prefer it to using a database, especially for simple tasks like global configuration.

The site uses two metadata files: data/titles.json and data/featured.json. The first stores the title of each page, useful for automatic linking and in other cases.

"/": "Home",
"/about": "About",
"/birds": "Bird profiles",

It’s a convenient way to keep all page titles in one place (file) that’s easy to update when you need them. These titles help navigate the top menu, breadcrumb list, and side panels.

function page_title($page = PAGE) {
$titles = get_titles();
return array_key_exists($page, $titles) ? $titles[$page] : basename($page);

A simple website page showing information about a bird with its photo

Here is the first part of breadcrumbs() function (since funcs.php) which builds an array of page titles for each part of the URL. For example, for the /birds/blue tit page, it retrieves the title of the / page, then the title of /birdsthen finally the title of /birds/blue tit. The breadcrumb list will then consist of a link for each page in the hierarchy.

function breadcrumbs() {
$items = array();
$titles = get_titles();
$parts = explode("/", PAGE);
$href = "";
foreach ($parts as $part) {
$href .= ($href == "/" ? "" : "/").$part;
$items[$href] = $titles[$href];

Get other metadata

If you look at the About page, a specific news item, or a specific bird profile, you should be able to spot a Last update message in the footer. The site footer is stored in tpl/footer.php. Open this file and note the PHP code snippet it contains:

if (file_exists($file = MD_DIR.PAGE.'.md')) {
echo 'Last updated: '.date('r', filemtime(MD_DIR.PAGE.'.md'));

This is a simple example of extracting metadata directly from a file rather than a database or other source. the file time The function returns the last modification time of a file. Note that this is a very convenient method of getting the content date, but it’s not without its flaws.

See also: Understanding Linux file timestamps: mtime, ctime, and atime

It is often necessary to reuse content on a site, to display news summaries on a content page, for example. With a full CMS, you can store this data as additional fields in a database. With a simple flat file approach, you have to think differently.

News on this site is stored as Markdown files, so the raw content is available. Regular expressions are a handy tool in a SDK, allowing you to match and extract content. the news/index.php file does exactly that to display its contents. It retrieves the contents of each file in the md/news directory as a string. It then executes several regular expressions to extract the data.

A simple website showing two bird stories, with photographs

The title is a line beginning with a # symbol, according to Markdown syntax. Optional white space then follows, before the actual title. The regular expression ^#s+(.+) matches this text pattern and preg_match() returns whatever matches between the square brackets: the title.

if (preg_match("/^#​s+(.+)/", $contents, $matches)) {
$title = $matches[1];

Two other regular expressions follow to extract the image and the first sentence from the news markdown file. There are downsides to this approach; in particular, it takes discipline to ensure that Markdown files are always formatted exactly as the code expects it.

See also: The Beginner’s Guide to Regular Expressions with Python

Random content selection

the /birds the page doesn’t do much, so a random bird image animates it. This is easy to achieve with a bit of filesystem inspection and a function built into PHP. The magic happens in site/birds/index.php:

function content() {
$files = scandir(SITE_DIR."/img");
$files = array_filter($files, function($file) { return $file[0] != '.'; });
$file = $files[array_rand($files)];
echo '


echo '';

The trick is to organize all the images for that specific function in one directory. the scandir() function then reads the files from that directory into an array and array_rand() gives us a random key in the array so the function can choose an individual file.

Website building and PHP skills

I hope you have learned at least one new thing from this article. More importantly, I hope it inspired you to consider various approaches and demonstrated how you can use PHP in different ways.

Once you get familiar with PHP, you’ll start thinking of alternative solutions to every problem. It’s a natural progression and it means you start thinking at a higher level, focusing less on the programming language itself and more on what you can do with it.

Person typing on a laptop
Add authentication to any PHP application using MySQL

Explore the power of PHP and MySQL with this tutorial that walks you through creating authentication on your web application.

Read more

About the Author

Comments are closed.