Friday, November 30, 2018
Thursday, November 29, 2018
Wednesday, November 28, 2018
Tuesday, November 27, 2018
Monday, November 26, 2018
Get Started With CRUD Operations in PHP MySQL Databases
In this article, we're going to explore how you could use a MySQL database to perform CRUD (create, read, update, and delete) operations with PHP. If you want to get your hands dirty with database connectivity in PHP, this article is a great starting point.
If you are just getting started with PHP, you probably realize that database connectivity is an essential feature that you'll need to get familiar with sooner or later. In most cases, a database is the backbone of any web application and holds the data of the application. So, as a PHP developer, you'll need to know how to deal with database operations.
In this article, we'll keep things simple and explore how to use the core mysqli functions. In upcoming articles of this series, we'll explore a couple of other ways to handle database connectivity.
Today, we'll go through the basics of database connectivity in PHP, and we'll use the MySQL database as our database back-end. Let's have a quick look at what we'll cover in this article:
- how to set up a database connection
- how to select a database
- how to insert and update records
- how to fetch records
- how to delete records
I assume that you've a working installation of PHP and MySQL, and that you're aware of the basics of MySQL. Also, you'll need to make sure that the mysqli extension is enabled in your PHP installation, since we'll use it to do database operations with the MySQL database.
If you are not sure about the mysqli extension, you can check it using the phpinfo()
function. In the phpinfo()
output, you can check if there's a section titled mysqli. You should also see the MysqlI Support | enabled header if the mysqli extension is enabled.
There's also an easy way to check it using the CLI interface. You can run the following command to list all extensions that are enabled with your PHP set up.
$php -m
It should print a list of extensions, and if it contains the mysqli keyword, the mysqli extension is enabled.
Now that we're set up, let's start creating a database connection.
How to Set Up a Database Connection
In this section, we'll discuss how you can establish a database connection using the mysqli extension.
There are two ways you can use the mysqli extension, procedural and object-oriented, but we'll use the procedural way in this post to keep things simple. If you're curious about the object-oriented syntax, let me know your questions in the comment section and I'll be happy to answer them.
Firstly, let's go through the syntax of the mysqli_connect
function which is used to set up a connection with the MySQL back-end.
<?php $connection_obj = mysqli_connect("{MYSQL_HOSTNAME}", "{MYSQL_USERNAME}", "{MYSQL_PASSWORD}", "{MYSQL_DATABASE}"); ?>
The mysqli_connect
function takes four arguments and returns the connection object upon successful connection. Let's go through the each argument:
MYSQL_HOSTNAME
: This should be replaced with the MySQL server's host-name or IP address. If you're working with the MySQL server in your local system, you can either uselocalhost
or127.0.0.1
.MYSQL_USERNAME
: The username of your MySQL user.MYSQL_PASSWORD
: The password of your MySQL user.MYSQL_DATABASE
: The database that you want to connect to.
Upon successful connection, the $connection_obj
contains the connection object. With this, you're ready to run queries against the database which was provided to the MYSQL_DATABASE
argument.
On the other hand, if the connection is not successful, we can debug it as shown in the following snippet:
<?php $connection_obj = mysqli_connect("{MYSQL_HOSTNAME}", "{MYSQL_USERNAME}", "{MYSQL_PASSWORD}", "{MYSQL_DATABASE}"); if (!$connection_obj) { echo "Error No: " . mysqli_connect_errno(); echo "Error Description: " . mysqli_connect_error(); exit; } ?>
In the next section, we'll see how you can select a specific database using the connection object.
How to Select a Database
In the previous section, we discussed how to set up a database connection using the mysqli_connect
function. In this section, we'll look at how to select a database once the MySQL connection is successful.
Of course, as we've already seen, you can always pass a database in the fourth argument of the mysqli_connect
function itself. But, there's also another way you could do this in case you want to change a database after you've connected to MySQL. You can use the mysqli_select_db
function to select a database to work with.
Let's revise the example discussed in the previous section to see how it can work.
<?php $connection_obj = mysqli_connect("{MYSQL_HOSTNAME}", "{MYSQL_USERNAME}", "{MYSQL_PASSWORD}"); if (!$connection_obj) { echo "Error No: " . mysqli_connect_errno(); echo "Error Description: " . mysqli_connect_error(); exit; } mysqli_select_db($connection_obj, "{MYSQL_DATABASE}"); ?>
As you can see, we've passed only three arguments in the mysqli_connect
function, and that should give us a successful database connection. Instead of passing a database in the fourth argument, we select the database using the mysqli_select_db
function.
The mysqli_select_db
function takes two arguments: the connection object and the database you want to connect to.
How to Create (Insert) and Update Records
In the previous sections, we discussed how to set up a MySQL connection and select a database to work with. Now, we'll look at how to execute different types of queries against the selected database. First, let's look at how to insert and update records.
If you want to follow along with examples discussed in this article, you'll need to create the following MySQL table in your database. It's the table which we're going to use in all the examples form now on.
CREATE TABLE `employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `email` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `phone` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Executing the above command in your MySQL database should create the employee
table.
How to Create Records
To keep things simple, we'll initialize values that need to be inserted into the employee table in the beginning of the script. However, in most of the cases, these would come from user input in the $_POST
variables submitted using a form.
<?php $connection_obj = mysqli_connect("{MYSQL_HOSTNAME}", "{MYSQL_USERNAME}", "{MYSQL_PASSWORD}", "{MYSQL_DATABASE}"); if (!$connection_obj) { echo "Error No: " . mysqli_connect_errno(); echo "Error Description: " . mysqli_connect_error(); exit; } // initialize variables for the insert query $name = 'John Smith'; $email = 'john.smith@yahoo.com'; $phone = '541-754-1234'; // prepare the insert query $query = "INSERT INTO employee(`name`,`email`, `phone`) VALUES ('". mysqli_real_escape_string($connection_obj, $name) ."','". mysqli_real_escape_string($connection_obj, $email) ."','". mysqli_real_escape_string($connection_obj, $phone) ."')"; // run the insert query mysqli_query($connection_obj, $query); // close the db connection mysqli_close($connection_obj); ?>
In the above script, we've first initialized variables that we’re going to use in the insert query. Next, we've prepared the insert query and assigned it into the $query
variable.
It's important to note that we've used the mysqli_real_escape_string
function to escape string values that we’re going to use in the insert query. You must use this function when you’re dealing with string values submitted via $_POST
variables. This ensures that your users don't inject malicious code into to your database queries.
Finally, we ran the insert query using the mysqli_query
function. The mysqli_query
function is used to run a query against the active database. To wrap things up, we used the mysqli_close
function to close the active connection.
How to Update Records
In the previous section, we discussed how you can insert new records in the MySQL table. In this section, we'll see how you can update a record which already exists in the table.
I assume that there's already a record exists in the employee table, and the id of that record is 1. In the following example, we're going to update a record which has a value of 1 in the id column.
<?php $connection_obj = mysqli_connect("{MYSQL_HOSTNAME}", "{MYSQL_USERNAME}", "{MYSQL_PASSWORD}", "{MYSQL_DATABASE}"); if (!$connection_obj) { echo "Error No: " . mysqli_connect_errno(); echo "Error Description: " . mysqli_connect_error(); exit; } // initialize variables for the insert query $id = 1; $phone = '333-555-4444'; // prepare the insert query $query = "UPDATE employee SET `phone` = '". mysqli_real_escape_string($connection_obj, $phone) ."' WHERE `id` = '". (int) $id ."'"; // run the insert query mysqli_query($connection_obj, $query); // close the db connection mysqli_close($connection_obj); ?>
As you can see in the above example, we want to update the phone
column of the employee
table where id
is 1. This is very similar to the insert query, except that we're using UPDATE
instead of INSERT
.
How to Retrieve Records
So far, we've discussed how to insert and update records in the MySQL table. In this section, we'll see how to retrieve (fetch) records from the MySQL table.
Take a look at the following example.
<?php $connection_obj = mysqli_connect("{MYSQL_HOSTNAME}", "{MYSQL_USERNAME}", "{MYSQL_PASSWORD}", "{MYSQL_DATABASE}"); if (!$connection_obj) { echo "Error No: " . mysqli_connect_errno(); echo "Error Description: " . mysqli_connect_error(); exit; } // prepare the select query $query = "SELECT * FROM employee"; // execute the select query $result = mysqli_query($connection_obj, $query) or die(mysqli_error($connection_obj)); // run the select query while ($row = mysqli_fetch_array($result, MYSQLI_BOTH)) { echo "ID:" . $row['id'] . "<br/>"; echo "Name:" . $row['name'] . "<br/>"; echo "Phone:" . $row['phone'] . "<br/>"; echo "Email:" . $row['email'] . "<br/>"; echo "<br/>"; } // close the db connection mysqli_close($connection_obj); ?>
The first thing that you need to do in order to fetch records from a database is to execute the select query using the mysqli_query
function. Upon successful execution of the select query, the mysqli_query
function returns the mysqli result
object, and that's what we've stored in the $result
variable above.
Next, we iterate over the result set using the mysqli_fetch_array
function in a while loop. The mysqli_fetch_array
function fetches a single row at a time from the mysqli result set.
The mysqli_fetch_array
function takes two arguments—the result object and result type. The result type indicates what type of array will be returned from the mysqli_fetch_array
function. It could be numeric, associative or both. It's an optional argument and you can pass one of these three values—MYSQLI_ASSOC
, MYSQLI_NUM
, or MYSQLI_BOTH
. MYSQLI_ASSOC
indicates that you want to access columns by their name, and MYSQLI_NUM
indicates that you want to access columns by their column number.
If you pass the MYSQLI_NUM
value in the second argument of the mysqli_fetch_array
function, you can access columns as $row[0]
, $row[1]
and so on. In our case, we've passed the MYSQLI_BOTH
value, so we can access columns in both ways. If you want to access only associative values, you can use the mysqli_fetch_assoc
function instead.
In the next and last section, we'll see how to delete records from a database.
How to Delete Records
In this section, we'll see how to delete records from a database.
Take a look at the following example.
<?php $connection_obj = mysqli_connect("{MYSQL_HOSTNAME}", "{MYSQL_USERNAME}", "{MYSQL_PASSWORD}", "{MYSQL_DATABASE}"); if (!$connection_obj) { echo "Error No: " . mysqli_connect_errno(); echo "Error Description: " . mysqli_connect_error(); exit; } // initialize variables for the delete query $id = 1; // prepare the insert query $query = "DELETE FROM employee WHERE `id` = '". (int) $id ."'"; // run the delete query mysqli_query($connection_obj, $query); // close the db connection mysqli_close($connection_obj); ?>
As you can see, it works pretty much the same as the insert and update queries. The mysqli_query
function executes the DELETE
query, and that eventually deletes the record from the employee
table.
Conclusion
In this article, we explored how you can use the MySQL database with PHP. This article was intended to provide you with a basic knowledge of MySQL database connectivity in PHP to beginners. We saw how to go from setting up a database connection to executing different types of queries.
Feel free to post your feedback and queries using the feed below.
Displaying the Date and Time in the WordPress Loop
Adding the date and time to the WordPress Loop seems like a simple enough task, right?
Well, yes. It can be a case of coding a simple template tag and letting WordPress do the work for you. But sometimes you can run into problems along the way.
In this quick tip, I'll show you the different functions WordPress gives you for displaying the date and time, and tell you which ones to use if you run into snags.
The Available Template Tags
WordPress gives you four functions to output the date and/or time. These are:
the_date().
By default it will echo the date of the post in the formatF j, Y
, so if the post was published on 20 November 2018, it would echo November 20, 2018.get_the_date()
- this fetches the date and doesn't echo it out. To echo it, you'd useecho get_the_date()
which gives you the same result asthe_date()
. It's useful if you're already usingecho
in your code. It can also help you get round the problem of dates not being displayed, as you'll see shortly.the_time()
andget_the_time()
- these fetch the time by default, but if you specify date formatting, you can also include the date. You could even this just to output the date if you configured the formatting to do so, but it would more sense to usethe_date()
orecho get_the_date()
.
Formatting the Date
Each function has a default format, which you can override if you need to. To do this, you'll need to use standard PHP date and time formatting.
Here are some examples, all for a post published on 20 November 2018.
the_date()
would output November 20, 2018 by default.echo get_the_date( l, S M Y )
would output Tuesday, 20th Nov 2018.the_time( 'g:i a' )
would output 2:03 pm.echo get_the_time( 'G:i' )
would output 14:03.the_time( 'g:i a, D, j F y' )
would output 2:03pm, Tues, 20 November 18.
Troubleshooting Dates in the Loop: Missing Dates in an Archive Page
If your'e using the_date()
to output dates on an archive page, and you find that the date isn't being displayed with some posts, that's because the_date()
doesn't repeat the date for subsequent posts published on the same day as a first.
Sometimes you might want to keep it like this, if you don't want to repeat the date for every post published that day.
But if you want to ensure that all posts have their date output with the title and any other content you're outputting, you'll need to use another function. You can use any of the other three functions above.
The simplest option is to replace the_date()
with echo get_the_date()
. If you wanted to add the time, either the_time()
or echo get_the_time()
will work.
Note: If you're puzzled by the fact that the_date()
throws up this problem, but the_time()
doesn't, it's because posts published on the same date weren't published at the same time. You'd have to go to a lot of effort, either scheduling posts, editing the publication times, or co-ordinating efforts between two bloggers, for that to happen!
I had this problem in the front page template of a theme I coded for a client. In this template were a number of loops, all leading to different content types on the site and all coded using WP_Query
. The problem wasn't apparent until the day they added two posts, (not something they normally did). They were puzzled as to why the second post's date didn't appear on the home page, and kept editing it, refreshing it and republishing it until they gave up and asked me.
Here's the original code:
<ul class="newsletters"> <?php $query = new WP_Query( array( 'post_type' => 'post', 'category_name' => 'newsletters', 'posts_per_page' => 8 ) ); while ($query->have_posts()) : $query->the_post(); ?> <li class="home newsletter"><a href="<?php the_permalink(); ?>"><?php the_title(); ?> - <?php the_date( 'j F' ); ?></a></li> <?php endwhile; ?> </ul>
I edited the one function so it read like this:
<ul class="newsletters"> <?php $query = new WP_Query( array( 'post_type' => 'post', 'category_name' => 'newsletters', 'posts_per_page' => 8 ) ); while ($query->have_posts()) : $query->the_post(); ?> <li class="home newsletter"><a href="<?php the_permalink(); ?>"><?php the_title(); ?> - <?php echo get_the_date( 'j F' ); ?></a></li> <?php endwhile; ?> </ul>
In the line beginning li class="home newsletter"
, I replaced the_date( 'j, F' )
with echo get_the_date( 'j, F' )
. It fixed the problem.
So if you ever find that dates aren't showing up in your archives, this might be the solution.
Sunday, November 25, 2018
Saturday, November 24, 2018
Friday, November 23, 2018
Thursday, November 22, 2018
Wednesday, November 21, 2018
Generate Random Alphanumeric Strings in PHP
Let me begin this post by saying that almost no event is truly random. Even the outcome of a classic coin toss could in theory be predicted if we knew the effect of every factor involved, like air friction, gravity, and initial force.
The same thing is applicable to the generation of random numbers and alphanumeric strings. The best we can hope for is to generate numbers and strings that don't seem to follow a pattern and can't be practically predicted by an attacker.
In this tutorial, we will cover different techniques for generating random numbers and alphanumeric strings in PHP. Some of them will be cryptographically secure, while others are meant only for casual use, like assigning pseudo-random file names or creating URLs and suggesting usernames.
Generating Random Numbers in PHP
There are three different functions for generating random numbers in PHP. All of them will accept a minimum and maximum possible value for the random numbers and output a random number for you. These are rand($min, $max)
, mt_rand($min, $max)
, and random_int($min, $max)
.
With rand()
, the minimum and maximum values of integers you can generate lie between 0
and the value returned by getrandmax()
. Before PHP 7.1.0, this function was about four times slower than mt_rand()
. However, starting from PHP 7.1.0, it has been made an alias of mt_rand()
. Unlike mt_rand()
, though, you can set the value of $max
to be lower than $min
without causing an error.
With mt_rand()
, the minimum and maximum values of integers you can generate lie between 0
and the value returned by mt_getrandmax()
. It relies on an implementation of the Mersenne Twister to generate random numbers. Watch out, though—prior to PHP 7.1.0, this function implemented an incorrect version of the algorithm to generate the numbers. However, it has been fixed in newer versions.
The function became even better in PHP 7.2.0 by getting rid of a modulo bias bug. This means that for some particular seeds, your sequence of random numbers will now be slightly better compared to older versions. Some specialized code might actually rely on this bias, though. If so, you can use the older seed algorithm by calling the mt_srand()
function to seed the random number generator and passing MT_RAND_PHP
as the value of the second parameter.
The mt_rand()
function has a period of 219937−1, which basically means that in best case scenarios you get as many as 219937−1 random numbers before the sequence starts repeating. You should note that repetition of a sequence is not the same as repetition of a particular number. In other words, you might get the same random number twice, but that does not mean that the sequence itself has started repeating. The following sequence is an example:
187 3276 1267 15 1267 34598 3467 125 17
In the above sequence, we had 1267 twice in the output, but that does not mean that the whole sequence started repeating after that. It's unlikely to get the same number repeated so soon in a random sequence, but it is possible!
Cryptographically Secure Random Integers
If you want cryptographically secure pseudo-random numbers, the random_int()
function in PHP is your best bet. It will generate random numbers between the provided $min
and $max
values, which default to PHP_INT_MIN
and PHP_INT_MAX
. Unfortunately, this function is only available starting from PHP 7.0. For versions before that, you can use this polyfill on GitHub.
Random Floats
Instead of generating random integers, you might also want to generate floats. This can be done effortlessly by simply dividing a random number with a value returned by mt_getrandmax()
. The following example will illustrate how to generate a random float between 0 and 1 or between any other minimum and maximum limits.
<?php // Output: 0.69458310943776 echo mt_rand(0, mt_getrandmax())/mt_getrandmax(); function mt_random_float($min, $max) { $float_part = mt_rand(0, mt_getrandmax())/mt_getrandmax(); $integer_part = mt_rand($min, $max - 1); return $integer_part + $float_part; } // Output: 10.199064863938 echo mt_random_float(10, 11); // Output: 35.540808309121 echo mt_random_float(15, 50); ?>
When generating a random float between given limits, we make sure that the random integer numbers do not go above $max - 1
. This way, we can be sure that adding the float part will not take the number above the maximum limit.
Seeding the Random Number Generators
One concept that needs a little bit of explanation is seeds. Put simply, these are just numbers that can be used to initialize the rand()
and mt_rand()
functions before generating any random numbers. The function which seeds rand()
is called srand($seed)
, and the function which seeds mt_rand()
is called mt_srand($seed, $mode)
.
It's important to remember that providing an initial seed value every single time before calling rand()
and mt_rand()
won't necessarily produce better random numbers. In fact, using the same seed each time will give you the same random number as well!
<?php mt_srand(10); // Output: 1656398468 echo mt_rand(); mt_srand(10); // Output: 1656398468 echo mt_rand(); mt_srand(10); // Output: 1656398468 echo mt_rand(); ?>
Seeding a random number is useful in situations where you want to generate a random but reproducible sequence. The following code snippet generates the same sequence of random numbers when run twice.
<?php mt_srand(10); $count = 0; while($count < 10) { echo mt_rand(0, 100)." "; $count++; } // Output on First Run: // 68 58 68 13 3 48 30 37 96 82 // Output on Second Run: // 68 58 68 13 3 48 30 37 96 82
Generating reproducible random sequences this way can help debug programs which were being tested using random data—if you keep track of the seed, you can reproduce the same input to figure out what went wrong.
Generating Random Alphanumeric Strings in PHP
There are many ways to generate random alphanumeric strings, and what you use will depend on your needs.
Generate Shuffled Strings
If you want to generate random alphanumeric strings from a fixed set of characters, you can use the str_shuffle($string)
function. This function will provide you a randomly shuffled string. Starting from PHP 7.1, the algorithm which determines the random order of characters in the output string has been changed to the Mersenne Twister.
Remember that the random string generated this way is not cryptographically secure. However, the string will still be pretty unpredictable for common use like generating random file names or URLs. Here are a few examples:
<?php $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyz'; // Output: 54esmdr0qf echo substr(str_shuffle($permitted_chars), 0, 10); $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; // Output: video-g6swmAP8X5VG4jCi.mp4 echo 'video-'.substr(str_shuffle($permitted_chars), 0, 16).'.mp4'; ?>
Your output will most probably be different in both cases. In the first case, we just shuffled the permitted characters string and then took the first 10 characters of it. In the second case, we added "video" at the beginning of the generated string and ".mp4" at the end.
This method of generating random alphanumeric strings is very easy, but it has a couple of issues. For example, you will never get the same characters in your random string twice. Also, the length of the random output string can only be as long as the input string.
Generate Random Strings
If the problems I listed above are a deal breaker, you might want to look at some other implementations. The following code will solve both these problems.
<?php $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; function generate_string($input, $strength = 16) { $input_length = strlen($input); $random_string = ''; for($i = 0; $i < $strength; $i++) { $random_character = $input[mt_rand(0, $input_length - 1)]; $random_string .= $random_character; } return $random_string; } // Output: iNCHNGzByPjhApvn7XBD echo generate_string($permitted_chars, 20); // Output: 70Fmr9mOlGID7OhtTbyj echo generate_string($permitted_chars, 20); // Output: Jp8iVNhZXhUdSlPi1sMNF7hOfmEWYl2UIMO9YqA4faJmS52iXdtlA3YyCfSlAbLYzjr0mzCWWQ7M8AgqDn2aumHoamsUtjZNhBfU echo generate_string($permitted_chars, 100); ?>
You can modify it to add particular suffixes and prefixes to the generated random string. People who are using PHP 7 can improve the string generation further by using the cryptographically secure function random_int()
instead of mt_rand()
.
Generate Random Hexadecimal Strings
If you want to generate random hexadecimal strings in PHP, you can also use either the md5($string, $raw_output)
or the sha1($string, $raw_output)
function. Both of them will generate hashes of a given input string.
You will keep getting unique hashes as long as the input is unique. This could be achieved by using the output of a function like time()
as the input. By default, md5()
will return a 32-character hexadecimal string, and sha1()
will return a 40-character hexadecimal string. These can be trimmed to a specific length using the substr()
function.
Here is an example of the output returned by these functions:
<?php // Output: 36e5e490f14b031e echo substr(md5(time()), 0, 16); // Output: aa88ef597c77a5b3 echo substr(sha1(time()), 0, 16); // Output: 447c13ce896b820f353bec47248675b3 echo md5(time()); // Output: 6c2cef9fe21832a232da7386e4775654b77c7797 echo sha1(time()); ?>
As you can see, generating random and unique hexadecimal strings up to 40 characters long is very easy in PHP.
Generate Cryptographically Secure Random Strings
The three functions to generate random alphanumeric strings that we have discussed so far are not cryptographically secure. Luckily, PHP also has a function called random_bytes($length)
to generate cryptographically secure pseudo-random bytes. The $length
parameter determines how long the output string should be.
Once you have the output in terms of random bytes, you can use the bin2hex()
function to convert them to hexadecimal values. This will double the length of the string.
<?php // Output: b7b33efa07915b60ad55 echo bin2hex(random_bytes(10)); // Output: a2e6cb1f25616324c8a11a2cceb0b47c590949ea echo bin2hex(random_bytes(20)); // Output: 25af3b86e11884ef5e8ef70a0ad06cba81b89ed6af3781a0 echo bin2hex(random_bytes(24)); ?>
Another function that you can use to generate cryptographically secure random bytes is openssl_random_pseudo_bytes($length, &$crypto_strong)
. The value of the second parameter can be used to determine if the output string will be generated using a cryptographically secure algorithm or not.
Final Thoughts
In this tutorial, we looked at the generation of random numbers and alphanumeric strings in PHP. Generating random numbers can be useful in a variety of situations, like in games where you have to spawn enemy players or randomly give users some clues about letters so they can form a whole word.
Just like random numbers, the generation of random alphanumeric strings can also be pretty helpful in many circumstances. With the help of str_shuffle()
, you can choose which set of characters appear in your random strings. With sha1()
and md5()
, you can easily generate random hexadecimal sequences, and with random_bytes()
you can generate cryptographically secure strings. This will allow you to generate meaningful yet randomized filenames and usernames that are hard to guess.
I hope you enjoyed this tutorial. If you have any questions, feel free to ask them in the comments.
Tuesday, November 20, 2018
Monday, November 19, 2018
Sunday, November 18, 2018
Saturday, November 17, 2018
Friday, November 16, 2018
Thursday, November 15, 2018
Dramatically Speed Up Your React Front-End App Using Lazy Loading
A constant challenge faced by front-end developers is the performance of our applications. How can we deliver a robust and full-featured application to our users without forcing them to wait an eternity for the page to load? The techniques used to speed up a website are so numerous that it can often be confusing to decide where to focus our energy when optimising for performance and speed.
Thankfully, the solution isn't as complicated as it sometimes might seem. In this post I'll breakdown one of the most effective techniques used by large web apps to speed up their user experience. I'll go over a package to facilitate this and ensure that we can deliver our app to users faster without them noticing that anything has changed.
What Does it Mean for a Website to be Fast?
The question of web performance is as deep as it is broad. For the sake of this post I'm going to try and define performance in the simplest terms: send as little as you can as fast as you can. Of course, this might be an oversimplification of the problem, but practically speaking, we can achieve dramatic speed improvements by simply sending less data for the user to download and sending that data fast.
For the purpose of this post I'm going to focus on the first part of this definition—sending the least possible amount of information to the user's browser.
Invariably, the biggest offenders when it comes to slowing down our applications are images and JavaScript. In this post I'm going to show you how to deal with the problem of large application bundles and speed up our website in the process.
React Loadable
React Loadable is a package that allows us to lazy load our JavaScript only when it's required by the application. Of course, not all websites use React, but for the sake of brevity I'm going to focus on implementing React Loadable in a server-side rendered app built with Webpack. The final result will be multiple JavaScript files delivered to the user's browser automatically when that code is needed.
Using our definition from before, this simply means we send less to the user upfront so that data can be downloaded faster and our user will experience a more performant site.
1. Add React Loadable
to Your Component
I'll take an example React component, MyComponent
. I'll assume this component is made up of two files, MyComponent/MyComponent.jsx
and MyComponent/index.js
.
In these two files I define the React component exactly as I normally would in MyComponent.jsx
. In index.js
, I import the react component and re-export it—this time wrapped in the Loadable
function. Using the ECMAScript import
feature, I can indicate to Webpack that I expect this file to be dynamically loaded. This pattern allows me to easily lazy load any component I've already written. It also allows me to separate the logic between lazy-loading and rendering. That might sound complicated, but here's what this would look like in practice:
// MyComponent/MyComponent.jsx export default () => ( <div> This component will be lazy-loaded! </div> )
// MyComponent/index.js import Loadable from 'react-loadable' export default Loadable({ // The import below tells webpack to // separate this code into another bundle loader: import('./MyComponent') })
I can then import my component exactly as I normally would:
// anotherComponent/index.js import MyComponent from './MyComponent' export default () => <MyComponent />
I've now introduced React Loadable into MyComponent
. I can add more logic to this component later if I choose - this might include introducing a loading state or an error handler to the component. Thanks to Webpack, when we run our build, I'll now be provided with two separate JavaScript bundles: app.min.js
is our regular application bundle and myComponent.min.js
contains the code we've just written. I'll discuss how to deliver these bundles to the browser a little later.
2. Simplify the Setup With Babel
Ordinarily, I'd have to include two extra options when passing an object to the Loadable
function, modules
and webpack
. These help Webpack identify which modules we should be including. Thankfully, we can obviate the need to include these two options with every component by using the react-loadable/babel
plugin. This automatically includes these options for us:
// input file import Loadable from 'react-loadable' export default Loadable({ loader: () => import('./MyComponent') })
// output file import Loadable from 'react-loadable' import path from 'path' export default Loadable({ loader: () => import('./MyComponent'), webpack: () => [require.resolveWeak('./MyComponent')], modules: [path.join(__dirname, './MyComponent')] })
I can include this plugin by adding it to my list of plugins in my .babelrc file, like so:
{ "plugins": ["react-loadable/babel"] }
I'm now one step closer to lazy-loading our component. However, in my case I'm dealing with server-side rendering. Currently, the server will not be able to render our lazy-loaded components.
3. Rendering Components on the Server
In my server application I have a standard configuration that looks something like this:
// server/index.js app.get('/', (req, res) => { const markup = ReactDOMServer.renderToString( <MyApp/> ) res.send(` <html> <body> <div id="root">${markup}</div> <script src="/build/app.min.js"></script> </body> </html> `) }) app.listen(8080, () => { console.log('Running...') })
The first step is going to be to instruct React Loadable that I want all modules to be preloaded. This allows me to decide which ones should be loaded immediately on the client. I do this by modifying my server/index.js
file like so:
// server/index.js Loadable.preloadAll().then(() => { app.listen(8080, () => { console.log('Running...') }) })
The next step is going to be to push all components I want to render to an array so we can later determine which components require immediate loading. This is so the HTML can be returned with the correct JavaScript bundles included via script tags (more on this later). For now, I'm going modify my server file like so:
// server/index.js import Loadable from 'react-loadable' app.get('/', (req, res) => { const modules = [] const markup = ReactDOMServer.renderToString( <Loadable.Capture report={moduleName => modules.push(moduleName)}> <MyApp/> </Loadable> ) res.send(` <html> <body> <div id="root">${markup}</div> <script src="/build/app.min.js"></script> </body> </html> `) }) Loadable.preloadAll().then(() => { app.listen(8080, () => { console.log('Running...') }) })
Every time a component is used that requires React Loadable
, it will be added to the modules
array. This is an automatic process done by React Loadable
, so this is all that's required on our part for this process.
Now we have a list of modules that we know will need to be rendered immediately. The problem we now face is mapping these modules to the bundles that Webpack has automatically produced for us.
4. Mapping Webpack Bundles to Modules
So now I've instructed Webpack to create myComponent.min.js and I know that MyComponent
is being used immediately, so I need to load this bundle in the initial HTML payload we deliver to the user. Thankfully, React Loadable provides a way for us to achieve this, as well. In my client Webpack configuration file, I need to include a new plugin:
// webpack.client.config.js import { ReactLoadablePlugin } from 'react-loadable/webpack' plugins: [ new ReactLoadablePlugin({ filename: './build/loadable-manifest.json' }) ]
The loadable-manifest.json file will provide me a mapping between modules and bundles so that I can use the modules
array I setup earlier to load the bundles I know I'll need. In my case this file might look something like this:
// build/loadable-manifest.json { "MyComponent": "/build/myComponent.min.js" }
This will also require a common Webpack manifest file to include the mapping between modules and files for internal Webpack purposes. I can do this by including another Webpack plugin:
plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', minChunks: Infinity }) ]
5. Including Bundles in Your HTML
The final step in loading our dynamic bundles on the server is to include these in the HTML we deliver to the user. For this step I'm going to combine the output of steps 3 and 4. I can start by modifying the server file I created above:
// server/index.js import Loadable from 'react-loadable' import { getBundles } from 'react-loadable/webpack' import manifest from './build/loadable-manifest.json' app.get('/', (req, res) => { const modules = [] const markup = ReactDOMServer.renderToString( <Loadable.Capture report={moduleName => modules.push(moduleName)}> <MyApp/> </Loadable> ) const bundles = getBundles(manifest, modules) // My rendering logic below ... }) Loadable.preloadAll().then(() => { app.listen(8080, () => { console.log('Running...') }) })
In this I've imported the manifest and asked React Loadable to create an array with module/bundle mappings. The only thing left for me to do is to render these bundles to an HTML string:
// server/index.js app.get('/', (req, res) => { // My App & modules logic res.send(` <html> <body> <div id="root">${markup}</div> <script src="/build/manifest.min.js"></script> ${bundles.map(({ file }) => `<script src="/build/${file}"></script>` }).join('\n')} <script src="/build/app.min.js"></script> </body> </html> `) }) Loadable.preloadAll().then(() => { app.listen(8080, () => { console.log('Running...') }) })
6. Load the Server-Rendered Bundles on the Client
The final step to using the bundles that we've loaded on the server is to consume them on the client. Doing this is simple—I can just instruct React Loadable
to preload any modules it's found to be immediately available:
// client/index.js import React from 'react' import { hydrate } from 'react-dom' import Loadable from 'react-loadable' import MyApplication from './MyApplication' Loadable.preloadReady().then(() => { hydrate( <MyApplication />, document.getElementById('root') ); });
Conclusion
Following this process, I can split my application bundle into as many smaller bundles as I need. In this way, my app sends less to the user and only when they need it. I've reduced the amount of code that needs to be sent so that it can be sent faster. This can have significant performance gains for larger applications. It can also set smaller applications up for rapid growth should the need arise.
Design Better UX With Vue.js Transitions and Animations
Transitions and animations are an important design pattern whose aim is to improve the user experience (UX) by making the user interface (UI) more natural and intuitive.
Most people think that the purpose of transitions and animations is to engage the user's attention, and this is true to some extent. In certain contexts, such as game websites, where attractiveness and entertainment take precedent, it is justified. However, in most websites, engagement should be the secondary role, while the main role of any transitions or animations should be for communication.
And that will be the subject of this tutorial. We'll explore how transitions and animations can communicate effectively, and we'll see how to use them in the context of Vue.js. Of course, to apply the principles discussed below, you can use any other library or framework (such as React or Angular), or plain CSS transitions and animations.
Note: To follow this tutorial, you should have at least some basic knowledge about Vue.js. If you need to get up to speed, try our beginner's course, Get Started With Vue.
Why Are Transitions and Animations So Important?
In the real world, things don't just appear and disappear suddenly. They move smoothly, they change gradually. In a house, we see people entering or leaving the rooms. On the road, we see cars approaching or moving away. Even at different speeds, their movement is continuous. So to make an interface familiar and easier to understand, we need to mimic some aspects of this real-world behavior in our websites and applications.
This is the role of transitions and animations. They smooth changes between states. They show and explain what happens in a clear and predictable way. In most cases, without transitional effects, the user would be wondering what just occurred.
In modern websites, where interactivity plays a key role, the knowledge of how to use this powerful design pattern properly is crucial. The first thing human eyes perceive is movement. Human brains just love movement. Movement creates interest and catches the attention, but most importantly it delivers a message. The right message will lead to the right action. So proper use of transitions and animations can be the difference between a user making a purchase or leaving your website.
What Are Transitions and Animations?
A transition is simply the change that occurs while a thing moves between two states. The first state is the starting point, and the second state is the ending point. It's like when you open your car's window. The window first is in the closed state, and when you push the button, it gradually transitions to its opened state.
An animation is a series of transitions arranged in a logical order. This means that we have not only starting and ending points, but also several points in between. With transitions, we just go from A to B, or from B to C, and so on. With animations, if we want to go from A to E, for example, we need also to pass through B, C, and D. So the whole animation from A to E is actually made of four transitions, giving an illusion of continuous motion.
How Do Transitions and Animations Improve User Experience?
The first and foremost way in which transitions and animations improve UX is through communication. Just as real-life communication can improve human relationships, similarly in web development, communication can improve the UX of your website or application.
Harry Marks, award-winning broadcast designer, said:
If you don't have a story, no amount of graphic trickery will make it interesting.
So, if content is king and stories are all-important, the key is to present that content to the users in a pleasant and meaningful way. The story communicates a message to the users and must deliver it in a way that users can understand. Let's explore some examples:
- If an object fades away, users know it disappeared.
- If an object fades into view, users know the object has arrived.
- If an image thumbnail zooms in after a mouse click or hover, users know that the zoomed image is the large version of the thumbnail.
All these transitions and animations are like road signs. They give the users clues about what to expect. And this leads to a more pleasant user experience.
There are also some important goals which transitions and animations help us to achieve in our application interfaces. They help us to:
- maintain context while changing views
- explain what just happened
- show relationships between objects
- focus user attention
- improve perceived performance
- create an illusion of virtual space
We'll see how this happens in action in the following examples, but let me first introduce you to Vue.js transitions and animations.
Getting Started With Vue.js Transitions and Animations
Working with Vue.js transitions and animations is easy. Vue.js provides a <transition>
component which wraps the element or component you want to animate. It automatically adds three entering and three leaving CSS classes.
v-enter
, v-enter-active
, and v-enter-to
are responsible for the enter transition when the component is enabled or inserted.
v-leave
, v-leave-active
, and v-leave-to
are responsible for the leave transition when the component is disabled or removed.
v-enter
/v-leave
and v-enter-to
/v-leave-to
define the starting and ending states of the transition. v-enter-active
/v-leave-active
define the transition's configuration, such as duration, easing function, etc.
The <transition>
component can have a name
property. If we define one, it will replace the default v-
prefix in all classes. For example, if the name is set to "menu", the v-enter
class will become menu-enter
, and so on.
Let's now move on to the next section and see how all this is used in practice.
Vue.js Transitions and Animations Use Cases
What follows is a series of use cases which will illustrate the practical application of transitions and animations in Vue.js.
Note: The CSS code unrelated to Vue.js is not shown in the examples for brevity. To see the full code, follow the link to CodePen at the end of each example.
Use Case 1: Dropdown Menu
In this first example, we have a nice dropdown menu which opens at mouse hover. The problem is that this happens too quickly, which is distracting and inconvenient to the users. To make the change between the opening and closing states more smooth and natural, we'll use CSS transitions. This helps users by explaining what just happened, so they can clearly see the connection between the drop-down button and the menu itself.
Let's see this in action. First, we create our HTML template:
<div id="app"> <ul class="navbar"> <li><a href="#home">Home</a></li> <li><a href="#products">Products</a></li> <li class="dropdown"> <button class="dropbtn" @mouseover="show = true" @mouseout="show = false">Dropdown <i class="down-arrow"></i> </button> <transition name="dropdown"> <ul class="dropdown-content" v-if="show" @mouseover="show = true" @mouseout="show = false"> <li><a href="#">Link 1</a></li> <li><a href="#">Link 2</a></li> <li><a href="#">Link 3</a></li> </ul> </transition> </li> </ul> </div>
This creates a navbar menu with three buttons. The third button will open a drop-down menu, which is an unordered list wrapped with the <transition>
component. We set the name
attribute for the transition to dropdown
. When the show
property is true
, the menu will appear, and vice versa.
In the JavaScript part, we create a new Vue instance and set the show
property initially to false
. So the menu will be hidden until we hover over it.
new Vue({ el: '#app', data: { show: false } })
Next, we use the transition classes created by Vue to apply the desired CSS transition:
... .dropdown-enter, .dropdown-leave-to { transform: scaleY(0.7); opacity: 0; } .dropdown-enter-to, .dropdown-leave { opacity: 1; transform: scaleY(1); } .dropdown-enter-active, .dropdown-leave-active { transition: all 0.3s ease-out; transform-origin: top center; }
In the first CSS declaration, we make the menu transparent and slightly scaled down at the beginning of the enter transition and at the end of the leave transition.
In its visible state, we make it fully opaque and scaled to its normal dimensions. In the last declaration, we set the settings for the transition. It will last 0.3 seconds and will have the ease-out
easing function applied. Also, we set the transform-origin
to top center
so the menu will start to appear right below the drop-down button with a nice scroll-down effect.
Use Case 2: Flipping Form
In the second example, we have two forms. One is used to allow users to log in, while the other allows users to create a new profile. Going from one form to another by loading a new page can interrupt the user flow. So we'll use a flip transition, and thus the switch between the two forms will be sleek and easy. This will help to maintain context while changing views, making the user flow fluent and continuous.
Here is the template code:
<div id="app"> <transition name="card" mode="out-in"> <div class="card" v-if="front == true" key="front"> <h2>Sign In</h2> <div class="form"> <h1>Sign In Form</h1> </div> <div class="footer"> <span>Not a member?</span> <button @click="front = false"> Join Us </button> </div> </div> <div class="card" v-else key="back"> <h2>Sign Up</h2> <div class="form"> <h1>Sign Up Form</h1> </div> <div class="footer"> <span>Already a member?</span> <button @click="front = true"> Log In </button> </div> </div> </transition> </div>
Here we want to transition between two elements: the sign-in and sign-up forms. Because we are toggling between elements that have the same tag name (we wrap both forms with a <div>
tag), they must have unique key attributes. Otherwise, Vue will only replace the content of the element.
Also, because entering and leaving happens simultaneously by default, we need to use the mode
attribute. We set it to out-in
, so the current element will transition out first, and then, when complete, the other element will transition in.
In the script part, we set the front
property to true
. So the sign-in form will be displayed first:
new Vue({ el: '#app', data: { front: true } })
And now let's move on to the CSS code:
... .card-enter, .card-leave-to { opacity: 0; transform: rotateY(90deg); } .card-enter-active, .card-leave-active { transition: all 0.5s; }
We make the form transparent and rotated 90 degrees at the start of entering and at the end of leaving the transition. Then we set the transition's duration to 0.5 seconds.
Use Case 3: Modal Window
In the third example, we use a modal window to show users additional information. But the modal appears and disappears abruptly and merges with the background. To solve the problem, we'll use transitions so the modal will be zoomed in and zoomed out smoothly when it is opened or closed. Also, we'll dim the background while keeping the modal bright to create more contrast. This will focus the user's attention in a natural way.
Let's start with the template again:
<div id="app"> <div v-bind:class="[isShowing ? blurClass : '', clearClass]"> <p>Lorem ipsum dolor sit amet...</p> <button @click="toggleShow">Say Hello</button> </div> <transition enter-active-class="animated zoomIn" leave-active-class="animated zoomOut"> <modal v-if="isShowing" class="modal"> <button @click="toggleShow">Close</button> </modal> </transition> </div>
In this example, we use custom transition classes. This way, we can use an animation library such as animate.css. We put the custom classes directly in the <transition>
component and use the classes from the animate.css library.
In the script part, we first register the modal component used in the template above. Then, in the Vue instance, we set several properties and one method, which will help us to toggle between visible and hidden state, and apply different classes for each one:
Vue.component('modal', { template: `<div> <h2>Hello Vue!</h2> <slot></slot> </div>` }) new Vue({ el: '#app', data() { return { isShowing: false, clearClass: 'clear', blurClass: 'blur' } }, methods: { toggleShow() { this.isShowing = !this.isShowing; } } })
And here are the CSS classes:
... .clear { transition: opacity 1s; } .blur { filter: blur(1px); opacity: 0.5; }
The .blur
class is applied when the modal is opened, and the .clear
class when it is closed.
Use Case 4: To-Do List
In the last example, we have a simple to-do list app. It works fine, but when we add or remove items, they are inserted and removed instantly. Users can be easily confused about what is added and what is removed. To make the user experience more pleasant and predictable, we'll use an animation when the items are inserted or removed. This will show relationships between items and help users to orientate themselves and understand what's going on.
Here is the template:
<div id="app"> <h4> 's To Do List </h4> <div> <input v-model="newItemText" /> <button v-on:click="addNewTodo">Add</button> <button v-on:click="removeTodo">Remove</button> <transition-group name="list" tag="ul"> <li v-for="task in tasks" v-bind:key="task" ></li> </transition-group> </div> </div>
In this example, we want to animate multiple items, so we need to use the <transition-group>
component. Unlike <transition>
, it renders an actual element. By default, it is <span>
. But we actually need an unordered list, so we need to set the tag
attribute to ul
.
In the script part, we put some initial data in and create two methods responsible for adding and removing list items:
new Vue({ el: '#app', data: { name: "Ivaylo", tasks: ['Write my posts', 'Go for a walk', 'Meet my friends', 'Buy fruits'], newItemText: "" }, methods: { addNewTodo() { if (this.newItemText != "") { this.tasks.unshift(this.newItemText); } this.newItemText = ""; }, removeTodo() { this.tasks.shift(); }, }, })
And here are the CSS classes:
... .list-enter-active { animation: add-item 1s; } .list-leave-active { position: absolute; animation: add-item 1s reverse; } .list-move { transition: transform 1s; } @keyframes add-item { 0% { opacity: 0; transform: translateX(150px); } 50% { opacity: 0.5; transform: translateX(-10px) skewX(20deg); } 100% { opacity: 1; transform: translateX(0px); } }
In the CSS, we create an add-item
animation. We use that animation in the enter transition. In the leave transition, we use the same animation, but reversed. This follows the Symmetry of Interaction principle.
If you try the app at this stage, the items will be animated, but the list itself will just snap to its new place. To make it move smoothly, we need to do two things: first set the position
to absolute
in the leaving transition, and then add the move
class which Vue provides especially for list transitions.
Best Practices for Transitions and Animations
As you can see, transitions and animations are a powerful way to communicate and engage the user. If used correctly, they can greatly improve the UX. To make it easy to remember, I've prepared the following list of best practices for employing transitions and animations in your websites or applications.
- The key to making a good transition is the balance of speed. The right duration differs for each individual use case, but as a rule of thumb, a transition should look and feel natural—not too fast, not too slow.
- Rapid movement and movement towards the user are considered more important than slow movement and movement away from the user.
- Avoid transitional effects which annoy and distract rather than communicate. The user's attention must be gently guided and directed, not forcibly commanded and dominated.
- Avoid overuse of transitions by only using them to communicate change in the interface.
- Usually, transitions should be reflexive. If users create an object and it slides in, then when it is removed it should slide out with a reverse transition. This illustrates the Symmetry of Interaction principle.
- To make the transitions more discoverable, you should keep them near the user's area of focus. This also will help feel them less like advertising.
Conclusion
I hope that after reading this post you now have a much better understanding of what transitions and animations are and how to use them correctly. You've also seen how to apply them, in the context of Vue.js, to your website or application's user interface, making the UX better and users happy.
This post only scratches the surface about Vue.js transitions and animations. So here are some useful links for further explorations:
- Enter/Leave & List Transitions
- State Transitions
- Creating Vue.js Transitions & Animations
- Native-Like Animations for Page Transitions on the Web
Wednesday, November 14, 2018
Write to Files and Read Files With PHP
In this tutorial, you'll learn several important functions in PHP which are sufficient for all your basic file reading and writing needs. You'll learn how to read a file, write to a file, write to a text file, and check if a file exists.
Luckily, PHP provides a lot of functions to read and write data to files. In this tutorial, I'll show you the easiest ways to read data from a local or remote file and how to use flags to write to files exactly how we want.
Checking if a File Exists
Your very first step when trying to read data from a file or writing something to it should be to check if the file already exists. Trying to read data from a file which does not exist will result in a warning from PHP and will probably crash your code.
The easiest way to check if a file exists is to use the PHP file_exists($filename)
function. It will return true
if a file or directory with the given $filename
exists and false
otherwise. This might be obvious, but I would like to point out that $filename
doesn't have to just be the name of a file. It can also be an absolute or relative path. For example, we could use prime_numbers.txt or science/project/periodic_table.txt.
It's also important to remember that this function will also return false
for files which are inaccessible due to safe mode restrictions.
Another function that you can use to check for the existence of a file is is_file()
. In contrast to file_exists()
, this function will only return true
if the specified path points to a file and not a directory.
Making Sure That the File Actually Exists
If the code you are writing performs a lot of file operations on a particular file, you might get incorrect results using the above functions. This is because the results of the execution of both file_exists()
and is_file()
are cached in order to improve performance. PHP also caches the values returned by other filesystem functions like filesize()
, filemtime()
, etc.
You can call clearstatcache()
to make sure that any information you are accessing for a file is up to date.
This is generally only a problem if the same file is being accessed multiple times in a single script to know its status. Also, the cached data is cleared if you delete the file inside the script using the unlink()
function. This basically means that you probably won't face any caching related problems, but it is still good to know that you can clear the cache in case the information goes stale or if you are getting unexpected results when trying to access information about a file.
Reading Data From a File in PHP
One of the easiest ways to read data from a file in PHP is with the help of the file_get_contents($filename, $use_include_path, $context, $offset, $maxlen)
function. It will simply read the entire file and give it to you in the form of a string. All the parameters except the first one are optional.
The second parameter accepts a boolean value to determine if it should look for a file in the location specified by the include path, which can be set using the set_include_path()
function.
You can use the third parameter to specify a bunch of options to refine how the files are accessed. You can use it to specify header values like the Cookies
and Host
as well as the HTTP method.
The $offset
parameter determines the point where reading starts on the original file. Providing a negative value will start counting from the end. The support for negative offsets was only added in PHP 7.1.0. It is worth noting that offset only works with local files and is not supported for remote files.
The file_get_contents()
function reads the whole file at once by default. You can change this behavior by providing a value for the $maxlen
parameter. The length of characters to be read is counted from the offset value.
This function will return false
if it failed to read data from the file you specified. However, it can also return values which evaluate to false
, so make sure that you check if it actually returned false using the ===
operator.
You can use this function to open remote files, but that would be possible only if the value of the allow-url-fopen
option in php.ini is true
or 1
.
Writing Data to a File in PHP
One of the easiest ways to write data to a file in PHP is with the help of the file_put_contents($filename, $data, $flags, $context)
function.
The $filename
parameter determines the file in which the data will be written. The second parameter is the data that you want to write to the file. Most of the time it will be a string, but it could also be an array or a stream resource.
Remember that PHP will automatically create a file with the given name for you if it doesn't already exist. However, it won't create any directories for you. This means that you can store a file with the name On the Origin of Species [Charles Darwin].txt without any error. However, setting $filename
to Biology/Evolution/On the Origin of Species [Charles Darwin].txt, if Biology/Evolution/ doesn't already exist, will result in an error.
The $flags
parameter determines how the content will be written to a file. It can have any or all of the following three values:
FILE_USE_INCLUDE_PATH
—This tells PHP to search for the given file name in the include directory.FILE_APPEND
—This will tell PHP to append the data you passed to the function to the existing data in the file. It could be useful if you are storing data in a file like a log or a personal diary. Recording new data like temperature or events that happened to you today won't overwrite something you recorded yesterday.LOCK_EX
—This will tell PHP to get a lock on the file before starting to write content into it. It can prevent unexpected things from happening when two different scripts are reading or writing data to the same file. With this particular value, you will get an exclusive lock on the file. You can read more about these locks in the PHP documentation of theflock()
function.
This function returns the number of bytes that were written to the file on success and false
on failure. However, you must still use the strict equality operator to check if it was successful in writing content to the file. That's because code that writes 0 bytes to the file will still evaluate to false.
Reading and Writing Data to Files
You can head over to the Project Gutenberg website and try to download files using the file_get_contents()
function. Once you have the data in a string, you can also simply store it in a local file using the file_put_contents()
function. The following example will make this clear:
<?php $filename = 'http://www.gutenberg.org/cache/epub/1228/pg1228.txt'; $book_content = file_get_contents($filename); file_put_contents('Biology/Evolution/On the Origin of Species [Charles Darwin].txt', $book_content, LOCK_EX); ?>
You could save webpages or content from websites like Wikipedia in a similar manner. If you need to make sense of the HTML or parse the HTML content that you just saved locally, you can follow a tutorial like Parsing HTML With PHP Using DiDOM, which will assist you in automatically getting links, image files, or any other such information from the webpage.
Let's get back to local files now. Consider a situation where you have a bunch of text files and you want to analyze their content to see things like the most common words in them. This could be achieved easily using a bunch of built-in PHP functions.
<?php $filename = 'On the Origin of Species [Charles Darwin].txt'; $book_content = file_get_contents($filename); $book_content_lowercase = strtolower($book_content); $individual_words = explode(' ', $book_content_lowercase); echo "There are about ".count($individual_words)." words in the book: ".substr($filename, 0, -4).".\n"; $word_frequency = array_count_values($individual_words); echo "Total number of unique words in the book are ".count($word_frequency).".\n"; echo "The word 'Elephant' occurs ".$word_frequency["elephant"]." times in the book.\n"; echo "The word 'Ant' occurs ".$word_frequency["ant"]." times in the book.\n"; if(isset($word_frequency["evolution"])) { echo "The word 'Evolution' occurs ".$word_frequency["evolution"]." times in the book.\n"; } else { echo "The word 'Evolution' does not occur even once in the book.\n"; } arsort($word_frequency); echo "The most used word in the book is: '".key($word_frequency)."'.\n"; /* Output of all the code above There are about 147520 words in the book: On the Origin of Species [Charles Darwin]. Total number of unique words in the book are 22758. The word 'Elephant' occurs 3 times in the book. The word 'Ant' occurs 6 times in the book. The word 'Evolution' does not occur even once in the book. The most used word in the book is: 'the'. ?>
We converted all the text to lowercase and made the assumption that every single word breaks at spaces. The text is then converted to an array using explode()
to make it easier to analyze individual words. Surprisingly, the word "evolution" is not used even once in the entire book that gave the theory of evolution its origin.
This was just an example of automatically analyzing a large amount of text. You could do something similar with any kind of text stored in a file.
Logging Data With FILE_APPEND
One more useful example would be logging information over small periods of time. It could be your exercise routine, weather data, or a bee colony that you are observing. Once you have the data in a string, you can easily store it in a file and append it to existing data using the FILE_APPEND
flag with file_put_contents()
.
<?php $filename = "bee-colony.txt"; $present = date('l | jS \of F Y h:i:s A', time()); $entry = $present."\n"; // A pseudo function which could be replaced with something real. $bee_information = gather_bee_data(); $entry .= "$bee_information.\n\n"; file_put_contents($filename, $entry, FILE_APPEND|LOCK_EX); ?>
Similar code could be used for something like storing Wikipedia's featured article of the day in a file every day or keeping track of news articles and headlines over the course of weeks or months. All you need to do is write code to scrape the data and then store it using something similar to the above code snippet. A tutorial like Parsing HTML With PHP Using DiDOM can help you with the scraping part.
Instead of writing the text in plain format, you could wrap it in some HTML to make it easier to read in browsers. The possibilities are endless.
Final Thoughts
There are many other ways of reading and writing data to files in PHP. However, file_get_contents()
and file_put_contents()
will address almost all your basic needs without adding unnecessary complication.
The only time you might face a problem with file_get_contents()
is when the file you are reading is very large—like 2GB or more in size. This is because file_get_contents()
loads the whole file into memory at once, and there is a good chance of running out of memory with such large files. In that case, you will have to rely on functions like fgets()
and fread()
to read a small part of the file at once.
Tuesday, November 13, 2018
Monday, November 12, 2018
Sunday, November 11, 2018
Saturday, November 10, 2018
Friday, November 9, 2018
PHP Integers, Floats and Number Strings
Working with numbers in PHP seems to be a trivial concept but it can be quite confusing. It looks easy at first because PHP provides automatic type conversion. For example, you can assign an integer value to a variable and the type of that variable will be an integer. On the next line, you can assign a string to the same variable and the type will change to a string. Unfortunately, this automatic conversion can sometimes break your code.
There are a lot of types for numeric values as well. In this tutorial, you'll learn about integers and floats in PHP, as well as the functions which can be used to determine the type of numbers that we are dealing with and convert between them. You'll also learn how to convert integers and floats to and from numerical strings.
Different Types of Numbers in PHP
Integers
The most basic type of number in PHP is the integer. As you might already know, integers are numbers without any decimal part. For example, 2 is an integer and so is 235298 or -235298. On the other hand, 2.0 and 3.58 are floats. We will discuss them in more detail later.
One important thing to remember is that it is not necessary that a number be of type int
if it does not have a decimal part. For example, 16 * 2.5
is exactly 40
but the type of this result will still be a float
. When you are multiplying numbers, the final result will be of type float if at least one of the operands was a float. It doesn't matter if the final number has a decimal part or not.
Also, the maximum possible value an integer can have in PHP on your system can be obtained using the constant PHP_INT_MAX
. A value greater in magnitude than the value returned by PHP_INT_MAX
will be stored as a float even if it looks like an integer.
Generally, you would expect the result of multiplication of two variables of type int
to be of type int
. However, it is not true in case of overflow. Multiplication of five or six different numbers can easily take you outside the bounds of int
type. For example, the result of 128*309*32*43*309
is a float on my system because it exceeds the value of PHP_INT_MAX
which is 2147483647
.
You can use the is_int($value)
function to check if a number is of type integer. There are two aliases of this function called is_integer($value)
and is_long($value)
. Both of them will give the same result.
Floats
The next most common type of number that you will deal with is a float. Unlike integers, which were simply numbers without decimal points in most cases, a number of type float
can be represented in a variety of ways. The values 3.14
, 12.0
, 5.87E+10
and 3.56E-5
are all floats.
PHP will automatically convert a number to type float
whenever decimals or very large numbers are involved. The float
type can commonly store numbers with magnitude approximately equal to 1.7976931348623E+308
. However, this is platform dependent.
The value 1.7976931348623E+308
may seem like a very large value—and it is!—but floats have a maximum precision of only about 14 digits. Any number with more digits than that will lose its precision. That means you can store a very large number, but you won't be able to keep the information about its exact value—in many cases, a float is only an approximation.
There are two functions which can be used to determine if the value you are dealing with is a float. These functions are is_float()
and is_double()
. Actually, is_double()
is just an alias of is_float()
so you can use any one of them and get the same result.
Infinity and NaN
There are two more kinds of numerical values that you might have to deal with when writing programs related to Mathematics. These values of infinity and NaN
(not a number). Both these values require a little explanation because they are different from what you might expect.
Infinity in PHP is different from infinity in real life. In PHP, any numerical value above approximately PHP_FLOAT_MAX
on a platform is considered infinity. So, 1.8e308
will give you float(INF)
on var_dump()
. You can check if a numerical value is finite or infinite using the is_finite()
and is_infinite()
functions.
Similarly, NaN
stands for Not a Number but it doesn't check if a value is numerical or not. The value NaN
is used for result of mathematical operations which are not possible in mathematics. For example, log(-1)
will be NaN
. Similarly, acos(5)
will also be NaN
. You can check if the value returned by a mathematical operation is not number by using the function is_nan()
.
Numerical Strings in PHP
Just like PHP dynamically change the type of different numbers based on how their values are used or assigned, it can also infer the value of different numerical strings for you to convert them to numbers.
The function is_numeric()
can help you determine if a string or variable is indeed numeric or not. This function will return true
for numbers written in octal, binary or hexadecimal notation. It will also return true
if the numbers are written in exponential notation like +16.52e39
.
Starting from PHP 7.0.0, when you pass a string to is_numeric()
, it only returns true
if the string consists of an optional sign, some digits, an optional decimal and an optional exponential part. This means that a numerical string written in hexadecimal or binary format will return false
from PHP 7.0.0 onward.
PHP will implicitly cast any valid numerical string to a number when need arises. The following examples should help you understand this process better.
<?php $num = "3258712" + 12380; // Output: int(3271092) var_dump($num); $num = "3258712" + "12380"; // Output: int(3271092) var_dump($num); $num = 3258712 + "12380"; // Output: int(3271092) var_dump($num); $num = 3258712 * "12380"; // Output: float(40342854560) var_dump($num); $num = 3258712 / "12380"; // Output: float(263.2239095315) var_dump($num); $num = 3258712 / "8"; // Output: int(407339) var_dump($num); $num = "53.9e4" + 10; // Output: float(539010) var_dump($num); $num = "398.328" + 10; // Output: float(408.328) var_dump($num); $num = "398328" + 0xfedd24; // Output: int(17101084) var_dump($num); $num = 398328 + "0xfedd24"; // Output: int(398328) var_dump($num); ?>
As you can see, all valid numerical string were converted to their respective values before addition or other operations were performed. The type of $num
in the end depends on its final value.
In the last case, the hexadecimal string "0xfedd24" is not converted to its decimal value because PHP 7 does not consider it to be a valid numerical string.
Casting Strings and Floats to Integers
Every now and then, you will need to cast one type of numerical values into another. PHP has a variety of functions and techniques to do so. Most of the time, the conversion will be implicit and you won't have to worry about it. However, if you have to do the conversion explicitly techniques mentioned here will definitely help.
You can use (int)
or (integer)
to convert any value to an integer. In case of floats, the values will always be rounded towards zero. Another way to cast strings and floats to integers is with the help of intval()
function. Both (int)
and intval()
work in exactly the same manner.
<?php $float_a = 3598723.8258; $int_cast = (int)$float_a; // Output: 3598723 echo $int_cast; $string_a = "98723.828"; $int_cast = (int)$string_a; // Output: 98723 echo $int_cast; $string_b = "987233498349834828"; $int_cast = (int)$string_b; // Output: 2147483647 echo $int_cast; $float_b = 21474836473492789; $int_cast = (int)$float_b; // Output: -6507212 echo $int_cast; ?>
You should note that casting overflowing strings to integers will set the final value to the maximum permissible integer value. However, casting a float whose value is more than the maximum permissible integer value will result in the value oscillating between -2147483648
and 2147483647
!
In certain situations, you might need to deal with very large numbers without loosing any precision. For example, it is impossible to get accurate result of multiplication of 987233498349834828
and 3487197512
using the *
operator. It will give you 3.4426781992086E+27
after float conversion. Calculating the actual answer, which is 3442678199208600117812547936
, will require use of libraries like BCMath. BCMath works by storing numbers as strings and doing arithmetic operations on them manually. Just remember that if you use BCMath, you will be dealing with strings instead of integers and floats.
Certain libraries will want you to only pass numbers of type int
to their methods but you might unknowingly supply them a float value. This might happen because the value seems like an int because it doesn't have a decimal part. This would almost certainly result in an error if the library uses a function like is_int()
to check if the passed number is of integer type. In such cases, it is always wise to first cast that number to int using either (int)
or intval()
and then pass it to any functions or methods of the library.
One example of when such a situation could come up would be when you are dealing with Mathematical functions like floor()
and ceil()
etc. floor()
and ceil()
will always return a float, even if you pass them an int!
<?php $int_a = 15*12; // Output: int(180) var_dump($int_a); $num = floor($int_a); // Output: float(180) var_dump($num); ?>
One problem with casting floats to integers is that you will lose the decimal part of the numbers. This may or may not be desirable. In such cases, you can use functions like floor()
and only cast the number to int type if its actual value is equal to the value returned by floor()
.
<?php $number = 16*2.5; if(floor($number) == $number) { $fraction->setNumerator((int)$number); } else { echo 'Did not set the numerator.'; doSomethingElse(); } ?>
Let's say you have a library which allows you to do fractional arithmetic and it throws exceptions when you pass a number to its setNumerator()
method that is not of type int. A variety of operations might turn a number in type float even if it is still an integer within the minimum and maximum bounds of type int. Using something like the code above will help you deal with such cases easily.
Final Thoughts
This tutorial has covered different ways in which PHP stores numbers and how you can determine if a number of a particular type. For example, you can use functions like is_int()
and is_float()
to determine the type of a number and proceed accordingly.
As you saw in the tutorial, PHP supports automatic type conversion. This means that sometimes smaller integers like 5
or 476
could have been stored as floats without you realizing it. Using these numbers in functions which only accept int
values might result in exceptions or errors. We learned that a simple solution to this problem is be to explicitly cast such numbers to int
if they don't have a decimal part and their values don't change upon casting.
After reading this tutorial, you should be able to determine the type of a number or the final type of a result after using a variety of operations using predefined functions and also explicitly cast them to a specific type after doing some checks.
As always, if you have any questions or additional tips, you are welcome to comment.