One place for hosting & domains

      Work

      How To Work With Zip Files in Node.js


      The author selected Open Sourcing Mental Illness to receive a donation as part of the Write for DOnations program.

      Introduction

      Working with files is one of the common tasks among developers. As your files grow in size, they start taking significant space on your hard drive. Sooner or later you may need to transfer the files to other servers or upload multiple files from your local machine to different platforms. Some of these platforms have file size limits, and won’t accept large files. To get around this, you can group the files into a single ZIP file. A ZIP file is an archive format that packs and compresses files with the lossless compression algorithm. The algorithm can reconstruct the data without any data loss. In Node.js, you can use the adm-zip module to create and read ZIP archives.

      In this tutorial, you will use adm-zip module to compress, read, and decompress files. First, you’ll combine multiple files into a ZIP archive using adm-zip. You’ll then list the ZIP archive contents. After that, you’ll add a file to an existing ZIP archive, and then finally, you’ll extract a ZIP archive into a directory.

      Prerequisites

      To follow this tutorial, you’ll need:

      Step 1 — Setting Up the Project

      In this step, you’ll create the directory for your project and install adm-zip as a dependency. This directory is where you’ll keep your program files. You’ll also create another directory containing text files and an image. You’ll archive this directory in the next section.

      Create a directory called zip_app with the following command:

      Navigate into the newly created directory with the cd command:

      Inside the directory, create a package.json file to manage the project dependencies:

      The -y option creates a default package.json file.

      Next, install adm-zip with the npm install command:

      After you run the command, npm will install adm-zip and update the package.json file.

      Next, create a directory called test and move into it:

      In this directory, you will create three text files and download an image. The three files will be filled with dummy content to make their file sizes larger. This will help to demonstrate ZIP compression when you archive this directory.

      Create the file1.txt and fill it with dummy content using the following command:

      • yes "dummy content" | head -n 100000 > file1.txt

      The yes command logs the string dummy content repeatedly. Using the pipe command |, you send the output from the yes command to be used as input for the head command. The head command prints part of the given input into the standard output. The -n option specifies the number of lines that should be written to the standard output. Finally, you redirect the head output to a new file file1.txt using >.

      Create a second file with the string “dummy content” repeated 300,000 lines:

      • yes "dummy content" | head -n 300000 > file2.txt

      Create another file with the dummy content string repeated 600,000 lines:

      • yes "dummy content" | head -n 600000 > file3.txt

      Finally, download an image into the directory using curl:

      • curl -O https://assets.digitalocean.com/how-to-process-images-in-node-js-with-sharp/underwater.png

      Move back into the main project directory with the following command:

      The .. will move you to the parent directory, which is zip_app.

      You’ve now created the project directory, installed adm-zip, and created a directory with files for archiving. In the next step, you’ll archive a directory using the adm-zip module.

      Step 2 — Creating a ZIP Archive

      In this step, you’ll use adm-zip to compress and archive the directory you created in the previous section.

      To archive the directory, you’ll import the adm-zip module and use the module’s addLocalFolder() method to add the directory to the adm-zip module’s ZIP object. Afterward, you’ll use the module’s writeZip() method to save the archive in your local system.

      Create and open a new file createArchive.js in your preferred text editor. This tutorial uses nano, a command-line text editor:

      Next, require in the adm-zip module in your createArchive.js file:

      zip_app/createArchive.js

      const AdmZip = require("adm-zip");
      

      The adm-zip module provides a class that contains methods for creating ZIP archives.

      Since it’s common to encounter large files during the archiving process, you might end up blocking the main thread until the ZIP archive is saved. To write non-blocking code, you’ll define an asynchronous function to create and save a ZIP archive.

      In your createArchive.js file, add the following highlighted code:

      zip_app/createArchive.js

      
      const AdmZip = require("adm-zip");
      
      async function createZipArchive() {
        const zip = new AdmZip();
        const outputFile = "test.zip";
        zip.addLocalFolder("./test");
        zip.writeZip(outputFile);
        console.log(`Created ${outputFile} successfully`);
      }
      
      createZipArchive();
      

      createZipArchive is an asynchronous function that creates a ZIP archive from a given directory. What makes it asynchronous is the async keyword you defined before the function label. Within the function, you create an instance of the adm-zip module, which provides methods you can use for reading and creating archives. When you create an instance, adm-zip creates an in-memory ZIP where you can add files or directories.

      Next, you define the archive name and store it in the outputDir variable. To add the test directory to the in-memory archive, you invoke the addLocalFolder() method from adm-zip with the directory path as an argument.

      After the directory is added, you invoke the writeZip() method from adm-zip with a variable containing the name of the ZIP archive. The writeZip() method saves the archive to your local disk.

      Once that’s done, you invoke console.log() to log that the ZIP file has been created successfully.

      Finally, you call the createZipArchive() function.

      Before you run the file, wrap the code in a try…catch block to handle runtime errors:

      zip_app/createArchive.js

      const AdmZip = require("adm-zip");
      
      async function createZipArchive() {
        try {
          const zip = new AdmZip();
          const outputFile = "test.zip";
          zip.addLocalFolder("./test");
          zip.writeZip(outputFile);
          console.log(`Created ${outputFile} successfully`);
        } catch (e) {
          console.log(`Something went wrong. ${e}`);
        }
      }
      
      createZipArchive();
      

      Within the try block, the code will attempt to create a ZIP archive. If successful, the createZipArchive() function will exit, skipping the catch block. If creating a ZIP archive triggers an error, execution will skip to the catch block and log the error in the console.

      Save and exit the file in nano with CTRL+X. Enter y to save the changes, and confirm the file by pressing ENTER on Windows, or the RETURN key on the Mac.

      Run the createArchive.js file using the node command:

      You’ll receive the following output:

      Output

      Created test.zip successfully

      List the directory contents to see if the ZIP archive has been created:

      You’ll receive the following output showing the archive among the contents:

      Output

      createArchive.js node_modules package-lock.json package.json test test.zip

      With the confirmation that the ZIP archive has been created, you’ll compare the ZIP archive, and the test directory file size to see if the compression works.

      Check the test directory size using the du command:

      The -h flag instructs du to show the directory size in a human-readable format.

      After running the command, you will receive the following output:

      Output

      15M test

      Next, check the test.zip archive file size:

      The du command logs the following output:

      Output

      760K test.zip

      As you can see, creating the ZIP file has dropped the directory size from 15 Megabytes(MB) to 760 Kilobytes(KB), which is a huge difference. The ZIP file is more portable and smaller in size.

      Now that you created a ZIP archive, you’re ready to list the contents in a ZIP file.

      Step 3 — Listing Files in a ZIP Archive

      In this step, you’ll read and list all files in a ZIP archive using adm-zip. To do that, you’ll instantiate the adm-zip module with your ZIP archive path. You’ll then call the module’s getEntries() method which returns an array of objects. Each object holds important information about an item in the ZIP archive. To list the files, you’ll iterate over the array and access the filename from the object, and log it in the console.

      Create and open readArchive.js in your favorite text editor:

      In your readArchive.js, add the following code to read and list contents in a ZIP archive:

      zip_app/readArchive.js

      const AdmZip = require("adm-zip");
      
      async function readZipArchive(filepath) {
        try {
          const zip = new AdmZip(filepath);
      
          for (const zipEntry of zip.getEntries()) {
            console.log(zipEntry.toString());
          }
        } catch (e) {
          console.log(`Something went wrong. ${e}`);
        }
      }
      
      readZipArchive("./test.zip");
      

      First, you require in the adm-zip module.

      Next, you define the readZipArchive() function, which is an asynchronous function. Within the function, you create an instance of adm-zip with the path of the ZIP file you want to read. The file path is provided by the filepath parameter. adm-zip will read the file and parse it.

      After reading the archive, you define a for....of statement that iterates over objects in an array that the getEntries() method from adm-zip returns when invoked. On each iteration, the object is assigned to the zipEntry variable. Inside the loop, you convert the object into a string that represents the object using the Node.js toString() method, then log it in the console using the console.log() method.

      Finally, you invoke the readZipArchive() function with the ZIP archive file path as an argument.

      Save and exit your file, then run the file with the following command:

      You will get output that resembles the following(edited for brevity):

      Output

      { "entryName": "file1.txt", "name": "file1.txt", "comment": "", "isDirectory": false, "header": { ... }, "compressedData": "<27547 bytes buffer>", "data": "<null>" } ...

      The console will log four objects. The other objects have been edited out to keep the tutorial brief.

      Each file in the archive is represented with an object similar to the one in the preceding output. To get the filename for each file, you need to access the name property.

      In your readArchive.js file, add the following highlighted code to access each filename:

      zip_app/readArchive.js

      const AdmZip = require("adm-zip");
      
      async function readZipArchive(filepath) {
        try {
          const zip = new AdmZip(filepath);
      
          for (const zipEntry of zip.getEntries()) {
            console.log(zipEntry.name);
          }
        } catch (e) {
          console.log(`Something went wrong. ${e}`);
        }
      }
      
      readZipArchive("./test.zip");
      

      Save and exit your text editor. Now, run the file again with the node command:

      Running the file results in the following output:

      Output

      file1.txt file2.txt file3.txt underwater.png

      The output now logs the filename of each file in the ZIP archive.

      You can now read and list each file in a ZIP archive. In the next section, you’ll add a file to an existing ZIP archive.

      Step 4 — Adding a File to an Existing Archive

      In this step, you’ll create a file and add it to the ZIP archive you created earlier without extracting it. First, you’ll read the ZIP archive by creating an adm-zip instance. Second, you’ll invoke the module’s addFile() method to add the file in the ZIP. Finally, you’ll save the ZIP archive in the local system.

      Create another file file4.txt with dummy content repeated 600,000 lines:

      • yes "dummy content" | head -n 600000 > file4.txt

      Create and open updateArchive.js in your text editor:

      Require in the adm-zip module and the fs module that allows you to work with files in your updateArchive.js file:

      const AdmZip = require("adm-zip");
      const fs = require("fs").promises;
      

      You require in the promise-based version of the fs module version, which allows you to write asynchronous code. When you invoke an fs method, it will return a promise.

      Next in your updateArchive.js file, add the following highlighted code to add a new file to the ZIP archive:

      zip_app/updateArchive.js

      const AdmZip = require("adm-zip");
      const fs = require("fs").promises;
      
      async function updateZipArchive(filepath) {
        try {
          const zip = new AdmZip(filepath);
      
          content = await fs.readFile("./file4.txt");
          zip.addFile("file4.txt", content);
          zip.writeZip(filepath);
          console.log(`Updated ${filepath} successfully`);
        } catch (e) {
          console.log(`Something went wrong. ${e}`);
        }
      }
      
      updateZipArchive("./test.zip");
      

      updateZipArchive is an asynchronous function that reads a file in the filesystem and adds it to an existing ZIP. In the function, you create an instance of adm-zip with the ZIP archive file path in the filepath as a parameter. Next, you invoke the fs module’s readFile() method to read the file in the file system. The readFile() method returns a promise, which you resolve with the await keyword (await is valid in only asynchronous functions). Once resolved, the method returns a buffer object, which contains the file contents.

      Next, you invoke the addFile() method from adm-zip. The method takes two arguments. The first argument is the filename you want to add to the archive, and the second argument is the buffer object containing the contents of the file that the readFile() method reads.

      Afterwards, you invoke adm-zip module’s writeZip() method to save and write new changes in the ZIP archive. Once that’s done, you call the console.log() method to log a success message.

      Finally, you invoke the updateZipArchive() function with the Zip archive file path as an argument.

      Save and exit your file. Run the updateArchive.js file with the following command:

      You’ll see output like this:

      Output

      Updated ./test.zip successfully

      Now, confirm that the ZIP archive contains the new file. Run the readArchive.js file to list the contents in the ZIP archive with the following command:

      You’ll receive the following output:

      file1.txt
      file2.txt
      file3.txt
      file4.txt
      underwater.png
      

      This confirms that the file has been added to the ZIP.

      Now that you can add a file to an existing archive, you’ll extract the archive in the next section.

      In this step, you’ll read and extract all contents in a ZIP archive into a directory. To extract a ZIP archive, you’ll instantiate adm-zip with the archive file path. After that, you’ll invoke the module’s extractAllTo() method with the directory name you want your extracted ZIP contents to reside.

      Create and open extractArchive.js in your text editor:

      Require in the adm-zip module and the path module in your extractArchive.js file:

      zip_app/extractArchive.js

      const AdmZip = require("adm-zip");
      const path = require("path");
      

      The path module provides helpful methods for dealing with file paths.

      Still in your extractArchive.js file, add the following highlighted code to extract an archive:

      zip_app/extractArchive.js

      const AdmZip = require("adm-zip");
      const path = require("path");
      
      async function extractArchive(filepath) {
        try {
          const zip = new AdmZip(filepath);
          const outputDir = `${path.parse(filepath).name}_extracted`;
          zip.extractAllTo(outputDir);
      
          console.log(`Extracted to "${outputDir}" successfully`);
        } catch (e) {
          console.log(`Something went wrong. ${e}`);
        }
      }
      
      extractArchive("./test.zip");
      

      extractArchive() is an asynchronous function that takes a parameter containing the file path of the ZIP archive. Within the function, you instantiate adm-zip with the ZIP archive file path provided by the filepath parameter.

      Next, you define a template literal. Inside the template literal placeholder (${}), you invoke the parse() method from the path module with the file path. The parse() method returns an object. To get the name of the ZIP file without the file extension, you append the name property to the object that the parse() method returns. Once the archive name is returned, the template literal interpolates the value with the _extracted string. The value is then stored in the outputDir variable. This will be the name of the extracted directory.

      Next, you invoke adm-zip module’s extractAllTo method with the directory name stored in the outputDir to extract the contents in the directory. After that, you invoke console.log() to log a success message.

      Finally, you call the extractArchive() function with the ZIP archive path.

      Save your file and exit the editor, then run the extractArchive.js file with the following command:

      You receive the following output:

      Output

      Extracted to "test_extracted" successfully

      Confirm that the directory containing the ZIP contents has been created:

      You will receive the following output:

      Output

      createArchive.js file4.txt package-lock.json readArchive.js test.zip updateArchive.js extractArchive.js node_modules package.json test test_extracted

      Now, navigate into the directory containing the extracted contents:

      List the contents in the directory:

      You will receive the following output:

      Output

      file1.txt file2.txt file3.txt file4.txt underwater.png

      You can now see that the directory has all the files that were in the original directory.

      You’ve now extracted the ZIP archive contents into a directory.

      Conclusion

      In this tutorial, you created a ZIP archive, listed its contents, added a new file to the archive, and extracted all of its content into a directory using adm-zip module. This will serve as a good foundation for working with ZIP archives in Node.js.

      To learn more about adm-zip module, view the adm-zip documentation. To continue building your Node.js knowledge, see How To Code in Node.js series



      Source link

      How To Work with Numbers in PHP


      The author selected Open Sourcing Mental Illness Ltd to receive a donation as part of the Write for DOnations program.

      Introduction

      Numbers are extremely common in programming. They are used to represent things like screen size dimensions, geographic locations, money, points, the amount of time that passes in a video, positions of game avatars, and colors through assigning numeric codes.

      Being able to effectively perform mathematical operations in programming is an important skill to develop because of how frequently you’ll be working with numbers. Though a high-level understanding of mathematics can certainly help you become a better programmer, it is not a prerequisite. If you don’t have a background in mathematics, try to think of math as a tool to accomplish what you would like to achieve, and as a way to improve your logical thinking.

      We’ll be working with the two numeric data types in PHP, integers and floats:

      • Integers are whole numbers that can be positive, negative, or 0 (…, -1, 0, 1, …).
      • Floating point numbers, or floats, are real numbers that contain a decimal point (as in 9.0 or -2.25).

      This tutorial will go over many different operators that can be used with numerical data types in PHP, as well as how PHP handles “type juggling” and built-in math functions.

      Operators

      An operator is something that takes one or more values (or expressions, in programming jargon) and yields another value (so that the construction itself becomes an expression). Operators are used for basic decision making, such as instructing a program to perform an action based on a value.

      Assignment Operator

      The most basic operator is the assignment operator, a single equals sign: =. This assignment operator is used when setting the value for a variable. A variable is like a box. Many different things may be stored in a box. Additional items may be added to the box. The items in the box can be rearranged or each given a sticker. The box may also be emptied and something new can be added to the box. This is exactly what happens when a variable is used in code. The variable is given a name, and that named variable is assigned a value:

      $box=3;
      var_dump($box);
      $box="Hello";
      var_dump($box);
      

      To see the variable type along with the value, the var_dump() function is used instead of echo. The variable named $box is assigned an int with a value of 3. Then that same $box variable is assigned a new value of "Hello". This is the same as emptying the box and adding something new. Now when the var_dump() function is called, we get entirely different information about the value of the $box variable:

      Output

      int(3) string(5) "Hello"

      After the first assignment, the $box variable contains the integer value of 3. After the second assignment, the $box variable contains a string of 5 characters matching “Hello”.

      To make our $box more useful, let’s take a look at our next type of operator.

      Arithmetic Operators

      PHP has arithmetic operators that work the same in a computer program as they do on a calculator, or even pen and paper. The important aspect to pay attention to is the symbol used for the operation. Let’s take a look at the most common arithmetic operators.

      Addition (+): Start with the first value and add the next value to that number. This can performed using either a numerical value itself or the variable that contains the value:

      $start=10;
      var_dump($start+3);
      

      The result is the sum of this equation:

      Output

      int(13)

      Subtraction (-): Start with the first value and subtract, or remove, the next value from the previous value:

      $start=10;
      var_dump($start-3);
      

      The result is the difference of this equation:

      Output

      int(7)

      Multiplication (*): Start with the first value and multiply it with the next value:

      $start=10;
      var_dump($start*3);
      

      This is the same as adding the first number as many times as the second number:

      $start=10;
      var_dump($start+$start+$start);
      

      Both of which give us the same result, the product of the equation:

      Output

      int(30)

      Division (/): How many times can the second value go into the first value:

      $start=10;
      var_dump($start/3);
      

      The result is the quotient of this equation:

      Output

      float(3.3333333333333)

      In this case the result is given as a float instead of an integer because 3 does not go into 10 evenly. We can tell PHP to give us the result as just the integer value by adding (int), which will ignore anything after the .:

      $start=10;
      var_dump((int) $start/3);
      

      Giving the results as an integer, which is a whole number:

      Output

      int(3)

      When the leftover value, or remainder, of a division equation is desired, that is called the modulo (%):

      $start=10;
      var_dump($start%3);
      var_dump(3%$start);
      

      The first var_dump gives us the remainder of the previous division equation. When the equation is reversed, the modulo returns 3 because 10 goes into 3 zero times, leaving the original 3 as the remainder:

      Output

      int(1) int(3)

      The modulo is often used when creating a pattern based on odd or even rows. When determining whether an integer count of a row is odd or even, use %2:

      var_dump(10%2);
      var_dump(11%2);
      

      An even integer will always give a result of 0, because even numbers are divisible by 2, while an odd integer will always give the result of 1 because it is not evenly divisible:

      Output

      int(0) int(1)

      PHP is able to perform complex calculations quickly and provides many more tools to write whichever calculations are needed. Exponents, percentage, square root, and many more operations are possible. Before we take a look at some of these mathematical functions, let’s explore another type of operator, which combines the assignment and arithmetic operators.

      Arithmetic Assignment Operators

      Say there is a basket with 10 apples. To represent this in code we could write $basket = 10. Next we pick an additional 5 apples and place them in the basket. Instead of using the integer 10, we can use the value of 10 that is stored in the $basket variable: $basket = $basket + 5. While this is technically correct, it is rather redundant. We just want to add 5 more apples to the existing basket. That’s where arithmetic assignment operators come in. Instead of repeating the variable, we can write $basket += 5. This works exactly like the previous expression; it tells the code to:

      1. Take the value of $basket
      2. Add 5 to that value
      3. Reassign the new value to $basket

      You can use this same principle with other arithmetic operators:

      Expression Result (assuming $i = 10)
      $i += 5 Add 10 + 5; Result: $i = 15
      $i -= 5 Subtract 10 – 5; Result: $i = 5
      $i *= 5 Multiply 10 * 5; Result: $i = 50
      $i /= 5 Divide 10 / 5; Result: $i = 2

      If Sammy decides to chomp on some of the apples in our basket, we could use something like $basket -= 6, which would leave us with the integer 9 assigned to $basket. So far, the program looks something like this:

      $basket = 10;
      $basket += 5;
      $basket -= 6;
      echo $basket;
      

      When $basket is echoed in the final line, it gives the final value:

      Output

      9

      While Sammy may be able to eat many apples at once, I can only eat a single apple at a time.

      Increment Operator

      For increasing a number by 1, PHP provides a separate increment operator, which is a double plus sign (++). This can be use to increment a variable independently (on its own line) or directly in an expression. Let’s go back to the apple basket example where the current value of the $basket variable is 9:

      ++$basket;
      echo $basket;
      

      The first line adds 1 to the current value, which was 9, and the next line gives the result:

      Output

      10

      We can do the same thing in a single line:

      echo ++$basket;
      

      First it adds 1 to the current value, which was 10, and the next line gives the result:

      Output

      11

      When the value of $basket is output once more:

      echo $basket;
      

      It confirms that the $basket variable was actually updated in the previous line, not just added to the output result:

      Output

      11

      In each of the previous lines, the increment operator was used before the variable. This pre-incremented action is applied to the variable before any other action, such as the echo command. Using ++$basket is the same as writing $basket += 1. The increment operator can also be used after the variable as a post-increment. When the variable is set independently, the order doesn’t matter, but when it is used within an expression, the order becomes important. Let’s repeat those same lines, only this time putting the increment operator after the variable:

      $basket++;
      echo $basket;
      

      The first line adds 1 to the current value, which was 11, and the next line gives the result. This works exactly the same as the pre-increment lines in the previous example:

      Output

      12

      Now we get to the difference with a post-incremented value:

      echo $basket++;
      

      The echo action happens before the value is incremented, so the result of the second echo still shows the value of $basket before it was increase by 1:

      Output

      12

      A final echo command confirms that the variable was actually incremented after the echo was processed:

      echo $basket;
      

      Showing that the final value of $basket:

      Output

      13

      Along with the increment operator, PHP give us the ability to decrease a value by 1 using the decrement operator.

      Decrement Operator

      To decrease a value by 1, we can use the decrement operator, which is a double minus sign (--). As with the increment operator, this operator can be added before or after the variable, but position may affect the output of the program:

      echo --$basket; # Pre-decrement
      echo $basket--; # Post-decrement
      echo $basket;
      

      The first line removes 1 from the current value, which was 13, before the echo command is executed. The next line executes the echo command before the post-decrement operator is evaluated, leaving the output the same. Once again, the final echo demonstrates that the value of $basket was actually decremented in the previous line, giving us a decreased value:

      Output

      12 12 11

      Keep this order of the operator in mind as we take a look at how operator precedence can play an important role in our results.

      Operator Precedence

      The precedence of an operator specifies how “tightly” it binds two expressions together. This is often referred to as the “order of operations.” This means that different operators are given greater importance and are applied first. When evaluating a mathematical equation, multiplication and division are always performed before addition and subtraction. For example:

      echo 1 + 5 * 3;
      

      In this expression, the multiplication (*) operator has a higher precedence than the addition (+) operator and is therefore evaluated first: 5 * 3 = 15. The addition is then performed as 1 + 15 = 16. This provides an end result of 16:

      Output

      16

      If the order of operations was not followed, 1 + 5 would be evaluated first and then that result would have the multiplication applied, giving us 6 * 3 = 18.

      The increment and decrement operators cannot be applied to a number; they are used with variables. We can, however, add variables to an equation in which we increment or decrement that value. When these incremented or decremented variables are used, the equation is either performed before or after the increment or decrement operation:

      $my_num = 8;
      echo 7 + $my_num++ + 9;
      echo $my_num;
      echo 7 + --$my_num + 9;
      echo $my_num;
      

      In the first echo line, the mathematical expression is performed using the original value of $my_num before the post-increment operator increases the value. It’s as if we had written echo 7 + 8 + 9;, which gives us the result of 24. We see from the second echo that $my_num is now set to 9. The second mathematical equation is performed after the pre-decrement operation, which means that the value of $my_num is now set to 8, and the mathematical equation itself is the same. After the mathematical equation is executed, the post-decrement operator is executed, giving the final result of the $my_num variable:

      Output

      24 9 24 8

      Grouping Operations

      Parentheses always have the highest level of precedence, providing a way to group operations or force precedence. For example, adding parenthesis to the previous equation:

      echo (1 + 5) * 3;
      

      Because the items within the parenthesis are evaluated before the multiplication, the result is different:

      Output

      18

      To summarize the Operator Precedence of Mathematical Equations:

      1. Parentheses are evaluated from left to right.
      2. Multiplication and division are evaluated from left to right.
      3. The final result is evaluated using any addition and subtraction from left to right.

      Type Juggling

      PHP does not define a variable type when a variable is declared or set. Instead, a variable’s type is determined by the context in which the variable is used. We can use var_dump() to show the details of a variable, including its type:

      $my_var="string";
      var_dump($my_var);
      $my_var = 1;
      var_dump($my_var);
      

      When a string value is assigned to a variable, that variable becomes a string. If an integer value is then assigned to that same variable, it becomes an integer:

      Output

      string(6) "string" int(1)

      PHP will also set the type based on the evaluation of an equation:

      $var1 = 1.2;
      $var2 = 2;
      $var3 = 12;
      var_dump($var1 * $var2);
      var_dump($var3 * $var2);
      var_dump($var1, $var2, $var3);
      

      If either operand is a float, then both operands are evaluated as floats, and the result will be a float, as show with the first var_dump. Otherwise, the operands will be interpreted as integers, and the result will also be an integer, as shown with the second var_dump:

      Output

      float(2.4) int(24) float(1.2) int(2) int(12)

      From the third var_dump we see that this does not change the types of the operands themselves; the only change is in how the operands are evaluated and the resulting type of the expression itself.

      Other data types such as strings and Booleans may also be converted to a number. This can cause much confusion, so it is best avoided. Although PHP will produce a notice or warning, it will still do its best to “juggle” the variables into a type that can be evaluated. For example:

      Expression Result Type Juggling
      2 * false 0 the boolean is converted to the integer 0
      2 * true 2 the boolean is converted to the integer 1
      2 * 'hi' 0 the string is converted to the integer 0
      2 * '1' 2 the string is converted to the integer 1

      While the loose typing of PHP can make it faster and easier to write code, it often makes it more difficult to track down problems. Be conscious of the variable types used in an application.

      Math Functions

      A function is a block of statements that can be used repeatedly in a program. PHP comes with many built-in functions that allow us to preform additional math calculations.

      When working with both positive and negative numbers, you can get the absolute value of the number with the abs function:

      echo abs(-1.3);
      

      This ignores the + or - before a number and just returns the number itself:

      Output

      1.3

      There are multiple options when estimating with numbers or retrieving the integer value of a float:

      echo round(1.3);
      echo round(1.5);
      echo ceil(1.3);
      echo floor(1.5);
      

      The round function will return the closest whole number, with .5 evaluating to the higher number. The ceil function will always round up, while the floor function will always round down:

      Output

      1 2 2 1

      The ratio of any circle is the same. Because this it true, the circumference of any circle can be determined by multiplying its diameter by a special number known as pi (Π):

      echo pi();
      echo 4 * pi();
      

      The pi function in PHP returns the first 14 digits of pi, since pi is an irrational number, meaning that its decimal form never ends. This function can be used to calculate circumference of a circle with a diameter of 4:

      Output

      3.1415926535898 12.566370614359

      Whether it’s flipping a coin or rolling a die, when the goal for a result is up to chance, random numbers provide the tool. PHP provides the rand function to return this unpredictable, random result:

      echo rand();
      

      This function will display a number between 0 and the getrandmax configured on the machine. When you need a little less randomness, or want to increase the max number, you may specify the min and max inclusively. To return a random three-digit number:

      var_dump(rand(100, 999));
      

      Each time this rand function is called, it will return a three-digit number between 100 and 999.

      The calculation to return a random number is not actually random, so when it comes to security and cryptography, PHP provides more cryptographically secure functions. To generate a cryptographic random integer that is suitable for unbiased results such as shuffling cards or drawing a winning number, use the random_int function:

      var_dump(random_int(-999, 999));
      

      With random_int you must specify the inclusive min and max numbers. Both rand and rand_int accept negative numbers.

      When generating cryptographically secure values for salts, keys, or initialization vectors that can take a byte string, use random_bytes with the specified string length:

      var_dump(random_bytes(20));
      

      You will get a new random byte string each time, which will look something like:

      Output

      string(20) "q8?Ud;??W?p4?C????"

      There are many more built-in math functions for PHP. Check out the php.net documentation to learn more.

      Conclusion

      This tutorial covered many of the operators you’ll use when working with the integer and float numeric data types. It also demonstrated how the precedence and position of operators can affect the outcome. These outcomes brought us to the way PHP “juggles” variable types and the issues that can cause. Finally a brief introduction to built-in functions expanded the mathematical choices available to an application. To learn more about other data types, take a look at Understanding Data Types in PHP.



      Source link

      Kubernetes Requests, Limits, and Autoscalers: How They (Sometimes Don’t) Work Together


      Video

      About the Talk

      Did you know that setting the wrong requests and limits for pods can crash your entire cluster?

      See a breakdown of the interconnected parts involved with automating a Kubernetes configuration, from defining requests and limits, to understanding the complex nature of autoscalers and schedulers.

      Learn best practices on balancing these automated tools to assist rather than hinder your application infrastructure.

      What You’ll Learn

      • What are requests and limits? Why do we use them?
      • How does the Cluster Autoscaler work?
      • How does the Horizontal Pod Autoscaler work?
      • How can you set intelligent requests and limits in YOUR cluster?

      This Talk Is Designed For

      New and experienced Kubernetes developers that want to learn more about how these complex Kubernetes services interact.

      Resources

      Slides

      Kubernetes on DigitalOcean: Docs

      Requests & Limits Crash Course by Henning Jacobs [Video]

      CPU limits and aggressive throttling (The CFS bug he mentions has been patched.)

      HPA Algorithm details

      Using the Vertical Pod Autoscaler

      Kubernetes best practices: resource requests and limits

      Kubernetes best practices: configuring liveness probes

      CPU Management [Kubernetes Documentation]



      Source link