In addition to the magnificent answer from KIKO Software, a few pointers

Getting IP
---

First of all there is at least one issue connected to security. The findIP() function. Many beginners are using a similar approach feeling smart. In reality, this function makes your code *less reliable and secure* as having this very function actually lets the IP being easily spoofed. See [my other answer](https://codereview.stackexchange.com/a/244194/101565) for the details. **Stick to `REMOTE_ADDR` only** and you're good to go.

Error reporting / Code repetition
---

The code repetition mentioned in the other answer is just horrible. Although it takes some experience to get the eye for the code repetitions that nobody expects from a beginner, but really: the two code blocks differ but *one symbol* (or so I can tell because finding differences in the identical code blocks is a job by itself)

        $date = '[' . date('d-M-Y h-i-s a') . ']';
        $msg = $e->getMessage();
        $err_msg = $date . ' | Exception Error | ' . $msg  . ' | \n';
        error_log($err_msg, 3, ERROR_LOG_BOOK);
        // error_log("Date/time: $date, Exception Error check error log for more details", 1, WEB_MASTER_EMAIL, "Subject: Exception Error \nfrom: Error Log <" . ERROR_LOG_EMAIL . "> \r\n");

        $date = '[' . date('d-M-Y h-i-s a') . ']';
        $msg = $e->getMessage();
        $err_msg = $date . ' | Error | ' . $msg  . ' | \n';
        error_log($err_msg, 1, ERROR_LOG_BOOK);
        // error_log("Date/time: $date, Error check error log for more details", 1, WEB_MASTER_EMAIL, "Subject: Error \nfrom: Error Log <" . ERROR_LOG_EMAIL . "> \r\n");

Moreover, these almost identical blocks are repeated in the code again!

But what I *really* don't understand is why there is so much attention to the database connection errors as compared to a *complete neglect* towards many other errors in the code! 

Say, connecting to a mail server may result in none the less illustrious error but we don't see even a hint of the error handling, least such a hairy one. 

Or, including a file may result in the error, when a file is missing or has a permission problem. Or sending a header almost certainly st some point will produce the infamous "Headers already sent" error. Or literally **any line** of **any code** may produce an error. But for some reason only some code blocks are wrapped in a try catch.

At least wrap the **entire code** in a single try catch, so you won't have to repeat the handling code and also it will e able to handle all possible errors, not just a subset of them.

And of course make this code to catch a **single** `\Throwable` class exception with some condition inside to distinguish the type (in case you really need it, which I highly doubt)

The separation of the business logic and presentation logic
---

As you already learned (from the fact you are using `endTheWebpage()`), intertwinig the application logic with the presentation logic makes your life incredibly hard. And you must separate them completely:

- make your application code do all its job first
- only then start sending HTML to the client

This simple approach will make both parts incredibly clearer and easier to understand.