Comprehensive-rust: Rust Course Used By The Android Team at Google

Comprehensive Rust 🦀

This repository has the source code for Comprehensive Rust 🦀, a four day Rust course developed by the Android team. The course covers all aspects of Rust, from basic syntax to generics and error handling. It also includes Android-specific content on the last day.

Course Format and Target Audience

The course is used internally at Google when teaching Rust to experienced software engineers. They typically have a background in C++ or Java.

The course is taught in a classroom setting and we hope it will be useful for others who want to teach Rust to their team. The course will be less useful for self-study since you miss out on the discussions happening in the classroom. You don't see the questions and answers and you don't see the compiler errors we trigger when going through the code samples. We hope to improve on this via speaker notes and by publishing videos.

Building

The course is built using mdBook and its Svgbob plugin. Install both tools with

$ cargo install mdbook
$ cargo install mdbook-svgbob

Then run

$ mdbook test

to test all included Rust snippets. Run

$ mdbook serve

to start a web server with the course. You'll find the content on http://localhost:3000. You can use mdbook build to create a static version of the course in the book/ directory.

Contact

For questions or comments, please contact Martin Geisler or start a discussion on GitHub. We would love to hear from you.

Read the course at https://google.github.io/comprehensive-rust/.

Download Details:

Author: google
Source Code: https://github.com/google/comprehensive-rust 
License: Apache-2.0 license

#rust #classroom #course #guide #google 

Comprehensive-rust: Rust Course Used By The Android Team at Google
Nat  Grady

Nat Grady

1673852280

Quick Guide: 4-minute to Java Loops

Whether you use a while loop, a do while loop, or an infinite loop, understanding how loops work is vital to Java programming.

A while loop performs a set of tasks for as long as some predefined condition is true. This is considered a control structure that directs the flow of a program. It's a way for you to tell your code what to do by defining a condition that it can test, and take action based on what it finds. The two kinds of while loops in Java are while and do while.

Java while loop

A while loop is meant to iterate over data until some condition is satisfied. To create a while loop, you provide a condition that can be tested, followed by the code you want to run. Java has several built-in test functions, the simplest of which are mathematical operators (<, >, ==, and so on):

package com.opensource.example;

public class Example {
  public static void main(String[] args) {

  int count = 0;
  while (count < 5) {
    System.out.printf("%d ", count);
    count++;
    }
  }
}

In this simple example, the condition is that the variable count is less than 5. Because count is instantiated at 0, and then incremented by 1 in the code within the while loop, the program iterates a total of 5 times:

$ java ./while.java
0 1 2 3 4

Before it can iterate a sixth time, the condition is no longer true, so the loop ends.

The conditional statement for a while loop is vital. Getting it wrong could mean that your loop never executes. For instance, suppose you had set count == 5 as the condition:

  while (count == 5) {
    System.out.printf("%d ", count);
    count++;

When you run the code, it builds and runs successfully, but nothing happens:

$ java ./while.java
$

The loop has been skipped because count was set to 0, and it's still 0 at the moment the while loop is first encountered. The loop never has a reason to start and count is never incremented.

The reverse of this is when a condition starts as true and can never be false, this results in an infinite loop.

Java do while loop

Similar to the while loop, a do while loop tests for the conditional at the end, not the beginning, of each iteration. With this, the code in your loop runs at least once because there's no gateway to entry, only a gateway to exit:

package com.opensource.example;

public class Example {
  public static void main(String[] args) {

  int count = 9;
  do {
      System.out.printf("%d ", count);
      count++;
    } while(count == 5);
  }
}

In this sample code, count is set to 9. The condition for the loop to repeat is that count is equal to 5. But 9 isn't equal to 5. That check isn't performed until the end of the first iteration, though:

$ java ./do.java
9

Java infinite loops

An infinite loop, as its name suggests, never ends. Sometimes they're created by mistake, but an infinite loop does have a valid use case. Sometimes you want a process to continue indefinitely (that's functionally infinite because you can't guarantee when you need it to stop), and so you might set your condition to something impossible to meet.

Suppose you've written an application that counts the number of zombies remaining in your neighborhood during a zombie apocalypse. To simulate uncertainty over how many loops are required to get to 0 zombies, my demo code retrieves a timestamp from the operating system and sets the value of the counter (c) to some number derived from that timestamp. Because this is a simple example and you don't really want to get trapped in an infinite loop, this code counts down to zero and uses the break function to force the loop to end:

package com.opensource.example;

public class Example {
  public static void main(String[] args) {

  long myTime = System.currentTimeMillis();

  int c;

  if ( myTime%2 == 0 ) {
      c = 128;
  } else {
      c = 1024;
  }

  while(true) {
    System.out.printf("%d Zombies\n", c);

    // break for convenience
    if ( c <= 0 ) { break; }
    c--;
    }
  }
}

You may have to run it a few times to trigger a different total number of zombies, but sometimes your program iterates 128 times and other times 1,024 times:

$ java ./zcount.java
1024 Zombies
1023 Zombies
[...]
0 Zombies

Can you tell why the loops end at 0 and not at -1?

Java loops

Loops give you control over the flow of your program's execution. Iteration is common in programming, and whether you use a while loop, a do while loop, or an infinite loop, understanding how loops work is vital.

Original article source at: https://opensource.com/

#java #loops #guide 

Quick Guide: 4-minute to Java Loops
Sheldon  Grant

Sheldon Grant

1672835220

Beginner’s Guide to PHP: Introducing

The following article is an excerpt from PHP & MySQL: Novice to Ninja, 7th Edition, a hands-on guide to learning all the tools, principles, and techniques needed to build a professional web application. In this second tutorial in the series, you’ll learn the basics of PHP, including statements, variables, operators, comments, and control structures.

Now that you have your server up and running, it’s time to write your first PHP script. PHP is a server-side language. This concept may be a little difficult to grasp, especially if you’ve only ever designed websites using client-side languages like HTML, CSS, and JavaScript.

A server-side language is similar to JavaScript in that it allows you to embed dynamically generated content into the HTML code of a web page, giving you greater control over what appears in the browser window than HTML alone can provide. The key difference between JavaScript and PHP is the stage at which the code is run.

Client-side languages like JavaScript are read and executed by the web browser after downloading the web page (embedded programs and all) from the web server. In contrast, server-side languages like PHP are run by the web server, before the web page is sent to the browser. Whereas client-side languages give you control over how a page behaves once it’s displayed by the browser, server-side languages let you generate customized pages on the fly before they’re even sent to the browser.

Once the web server has executed the PHP code embedded in a web page, the result takes the place of the PHP code in the page. All the browser sees is standard HTML code when it receives the page. That’s why PHP is called a “server-side language”: its work is done on the server.

Note: in the early days of the Web — and when the first edition of this book was published! — JavaScript was a client-side scripting language used mainly in the browser. Then along came technologies like Ajax, which allowed JavaScript to communicate with the server. And more recently still, JavaScript has been used both in the browser and on the server to create database-driven apps. While these new uses for JavaScript offer exciting possibilities, there’s still very much a place for PHP — as this book sets out to demonstrate!

PHP code is written in PHP tags. Like most HTML tags, PHP has a start tag and and end tag: <?php and ?> respectively. Anything inside these PHP tags is treated as PHP code and run on the server.

PHP code must be placed in a file with a .php extension. When someone connects to the server and asks it to load a file with a .php extension, the server then runs it as a PHP script. If you put PHP tags in a file with a .html or any extension other than .php, the web server won’t run any PHP code, and the PHP code will be sent directly to the browser — which doesn’t understand PHP code!

Let’s take a look at a PHP script.

Example: PHP-RandomNumber

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Random Number</title>
  </head>
  <body>
    <p>Generating a random number between 1 and 10:
      <?php
      echo rand(1, 10);
      ?>
    </p>
  </body>
</html>

To run this code, save it as random.php in the public directory and navigate to https://v.je/random.php.

Most of this is plain HTML. Only the line between <?php and ?> is PHP code. <?php marks the start of an embedded PHP script and ?> marks its end. The web server is asked to interpret everything between these two delimiters and convert it to regular HTML code before it sends the web page to the requesting browser. If you right-click inside your browser and choose View Source (the label may be different depending on the browser you’re using) you can see that the browser is presented with something like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Random Number</title>
  </head>
  <body>
    <p>Generating a random number between 1 and 10:
      5
    </p>
  </body>
</html>

There’s no HTML file on the server that contains this exact code. This HTML is generated dynamically on the server before being sent to the browser.

Try running the script a couple of times and notice how the number changes. PHP code has been used to generate a random number, but all signs of the PHP code have disappeared when viewing the source in the browser. In its place, the output of the script has appeared, and it looks just like standard HTML. This example demonstrates several advantages of server-side scripting:

  • Security. In the example above, we placed a random number generated by the web server into the web page. If we had inserted the number using JavaScript, the number would be generated in the browser and someone could potentially amend the code to insert a specific number.
  • No browser compatibility issues. PHP scripts are interpreted by the web server alone, so there’s no need to worry about whether the language features you’re using are supported by the visitor’s browser.
  • Access to server-side resources. The code on the server can do anything; it’s not limited to the capabilities of the browser. The resulting HTML could be generated from a database or an Excel file, or it could be the result of a calculation, such as the total of the user’s shopping cart.
  • Reduced load on the client. JavaScript can delay the display of a web page significantly (especially on mobile devices!), since the browser must download and then run the script before it can display the web page. With server-side code, this burden is passed to the web server, which you can make as beefy as your application requires (and your wallet can afford).
  • Choice. When writing code that’s run in the browser, the browser has to understand how to run the code given to it. All modern browsers understand HTML, CSS and JavaScript. To write some code that’s run in the browser, you must use one of these languages. By running code on the server that generates HTML, you have a choice of many languages — one of which is PHP.

Basic Syntax and Statements

PHP syntax will be very familiar to anyone with an understanding of JavaScript, C, C++, C#, Objective-C, Java, Perl, or any other C-derived language. But if these languages are unfamiliar to you, or if you’re new to programming in general, there’s no need to worry.

A PHP script consists of a series of commands, or statements. Each statement is an instruction that must be followed by the web server before it can proceed to the next instruction. PHP statements, like those in the aforementioned languages, are always terminated by a semicolon (;).

This is a typical PHP statement:

echo 'This is a <strong>test</strong>!';

This is an echo statement, which is used to generate content (usually HTML code) to send to the browser. An echo statement simply takes the text it’s given and inserts it into the page’s HTML code at the position where the PHP script was located.

In this case, we’ve supplied a string of text to be output: This is a <strong>test</strong>!. Notice that the string of text contains HTML tags (<strong>and </strong>), which is perfectly acceptable.

So, if we take this statement and put it into a complete web page, here’s the resulting code.

Example: PHP-Echo

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Test page</title>
  </head>
  <body>
    <p><?php echo 'This is a <strong>test</strong>!'; ?></p>
  </body>
</html>

If you place this file on your web server and then request it using a web browser, your browser will receive this HTML code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Test page</title>
  </head>
  <body>
    <p>This is a <strong>test</strong>!</p>
  </body>
</html>

The random.php example we looked at earlier contained a slightly more complex echo statement:

echo rand(1, 10);

You’ll notice that, in the first example, PHP is given some text to print directly, and in the second, PHP is given an instruction to follow. PHP tries to read anything that exists outside quotes as an instruction it must follow. Anything inside quotes is treated as text — or, to use the technical term, as a string. PHP doesn’t process strings as commands to follow. They’re treated as data in the application. You can do things with them, such as sending them to the browser, but PHP doesn’t treat one string differently from another.

So the following code will pass the string This is a <strong>test</strong>! directly to the echo command:

echo 'This is a <strong>test</strong>!';

A string is signified using a start quote and an end quote. PHP will see the first ' as the start of the string and find the next ' and use that as the end of the string.

Anything outside of quotes is treated as a series of commands to run. The following is not valid code:

echo This is a <strong>test</strong>!;

Because the quotes have been removed, PHP will first try to run the command This, then the command is, followed by the command a, and so on. As none of these are valid commands in PHP, the above code would produce an error message. If you want to treat something as text, remember to put quotes around it!

In contrast, the following code will run a valid command — the built-in “function” rand — to generate a random number and then pass the result to the echo command:

echo rand(1, 10);

A function is a special type of command that performs a specific task. Behind the scenes, PHP will do some processing and then generate a result. In this case, the rand function will produce a random number, but different functions perform different tasks.

You can quickly identify if something is a function because it’s followed by parentheses. PHP has many built-in functions that let you do all sorts of things, such as sending email and working with information stored in various types of databases.

PHP won’t try to run anything that’s inside a string. The following code won’t process the rand function:

echo 'rand(1, 10)';

PHP will see 'rand(1, 10)' as a string, and will send the text rand(1, 10) to the browser, which probably isn’t what you’d want to do. It’s important to understand the difference between a string and code. PHP will see any text outside quotes as a series of commands it should follow. Anything inside quotes is a string and is data that PHP will work with.

PHP doesn’t try to understand strings. They can contain any characters in any order. But code (anything not inside quotes) — which is essentially a series of instructions — must follow a rigid structure for a computer to understand it.

Note: using a code editor with syntax highlighting makes it easy to quickly see if something is a string or code. Strings will be a different color from code that needs to be processed.

The image below shows simple code highlighting in the Visual Studio Code editor.

An example of code highlighting in VS Code

PHP supports both single quotes (') and double quotes (") to encase strings. For most purposes, they’re interchangeable. PHP developers tend to favor single quotes, because we deal with HTML code a lot, which tends to contain a lot of double quotes. For example:

echo '<a href="http://www.sitepoint.com">Click here</a>';

If double quotes were used at each end here, we’d need to tell PHP that the quote after href= is not the end of the string by placing a \ before it (known as an escape character) and do the same with any double quotes we actually wanted to send to the browser as part of the HTML:

echo "<a href=\"http://www.sitepoint.com\">Click here</a>";

For this reason, PHP developers use single quotes, although there are some differences between single and double quotes. For our purposes here, though, they’re effectively interchangeable.

A function can be thought of as a miniature program within your program. You can instruct PHP to run the function by using its name (such as rand in our example earlier) followed by parentheses. The instruction rand(1, 10) tells PHP to run the function with the name rand. Running a function is also more commonly referred to as calling a function.

Most functions in PHP return a value when they’re called. Once the value is returned, PHP behaves as if you’d actually just typed that returned value in your code instead. In the echo rand(1, 10); example, our echo statement contains a call to the rand function, which returns a random number as a string of text. The echo statement then outputs the value that was returned by the function call.

Every function in PHP can have one or more arguments that allow you to make the function behave in a slightly different way. The rand function takes two arguments: a minimum and maximum random number. By changing the values that are passed to the function, you’re able to change the way it works. For example, if you wanted a random number between 1 and 50, you could use this code:

echo rand(1, 50);

We surround the arguments with parentheses ((1, 50)) for two reasons. First, they indicate that rand is a function that you want to call. Second, they mark the beginning and end of a list of arguments — PHP statements that you wish to provide — in order to tell the function what you want it to do. In the case of the rand function, you need to provide a minimum and a maximum value. Those values are separated by a comma.

Later on, we’ll look at functions that take different kinds of arguments. We’ll also consider functions that take no arguments at all. These functions will still need the parentheses, even though nothing will be typed between them.

Variables, Operators, and Comments

Variables

Variables in PHP are identical to variables in most other programming languages. For the uninitiated, a variable can be thought of as a name given to an imaginary box into which any value may be placed. The following statement creates a variable called $testVariable (all variable names in PHP begin with a dollar sign) and assigns it a value of 3:

$testVariable = 3;

PHP is a loosely typed language. This means that a single variable may contain any type of data — be it a number, a string of text, or some other kind of value — and may store different types of values over its lifetime. If you were to type the following statement after the statement shown above, it would assign a new value to the existing $testVariable. While the $testVariable variable used to contain a number, it would now contain a string of text:

$testVariable = 'Three';

Once you have data stored in a variable, you can send it to the browser using the echo command from earlier:

$testVariable = 3;
echo $testVariable;

When this code runs, the digit “3” will be sent to the browser to be displayed on the page.

In addition to specific strings or numbers, it’s possible to store the result of a function and then use it later on in the script:

$randomNumber = rand(1, 10);
echo $randomNumber;

Operators

The equals sign we used in the last two statements is called the assignment operator, as it’s used to assign values to variables. (There’s a different way to actually indicate “equals” in PHP, as we’ll see below.) Other operators may be used to perform various mathematical operations on values:

$testVariable = 1 + 1;  // assigns a value of 2
$testVariable = 1 - 1;  // assigns a value of 0
$testVariable = 2 * 2;  // assigns a value of 4
$testVariable = 2 / 2;  // assigns a value of 1

From these examples, you can probably tell that + is the addition operator, - is the subtraction operator, * is the multiplication operator and / is the division operator. These are all called arithmetic operators, because they perform arithmetic on numbers.

Note: each of the arithmetic lines above ends with a “comment” after the semicolon. Comments enable you to describe what your code is doing. They insert explanatory text into your code — text that the PHP interpreter will ignore.

Single-line comments begin with //. A single-line comment can be on its own line or, as in the example above, it can be placed at the end of a line of code.

If you want a comment to span several lines, start it with /*, and end it with */. The PHP interpreter will ignore everything between these two delimiters. I’ll be using comments throughout the rest of this book to help explain some of the code I present.

One operator that sticks strings of text together is called the string concatenation operator:

$testVariable = 'Hi ' . 'there!';  // Assigns a value of 'Hi there!'

Variables may be used almost anywhere you use a value. Consider this series of statements:

$var1 = 'PHP';          // assigns a value of 'PHP' to $var1
$var2 = 5;              // assigns a value of 5 to $var2
$var3 = $var2 + 1;      // assigns a value of 6 to $var3
$var2 = $var1;          // assigns a value of 'PHP' to $var2
$var4 = rand(1, 12);    // assigns a value to $var4 using the rand() function
echo $var1;             // outputs 'PHP'
echo $var2;             // outputs 'PHP'
echo $var3;             // outputs '6'
echo $var4;             // outputs the random number generated above
echo $var1 . ' rules!'; // outputs 'PHP rules!'
echo '$var1 rules!';    // outputs '$var1 rules!'
echo "$var1 rules!"     // outputs 'PHP rules!'

Note the last two lines in particular. If you place a variable inside single quotes, it will print the name rather than the contents of the variable. In contrast, when using double quotes, the variable in the string is replaced with the variable’s contents.

Placing variables inside double quotes works in simple situations, but for most of this book it won’t be usable, as we won’t be using such simple code. So it’s a good idea to get used to the practice of concatenation (shown in the third-from-last line: echo $var1 . ' rules!';).

Control Structures

The examples of PHP code we’ve seen so far have been either one-statement scripts that output a string of text to the web page, or a series of statements that were to be executed one after the other in order. If you’ve ever written programs in other languages (such as JavaScript, Objective-C, Ruby, or Python), you already know that practical programs are rarely so simple.

PHP, just like any other programming language, provides facilities that enable you to affect the flow of control. That is, the language contains special statements that you can use to deviate from the one-after-another execution order that has dominated our examples so far. Such statements are called control structures. Don’t understand? Don’t worry! A few examples will illustrate it perfectly.

If Statements

The most basic, and most often used, control structure is the if statement. The flow of a program through an if statement can be visualized as shown below.

The logical flow of an if statement

Here’s what an if statement looks like in PHP code:

if (condition) {
  ⋮ conditional code to be executed if condition is true
}

This control structure lets us tell PHP to execute a set of statements only if some condition is met.

For example, we might want to create a game that mimics a dice roll and in which you have to roll a six to win. The dice roll can be modeled using the rand() function we used earlier, setting the minimum and maximum from 1 to 6:

$roll = rand(1, 6);

echo 'You rolled a ' . $roll;

To print out a message if the player rolls a six and wins, you can use an if statement.

Example: PHP-DiceRoll

$roll = rand(1, 6);

echo 'You rolled a ' . $roll;

if ($roll == 6) {
  echo 'You win!';
}

The == used in the condition above is the equals operator, which is used to compare two values to see whether they’re equal. This is quite different from using a single =, which is used for assignment, and can’t be used for comparison.

The if statement uses braces ({ and }) to surround the code you want to run only when the condition is met. You can place as many lines of code as you like between the braces; the code will only be run when the condition is met. Any code placed after the closing brace (}) will be run all the time:

$roll = rand(1, 6);

echo 'You rolled a ' . $roll;

if ($roll == 6) {
  echo 'You win!'; // This line will only be printed if you roll a 6
}

echo 'Thanks for playing'; // This line will always be printed

Note: remember to type the double-equals (==). A common mistake among beginner PHP programmers is to type a condition like this with a single equals sign:

if ($roll = 6)     // Missing equals sign!

This condition is using the assignment operator (=) instead of the equals operator (==). Consequently, instead of comparing the value of $roll to the number 6, it will actually set the value of $roll to 6. Oops!

To make matters worse, the if statement will use this assignment operation as a condition, which it will consider to be true, so the conditional code within the if statement will always be executed, regardless of what the original value of $roll happened to be.

If you save this as diceroll.php and run the code, you’ll see the random number being generated. If you run it until you win, you’ll see this in the browser:

You rolled a 6You win!Thanks for playing

This isn’t very pretty. But because PHP outputs HTML, you can add some paragraph tags in order to format the output.

Example: PHP-DiceRoll-Formatted

$roll = rand(1, 6);

echo '<p>You rolled a ' . $roll . '</p>';

if ($roll == 6) {
  echo '<p>You win!</p>';
}

echo '<p>Thanks for playing</p>';

If you run the updated code, you’ll see that it now prints this in the browser:

You rolled a 6

You win!

Thanks for playing

This is much more user friendly. To make the game itself more user friendly, you might want to display a different message to people who didn’t roll a 6 and didn’t win. This can be done with an else statement. The else statement must follow an if, and will be run if the condition isn’t met.

Example: PHP-DiceRoll-Else

$roll = rand(1, 6);

echo '<p>You rolled a ' . $roll . '</p>';

if ($roll == 6) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}

echo '<p>Thanks for playing</p>';

Note: because the word didn't contains a single quote, it needs to be “escaped”. By preceding the single quote with a backslash (\), it tells PHP not to treat the ' in didn't as the end of the string.

With an else statement, one (and only one!) of the two blocks of code is guaranteed to run. Either the code in the if block will run if the condition is met, or the code in the else block will run if it isn’t.

Conditions can be more complex than a single check for equality. An if statement can contain more than one condition. For example, imagine if the game were adjusted so that both 5 and 6 were winning numbers. The if statement could be changed to the following.

Example: PHP-DiceRoll-Or

if ($roll == 6 || $roll == 5) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}

The double pipe operator (||) means “or”. The condition above is now met if either condition is met. This can be read as “If you roll a 6 or you roll a 5”.

However, this can be expressed in an even better way. if statements aren’t limited to using the equals (==) operator. They can also utilize the mathematical greater than (>) and less than (<) operators. The if statement above could also be done with a single expression.

Example: PHP-DiceRoll-Greater

if ($roll > 4) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}

The condition $roll > 4 will be met if the value stored in the $roll variable is greater than 4, allowing us to have 5 and 6 as winning numbers with a single condition. If we wanted 4, 5 and 6 as winning numbers, the condition could be changed to $roll > 3.

Like the “or” expression (||), there’s an “and” expression that’s only met when both conditions are met. We could expand the game to include two dice and require players to roll two sixes to win.

Example: PHP-DiceRoll-TwoDice

$roll1 = rand(1, 6);
$roll2 = rand(1, 6);

echo '<p>You rolled a ' . $roll1 . ' and a ' . $roll2 . '</p>';

if ($roll1 == 6 && $roll2 == 6) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}

echo '<p>Thanks for playing</p>';

The condition $roll1 == 6 && $roll2 == 6 will only be met if $roll1 == 6 is true and $roll2 == 6. This means that the player has to roll a 6 on both dice to win the game. If we changed the and (&&) to an or (||) — that is, if ($roll1 == 6 || $roll2 == 6) — the player would win if they rolled a 6 on either dice.

We’ll look at more complicated conditions as the need arises. For the time being, a general familiarity with if … else statements is sufficient.

Note: PHP also allows the use of or in place of || and and in place of &&. For example:

if ($roll == 6 or $roll == 5) { … }

There are some minor differences between the way or and || work that can lead to unexpected behavior. Generally speaking, avoid the “spelled out” operators. Sticking to the double pipe (||) and double ampersand (&&) will help prevent a number of confusing bugs.

Loops

Another type of control structure that’s very useful is a “loop”. Loops allow you to repeat the same lines of code over and over. Two important kind of loops are for loops and while loops. Let’s look at how they work.

For Loops

The for loop is used when you know up front how many times you need to run the same code. The image below shows the flow of a for loop.

The logical flow of a for loop

Here’s what it looks like in code:

for (declare counter; condition; increment counter) {
  ⋮ statement(s) to execute repeatedly as long as condition is true
}

The declare counter statement is executed once at the start of the loop. The condition statement is checked each time through the loop before the statements in the body are executed. The increment counter statement is executed each time through the loop after the statements in the body.

To count to ten using a for loop, you can use the following code:

for ($count = 1; $count <= 10; $count++) {
  echo $count . ' ';
}

This looks quite scary, as there’s a lot going on, but let me break it down for you:

  • $count = 1;. You’re already familiar with this code. It’s creating a variable called $count and setting the value to 1.
  • $count <= 10;. This is the condition. It can be read as “keep looping while $count is less than or equal to 10”.
  • $count++. This says “add 1 to the counter each time”. It’s identical to $count = $count + 1.
  • echo $count . ' ';. This prints the value of the counter followed by a space.

The condition in this example uses the <= operator. This acts similarly to the less than operator (<), but evaluates to true if the number being compared is less than or equal to the second. Other available operators include >= (greater than or equal) and != (not equal).

All three parts of the for loop are combined to produce the complete loop. Although, at first glance, the code seems a little more difficult to read, putting all the code that deals with controlling the loop in the same place actually makes it easier to understand once you’re used to the syntax. Many of the examples in this book will use for loops, so you’ll have plenty of opportunities to practice reading them.

You can change each part of the for loop to have different results. For example, let’s look at how to add 3 each time you can change the for loop by amending the last part.

The final part of the loop, $count++, says add 1 to the value of $count, and it’s a short way of writing $count = $count + 1.

By changing $count++ to $count = $count + 3, the for loop can be used to count in threes.

Example: PHP-For

for ($count = 1; $count <= 10; $count = $count + 3) {
  echo $count . ' ';
}

This will result in the following:

1 4 7 10

for loops can be combined with other statements — such as if statements — to perform specific tasks on each iteration. For example, rather than refreshing the page on our dice game each time, we might want to roll the dice ten times and print the results.

Example: PHP-DiceRoll-ManyDice

for ($count = 1; $count <= 10; $count++) {
  $roll = rand(1, 6);
  echo '<p>You rolled a ' . $roll . '</p>';

  if ($roll == 6) {
    echo '<p>You win!</p>';
  }
  else {
    echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
  }
}

echo '<p>Thanks for playing</p>';

This lets us roll the dice ten times without needing to refresh the page each time. Using a loop is functionally identical to copying and pasting the code ten times, and will produce the exact same outcome as the following:

$roll = rand(1, 6);
echo '<p>You rolled a ' . $roll . '</p>';

if ($roll == 6) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}

$roll = rand(1, 6);
echo '<p>You rolled a ' . $roll . '</p>';

if ($roll == 6) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}

$roll = rand(1, 6);
echo '<p>You rolled a ' . $roll . '</p>';

if ($roll == 6) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}

// and so on …

The computer doesn’t care which method you use: you can copy/paste or use a loop. It will just run the code. However, as a developer, you’ll quickly realize that a loop is the better choice. If you wanted to update the code to also allow 5 as a winning number, you’d need to update the condition in ten different places. Using a loop, you can change the code in one place and it will affect each iteration of the loop. If you ever find yourself copy/pasting code, there’s always a better way of achieving what you’re trying to do.

Note: given your new knowledge of loops, you should be able to start coding for yourself. Can you complete these challenges?

  • Challenge 1: print all the odd numbers from 21 to 99.
  • Challenge 2: print the nine times table up to 12 x 9 (9 18 27 … etc.) without using the multiplication operator (*) or an if statement.
  • Challenge 3: print the nine times table in this format:
1x9 = 9
2x9 = 18
… etc.

This time, you’ll need to use the multiplication operator!

While Loops

Another often-used PHP control structure is the while loop. Where the if … else statement allows us to choose whether or not to execute a set of statements depending on some condition, the while loop allows us to use a condition to determine how many times we’ll execute a set of statements repeatedly.

The following image shows how a while loop operates.

The logical flow of a while loop

Here’s what a while loop looks like in code:

while (condition) {
  ⋮ statement(s) to execute repeatedly as long as condition is true
}

The while loop works very similarly to an if statement. The difference arises when the condition is true and the statement(s) are executed. Instead of continuing the execution with the statement that follows the closing brace (}), the condition is checked again. If the condition is still true, the statement(s) are executed a second time, and a third, and will continue to be executed as long as the condition remains true. The first time the condition evaluates false (whether it’s the first time it’s checked, or the hundredth), the execution jumps immediately to the statement that follows the while loop, after the closing brace.

You can use a while loop to create a counter that has a similar result to a for loop.

Example: PHP-WhileCount

$count = 1;
while ($count <= 10) {
  echo $count . ' ';
  ++$count;
}

This works in exactly the same way as a for loop, and you’ll notice a lot of the same statements in different places. This code may look a bit frightening, I know, but let me talk you through it line by line:

  • $count = 1;. The first line creates a variable called $count and assigns it a value of 1.
  • while ($count <= 10). The second line is the start of a while loop, the condition being that the value of $count is less than or equal (<=) to 10.
  • {. The opening brace marks the beginning of the block of conditional code for the while loop. This conditional code is often called the body of the loop, and is executed over and over again, as long as the condition holds true.
  • echo $count . ' ';. This line simply outputs the value of $count, followed by a space.
  • ++$count;. The fourth line adds 1 to the value of $count. ++$count is a shortcut for $count = $count + 1. $count++ will also work here! The position of the ++ can be important, but in this case it doesn’t matter. If the ++ is before the variable name, the counter is incremented before the value is read. When $count is zero, the code echo ++$count; will print 1, whereas echo $count++; will print 0. Be careful when using ++, as putting it in the wrong place can cause bugs.
  • }. The closing brace marks the end of the while loop’s body.

So here’s what happens when this code is executed. The first time the condition is checked, the value of $count is 1, so the condition is definitely true. The value of $count (1) is output, and $count is given a new value of 2. The condition is still true the second time it’s checked, so the value (2) is output and a new value (3) is assigned. This process continues, outputting the values 3, 4, 5, 6, 7, 8, 9, and 10. Finally, $count is given a value of 11, and the condition is found to be false, which ends the loop.

The net result of the code is shown in the following image.

The net result of the while loop code

While loops aren’t generally used for simple counters like this; it’s normally the job of the for loop. Although you can create a counter with a while loop, usually they’re used to keep running code until something happens. For example, we might want to keep rolling the dice until we get a 6. There’s no way to know how many dice rolls will be needed when we write the code: it could take one roll or hundreds to get a six. So you can place the dice roll in a while loop.

Example: PHP-DiceRoll-While

$roll = 0;
while ($roll != 6) {
  $roll = rand(1, 6);
  echo '<p>You rolled a ' . $roll . '</p>';

  if ($roll == 6) {
    echo '<p>You win!</p>';
  }
  else {
    echo '<p>Sorry, you didn\'t win, better luck next time!</p>';
  }
}

This will keep rolling the dice until a 6 is rolled. Each time you run the code, it will take a different number of rolls before you win.

The while statement uses the condition $roll != 6. In order for the while loop to be run the first time, the $roll variable must be set to a value for the initial comparison. That’s the purpose of the $roll = 0; line above the while loop. By setting the value to zero initially, when the while loop runs the first time, the condition $roll != 6 is met, because $roll is equal to zero, not 6, and the loop will start. If the $roll variable isn’t created prior to starting the loop, you’ll get an error, because the $roll variable hasn’t been set to anything before it’s used.

There’s a variant of the while loop called do … while, which is useful in these kinds of cases. It allows you to run some code without a condition and then run it again if the code isn’t set. This takes the following structure:

do {
 statement(s) to execute and then repeat if the condition is true
}
while (condition);

For the dice-roll example above, this allows you to ignore the first line.

Example: PHP-DiceRoll-DoWhile

do {
  $roll = rand(1, 6);
  echo '<p>You rolled a ' . $roll . '</p>';

  if ($roll == 6) {
    echo '<p>You win!</p>';
  }
  else {
    echo '<p>Sorry, you didn\'t win, better luck next time!</p>';
  }
}
while ($roll != 6);

This time, because the condition is at the bottom, by the time the while statement is run, the $roll variable has been given a value, so you don’t need to give it an initial value of zero to force the loop to run the first time.

Note: PHP doesn’t mind how you format your code, and whitespace is ignored. You could write the previous example like this:

do {
  $roll = rand(
  1,
  6);

  echo '<p>You rolled a ' . $roll . '</p>';

  if (
      $roll == 6
  ) 
  {
    echo '<p>You win!</p>';
  }
  else
  {
    echo '<p>Sorry, you didn\'t win, better luck next time!</p>';
  }
}
while ($roll != 6);

The script will execute in the exact same way. Different programmers have different preferred styles, such as using tabs or spaces for indentation, or placing the opening brace on the same line as the statement or after it. There are even coding style guides that dictate where braces and brackets should be placed and how code should be formatted. But the computer doesn’t care whether a brace is on the same line or the next line, so use whatever style you feel most comfortable with.

Arrays

An array is a special kind of variable that contains multiple values. If you think of a variable as a box that contains a value, an array can be thought of as a box with compartments where each compartment is able to store an individual value.

To create an array in PHP, use square brackets ([ and ]) containing the values you want to store, separated by commas:

$myArray = ['one', 2, '3'];

Note: arrays in PHP can also be defined using the array keyword. The following code is equivalent to the square bracket notation above:

$myArray = array('one', 2, 3);

The square bracket notation was introduced in PHP 5.4 and is preferred by PHP developers, as it’s less to type, and square brackets are more easily visible among round brackets in control structures like if statements and while loops.

This code creates an array called $myArray that contains three values: 'one', 2, and '3'. Just like an ordinary variable, each space in an array can contain any type of value. In this case, the first and third spaces contain strings, while the second contains a number.

To access a value stored in an array, you need to know its index. Typically, arrays use numbers as indices to point to the values they contain, starting with zero. That is, the first value (or element) of an array has index 0, the second has index 1, the third has index 2, and so on. Therefore, the index of the nth element of an array is n–1. Once you know the index of the value you’re interested in, you can retrieve that value by placing that index in square brackets after the array variable name:

echo $myArray[0];    // outputs 'one'
echo $myArray[1];    // outputs '2'
echo $myArray[2];    // outputs '3'

Each value stored in an array is called an element. You can use a key in square brackets to add new elements, or assign new values to existing array elements:

$myArray[1] = 'two';     // assign a new value
$myArray[3] = 'four';    // create a new element

You can also add elements to the end of an array using the assignment operator as usual, but leaving empty the square brackets that follow the variable name:

$myArray[] = 'five';
echo $myArray[4];    // outputs 'five'

Array elements can be used like any other variable, and in a lot of cases choosing to use an array or multiple variables will depend on the programmer’s preference. However, arrays can be used to solve problems that normal variables can’t!

Remember the dice game from the last section? It would be more user-friendly if it showed the English word rather than the numeral for the result. For example, instead of “You rolled a 3” or “You rolled a 6”, it might be nicer to read “You rolled a three” or “You rolled a six”.

To do this, we need some way of converting from a numeral to the English word for that number. This is possible with a series of if statements.

Example: PHP-DiceRoll-English-If

$roll = rand(1, 6);

if ($roll == 1) {
  $english = 'one';
}
else if ($roll == 2) {
  $english = 'two';
}
else if ($roll == 3) {
  $english = 'three';
}
else if ($roll == 4) {
  $english = 'four';
}
else if ($roll == 5) {
  $english = 'five';
}
else if ($roll == 6) {
  $english = 'six';
}

echo '<p>You rolled a ' . $english . '</p>';

if ($roll == 6) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win. Better luck next time!</p>';
}*

This solution works, but it’s very inefficient, as you need to write an if statement for each possible dice roll. Instead, you can use an array to store each roll value:

$english = [
  1 => 'one',
  2 => 'two',
  3 => 'three',
  4 => 'four',
  5 => 'five',
  6 => 'six'
];

The => notation (known as a double arrow operator) allows you to define both the keys and the values when creating the array. This is equivalent to the following:

$english = [];
$english[1] = 'one';
$english[2] = 'two';
$english[3] = 'three';
$english[4] = 'four';
$english[5] = 'five';
$english[6] = 'six';

Although these are equivalent, the code required to use the shorthand notation is a lot quicker to type, and is arguably easier to read and easier to understand.

Now that the array is created, it’s possible to read each English word from it:

echo $english[3];    // Prints "three"
echo $english[5];    // Prints "five"

In PHP, a number like 3 can be replaced with a variable that contains that value. This is also possible with array keys. For example:

$var1 = 3;
$var2 = 5;

echo $english[$var1];    // Prints "three"
echo $english[$var2];    // Prints "five"

Knowing this, we can piece it all together and adjust the dice game to display the English word of the dice roll by reading the relevant value from the array using the $roll variable.

Example: PHP-DiceRoll-English-Array

$english = [
  1 => 'one',
  2 => 'two',
  3 => 'three',
  4 => 'four',
  5 => 'five',
  6 => 'six'
];

$roll = rand(1, 6);

echo '<p>You rolled a ' . $english[$roll] . '</p>';

if ($roll == 6) {
  echo '<p>You win!</p>';
}
else {
  echo '<p>Sorry, you didn\'t win, better luck next time!</p>';
}

As you can see, this is a lot cleaner and tidier than a long list of if statements. There are two big advantages here.

Firstly, if you wanted to represent a ten-sided dice, it’s a lot easier to add to the array than add an extra if statement for each number.

Secondly, the array is reusable. For the version with two dice, you can just reuse the $english array rather than repeating all the if statements for each dice roll.

Example: PHP-DiceRoll-English-If-TwoDice

$roll1 = rand(1, 6);
$roll2 = rand(1, 6);

if ($roll1 == 1) {
  $english = 'one';
}
else if ($roll1 == 2) {
  $english = 'two';
}
else if ($roll1 == 3) {
  $english = 'three';
}
else if ($roll1 == 4) {
  $english = 'four';
}
else if ($roll1 == 5) {
  $english = 'five';
}
else if ($roll1 == 6) {
  $english = 'six';
}

if ($roll2 == 1) {
  $englishRoll2 = 'one';
}
else if ($roll2 == 2) {
  $englishRoll2 = 'two';
}
else if ($roll2 == 3) {
  $englishRoll2 = 'three';
}
else if ($roll2 == 4) {
  $englishRoll2 = 'four';
}
else if ($roll2 == 5) {
  $englishRoll2 = 'five';
}
else if ($roll2 == 6) {
  $englishRoll2 = 'six';
}

echo '<p>You rolled a ' . $english . ' and a ' . $englishRoll2 . '</p>';

Instead, the array can be used for both rolls.

Example: PHP-DiceRoll-English-Array-TwoDice

$english = [
  1 => 'one',
  2 => 'two',
  3 => 'three',
  4 => 'four',
  5 => 'five',
  6 => 'six'
];

$roll1 = rand(1, 6);
$roll2 = rand(1, 6);

echo '<p>You rolled a ' . $english[$roll1] . ' and a ' . $english[$roll2] . '</p>';

While numbers are the most common choice for array indices, there’s another possibility. You can also use strings as indices to create what’s called an associative array. It’s called this because it associates values with meaningful indices. In this example, we associate a date (in the form of a string) with each of three names:

$birthdays['Kevin'] = '1978-04-12';
$birthdays['Stephanie'] = '1980-05-16';
$birthdays['David'] = '1983-09-09';

Like the numerical indexes, you can use the shorthand notation for associative arrays as well:

$birthdays = [
  'Kevin' => '1978-04-12',
  'Stephanie' => '1980-05-16',
  'David' => '1983-09-09'
];

Now, if we want to know Kevin’s birthday, we look it up using the name as the index:

echo 'Kevin\'s birthday is: ' . $birthdays['Kevin'];

This type of array is especially important when it comes to user interaction in PHP, as we’ll see shortly. I’ll also demonstrate other uses of arrays throughout this book.

Note: because Kevin's contains an apostrophe (single quote) and PHP would see this as the end of the string, it must be escaped with a \ so that PHP treats it as part of the string, rather than marking the end.

User Interaction and Forms

Database-driven websites often need to do more than dynamically generate pages based on database data. You also need to provide some degree of interactivity, even if it’s just a search box.

Because JavaScript code can live in the browser, it allows users to have all sorts of immediate interactions with a web page. Server-side scripting languages such as PHP have a more limited scope when it comes to support for user interaction. As PHP code is only activated when a request is made to the server, user interaction occurs solely in a back-and-forth fashion: the user sends requests to the server, and the server replies with dynamically generated pages.

The key to creating interactivity with PHP is to understand the techniques we can employ to send information about a user’s interaction, along with a request for a new web page. As it turns out, PHP makes this quite easy.

Note: as the Web has evolved, so too have the options for communication between the front and back ends of a web app. JavaScript allows for communication with a back end without page reloading. A JavaScript framework such as Vue.js, for example, can communicate with PHP frameworks like Laravel. For the purposes of this book, however, we’ll focus on what can be done with PHP alone.

Passing Variables in Links

The simplest way to send information along with a page request is to use the URL query string. If you’ve ever noticed a URL containing a question mark that follows the filename, you’ve seen this technique in use. For example, if you search for “SitePoint” on Google, it will take you to a search result page with a URL like this:

http://www.google.com/search?hl=en&q=SitePoint

See the question mark in the URL? The text that follows the question mark contains your search query (SitePoint). That information is being sent along with the request for http://www.google.com/search.

Let’s code up an easy example of our own. Create a regular HTML file called name.html (no .php filename extension is required, since there won’t be any PHP code in this file) and insert this link:

<a href="name.php?name=Tom">Hi, I’m Tom!</a>

This is a link to a file called name.php, but as well as linking to the file, you’re also passing a variable along with the page request. The variable is passed as part of the query string, which is the portion of the URL that follows the question mark. The variable is called name, and its value is Tom. So, you’ve created a link that loads name.php, and which informs the PHP code contained in that file that name equals Tom.

To really understand the effect of this link, we need to look at name.php. Create it as a new file, but this time, note the .php filename extension. This tells the web server that it can expect to interpret some PHP code in the file. In the body of this new web page, type the following.

Example: PHP-GET

<?php
$name = $_GET['name'];
echo 'Welcome to our website, ' . $name . '!';
?>

Now, put these two files (name.html and name.php) in the public folder, and load the first file in your browser. (The URL should be https://v.je/name.html.) Click the link in that first page to request the PHP script. The resulting page should say “Welcome to our website, Tom!”, as shown in the image below.

The welcome message, seen in the browser

Let’s take a closer look at the code that made this possible. This is the most important line:

$name = $_GET['name'];

Using what you learned from the “Arrays” section above, you may be able to figure out what this line does. It assigns the value stored in the 'name' element of the array called $_GET to a new variable called $name. But where does the $_GET array come from?

It turns out that $_GET is one of a number of variables that PHP automatically creates when it receives a request from a browser. PHP creates $_GET as an array variable that contains any values passed in the URL query string. $_GET is an associative array, so the value of the name variable passed in the query string can be accessed as $_GET['name']. Your name.php script assigns this value to an ordinary PHP variable ($name), then displays it as part of a text string using an echo statement:

echo 'Welcome to our website, ' . $name . '!';

The value of the $name variable is inserted into the output string using the string concatenation operator (.) that we looked at in the “Variables, Operators, and Comments” section.

But watch out! There’s a security hole lurking in this code! Although PHP is an easy programming language to learn, it turns out it’s also especially easy to introduce security issues into websites using PHP if you’re unaware of what precautions to take. Before we go any further with the language, I want to make sure you’re able to spot and fix this particular security issue, since it’s probably the most common one on the Web today.

The security issue here stems from the fact that the name.php script is generating a page containing content that’s under the control of the user — in this case, the $name variable. Although the $name variable will normally receive its value from the URL query string in the link on the name.html page, a malicious user could edit the URL to send a different value for the name variable.

To see how this would work, click the link in name.html again. When you see the resulting page (with the welcome message containing the name “Tom”), take a look at the URL in the address bar of your browser. It should look similar to this:

https://v.je/name.php?name=Tom

Edit the URL to insert a <b> tag before the name and a </b> tag following the name:

https://v.je/name.php?name=<b>Tom</b>

Hit enter to load this new URL, and note that the name in the page is now bold, as shown in the following image.

The name shown in bold

Note: you might notice that some browsers will automatically convert the < and > characters into URL escape sequences (%3C and %3E respectively), but either way, PHP will receive the same value.

See what’s happening here? The user can type any HTML code into the URL, and your PHP script includes it in the code of the generated page without question. If the code is as innocuous as a <b> tag, there’s no problem, but a malicious user could include sophisticated JavaScript code that performs some low action like stealing the user’s password. All the attacker would have to do is publish the modified link on some other site under the attacker’s control, and then entice one of your users to click it. The attacker could even embed the link in an email and send it to your users. If one of your users clicked the link, the attacker’s code would be included in your page and the trap would be sprung!

I hate to scare you with this talk of malicious hackers attacking your users by turning your own PHP code against you, particularly when you’re only just learning the language. The fact is that PHP’s biggest weakness as a language is how easy it is to introduce security issues like this. Some might say that much of the energy you spend learning to write PHP to a professional standard is spent on avoiding security issues. The sooner you’re exposed to these issues, however, the sooner you become accustomed to avoiding them, and the less of a stumbling block they’ll be for you in future.

So, how can we generate a page containing the user’s name without opening it up to abuse by attackers? The solution is to treat the value supplied for the $name variable as plain text to be displayed on your page, rather than as HTML to be included in the page’s code. This is a subtle distinction, so let me show you what I mean.

Open up your name.php file again and edit the PHP code it contains so that it looks like the code below.

Example: PHP-GET-Sanitized

<?php
$name = $_GET['name'];
echo 'Welcome to our website, ' .
  htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '!';
?>

There’s a lot going on in this code, so let me break it down for you. The first line is the same as it was previously, assigning to $name the value of the 'name' element from the $_GET array. But the echo statement that follows it is drastically different. Whereas previously we simply dumped the $name variable — naked — into the echo statement, this version of the code uses the built-in PHP function htmlspecialchars to perform a critical conversion.

Remember, the security hole occurs because, in name.php, HTML code in the $name variable is dumped directly into the code of the generated page, and can therefore do anything that HTML code can do. What htmlspecialchars does is convert “special HTML characters” like < and > into HTML character entities like &lt; and &gt;, which prevents them from being interpreted as HTML code by the browser. I’ll demonstrate this for you in a moment.

First, let’s take a closer look at this new code. The call to the htmlspecialchars function is the first example in this book of a PHP function that takes more than one argument. Here’s the function call all by itself:

htmlspecialchars($name, ENT_QUOTES, 'UTF-8')

The first argument is the $name variable (the text to be converted). The second argument is the PHP “constant” ENT_QUOTES, which tells htmlspecialchars to convert single and double quotes in addition to other special characters.

Note: a PHP constant is like a variable whose value you’re unable to change. Unlike variables, constants don’t start with a dollar sign. PHP comes with a number of built-in constants like ENT_QUOTES that are used to control built-in functions like htmlspecialchars.

The third parameter is the string 'UTF-8', which tells PHP what character encoding to use to interpret the text you give it.

Note: you may have discerned that all the example HTML pages in this book contain the following meta element near the top:

<meta charset="utf-8">

This element tells the browser receiving this page that the HTML code of the page is encoded as UTF-8 text.

UTF-8 is one of many standards for representing text as a series of ones and zeros in computer memory, called character encodings. If you’re curious to learn all about character encodings, check out “The Definitive Guide to Web Character Encoding”.

In a few pages, we’ll reach the section on “Passing Variables in Forms”. By encoding your pages as UTF-8, your users can submit text containing thousands of foreign characters that your site would otherwise be unable to handle.

Unfortunately, many of PHP’s built-in functions, such as htmlspecialchars, assume you’re using the much simpler ISO-8859-1 (or Latin-1) character encoding by default. Therefore, you need to let them know you’re using UTF-8 when utilizing these functions.

If you can, you should also tell your text editor to save your HTML and PHP files as UTF-8 encoded text. This is only required if you want to type advanced characters (such as curly quotes or dashes) or foreign characters (like “é”) into your HTML or PHP code. The code in this book plays it safe and uses HTML entity references (for example, &rsquo; for a curly right quote), which will work regardless.

Open up name.html in your browser and click the link that now points to your updated name.php. Once again, you’ll see the message “Welcome to our website, Tom!” As you did before, modify the URL to include <b> and </b> tags surrounding the name:

https://v.je/name.php?name=<b>Tom</b>

When you hit enter this time, instead of the name turning bold in the page, you should see the actual text you typed, as shown in the following image.

It sure is ugly, but it’s secure!

If you view the source code of the page, you can confirm that the htmlspecialchars function did its job and converted the < and > characters into the &lt; and &gt; entity references respectively. This prevents malicious users from injecting unwanted code into your site. If they try anything like that, the code is harmlessly displayed as plain text on the page.

We’ll make extensive use of the htmlspecialchars function throughout this book to guard against this sort of security hole. No need to worry too much if you’re having trouble grasping the details of how to use it just at the moment. Before long, you’ll find its use becomes second nature. For now, let’s look at some more advanced ways of passing values to PHP scripts when we request them.

Passing a single variable in the query string was nice, but it turns out you can pass more than one value if you want to! Let’s look at a slightly more complex version of the previous example. Open up your name.html file again, and change the link to point to name.php with this more complicated query string:

<a href="name.php?firstname=Tom&amp;lastname=Butler">Hi,
  I’m Tom Butler!</a>

This time, our link passes two variables: firstname and lastname. The variables are separated in the query string by an ampersand (&, which should be written as &amp; in HTML — yes, even in a link URL! … although, if you do wrongly use &, browsers will mostly fix it for you). You can pass even more variables by separating each name=value pair from the next with an ampersand.

As before, we can use the two variable values in our name.php file.

Example: PHP-GET-TwoVars

<?php
$firstName = $_GET['firstname'];
$lastName = $_GET['lastname'];
echo 'Welcome to our website, ' .
  htmlspecialchars($firstName, ENT_QUOTES, 'UTF-8') . ' ' .
  htmlspecialchars($lastName, ENT_QUOTES, 'UTF-8') . '!';
?>

The echo statement is becoming quite sizable now, but it should still make sense to you. Using a series of string concatenations (.), it outputs “Welcome to our website”, followed by the value of $firstName (made safe for display using htmlspecialchars), a space, the value of $lastName (again, treated with htmlspecialchars), and finally an exclamation mark.

The result is pictured below.

The echoed welcome

This is all well and good, but we’re still yet to achieve our goal of true user interaction, where the user can enter arbitrary information and have it processed by PHP. To continue with our example of a personalized welcome message, we’d like to invite the user to type their name and have it appear in the resulting page. To enable the user to type in a value, we’ll need to use an HTML form.

Passing Variables in Forms

Remove the link code from name.html and replace it with this HTML code to create the form.

Example: PHP-GET-Form

<form action="name.php" method="get">
  <label for="firstname">First name:</label>
  <input type="text" name="firstname" id="firstname">

  <label for="lastname">Last name:</label>
  <input type="text" name="lastname" id="lastname">

  <input type="submit" value="GO">
</form>

The image below shows how the browser displays the form produced from this code.

The form as it appears in a browser

Note: I’ve added some CSS to the form (available in form.css in the sample code) to make it look a little prettier. The CSS I’ve used is very generic, and can be used to display any form in the format label-input-line break. I’ll be including this CSS file on any page that contains a form.

Since this is a book about PHP and MySQL, however, I won’t go into detail about how the CSS works. Check out SitePoint’s HTML5 & CSS3 for the Real World for advice on styling your forms with CSS.

This form has the exact same effect as the second link we looked at in the “Passing Variables in Links” section above (with firstname=Tom&amp;lastname=Butler in the query string), except that you can now enter whichever names you like. When you click the submit button (labeled GO), the browser will load name.php and add the variables and their values to the query string for you automatically. It retrieves the names of the variables from the name attributes of the type="text" inputs, and obtains the values from the text typed into the text fields by the user.

The method attribute of the form tag is used to tell the browser how to send the variables and their values along with the request. A value of get (as used in name.html above) causes them to be passed via the query string (and appear in PHP’s $_GET array), but there’s an alternative. It can be undesirable — or even technically unfeasible — to have the values appear in the query string. What if we included a <textarea> element in the form, to let the user enter a large amount of text? A URL whose query string contained several paragraphs of text would be ridiculously long, and would possibly exceed the maximum length for a URL in today’s browsers. The alternative is for the browser to pass the information invisibly, behind the scenes.

Edit your name.html file once more. Modify the form method by setting it to post:

<form action="name.php" method="post">
  <label for="firstname">First name:</label>
  <input type="text" name="firstname" id="firstname">

  <label for="lastname">Last name:</label>
  <input type="text" name="lastname" id="lastname">

  <input type="submit" value="GO">
</form>

This new value for the method attribute instructs the browser to send the form variables invisibly as part of the page request, rather than embedding them in the query string of the URL.

As we’re no longer sending the variables as part of the query string, they stop appearing in PHP’s $_GET array. Instead, they’re placed in another array reserved especially for “posted” form variables: $_POST. We must therefore modify name.php to retrieve the values from this new array.

Example: PHP-POST-Form

<?php
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
echo 'Welcome to our website, ' .
  htmlspecialchars($firstname, ENT_QUOTES, 'UTF-8') . ' ' .
  htmlspecialchars($lastname, ENT_QUOTES, 'UTF-8') . '!';
?>

The image below shows what the resulting page looks like once this new form is submitted.

The resulting page once the form is submitted

The form is functionally identical to the previous one. The only difference is that the URL of the page that’s loaded when the user clicks the GO button will be without a query string. On the one hand, this lets you include large values (or sensitive values such as passwords and credit card numbers) in the data that’s submitted by the form without them appearing in the query string. On the other hand, if the user bookmarks the page that results from the form’s submission, that bookmark will be useless, as it lacks the submitted values. This, incidentally, is the main reason why search engines use the query string to submit search terms. If you bookmark a search results page on Google, you can use that bookmark to perform the same search again later, because the search terms are contained in the URL.

Note: as a rule of thumb, you should only use GET forms if, when the form is submitted, nothing on the server changes — such as when you’re requesting a list of search results. Because the search terms are in the URL, the user can bookmark the search results page and get back to it without having to type in the search term again. But if, after submitting the form, a file is deleted, a database is updated, or a record is inserted, you should use POST. The primary reason for this is that if a user bookmarks the page (or presses the back button in their browser) it won’t trigger the form submission again and potentially create a duplicate record.

POST is also more secure. Anything sent via GET appears in the URL and is stored in the user’s history and bookmarks — which are very insecure locations for sensitive data such as passwords and credit card details.

That covers the basics of using forms to produce rudimentary user interaction with PHP. We’ll look at more advanced issues and techniques in later examples.

Hiding the Seams

You’re now armed with a working knowledge of the basic syntax of the PHP programming language. You understand that you can take any HTML web page, rename it with a .php file name extension, and inject PHP code into it to generate page content on the fly. Not bad for a day’s work!

Before we go any further, however, I want to stop and cast a critical eye over the examples we’ve discussed so far. Assuming your objective is to create database-driven websites that hold up to professional standards, there are a few unsightly blemishes we need to clean up.

The techniques in the rest of this chapter will help advance your programming skills beyond the beginner level, giving them a certain professional polish. I’ll rely on these techniques throughout the rest of this book to ensure that, no matter how simple the example, you can feel confident in the quality of the product you’re delivering.

PHP Templates

In the simple examples we’ve seen so far, inserting PHP code directly into your HTML pages has been a reasonable approach. As the amount of PHP code that goes into generating your average page grows, however, maintaining this mixture of HTML and PHP code can become unmanageable.

Particularly if you work in a team of web designers who aren’t especially PHP savvy, having large blocks of cryptic PHP code intermingled with the HTML is a recipe for disaster. It’s far too easy for designers to accidentally modify the PHP code, causing errors they’ll be unable to fix.

A much more robust approach is to separate out the bulk of your PHP code so that it resides in its own file, leaving the HTML largely unpolluted by PHP code.

The key to doing this is the PHP include statement. With an include statement, you can insert the contents of another file into your PHP code at the point of the statement. To show you how this works, let’s rebuild the “count to ten” for loop example we looked at earlier.

Start by creating a new file, count.php, in your public directory. Open the file for editing and type in this code:

<?php
$output = '';
for ($count = 1; $count <= 10; $count++) {
    $output .= $count . ' ';
}

include 'count.html.php';

Yes, that’s the complete code for this file. It contains no HTML code whatsoever. The for loop should be familiar to you by now, but let me point out the interesting parts of this code:

  • Instead of echoing out the numbers 1 to 10, this script will add these numbers to a variable named $output. At the start of this script, therefore, we set this variable to contain an empty string.
  • The line $output .= $count . ' '; adds each number (followed by a space) to the end of the $output variable. The .= operator you see here is a shorthand way of adding a value to the end of an existing string variable, by combining the assignment and string concatenation operators into one. The longhand version of this line is $output = $output . $count . ' ';, but the .= operator saves you some typing.
  • The include statement instructs PHP to execute the contents of the count.html.php file at this location. You can think of the include statement as a kind of copy and paste. You would get the same result by opening up count.html.php, copying the contents and pasting them into count.php, overwriting the include line.
  • Finally, you might have noticed that the file doesn’t end with a ?> to match the opening <?php. You can put it in if you really want to, but it’s not necessary. If a PHP file ends with PHP code, there’s no need to indicate where that code ends; the end of the file does it for you. The big brains of the PHP world generally prefer to leave it off the end of files like this one that contain only PHP code.

Note: outside of this book, you’ll sometimes see parentheses surrounding the filename in include code, as if include were a function like date or htmlspecialchars, which is far from the case. For example, instead of include 'count.html.php';, you might see include('count.html.php');. These parentheses, when used, only serve to complicate the filename expression, and are therefore avoided in this book. The same goes for echo, another popular one-liner.

Since the final line of our count.php file includes the count.html.php file, you should create that file next.

Example: PHP-Count-Template

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Counting to Ten</title>
  </head>
  <body>
    <p>
      <?php echo $output; ?>
    </p>
  </body>
</html>

This file is almost entirely plain HTML, except for the one line that outputs the value of the $output variable. This is the same $output variable that was created by the count.php file.

What we’ve created here is a PHP template: an HTML page with only very small snippets of PHP code that insert dynamically generated values into an otherwise static HTML page. Rather than embedding the complex PHP code that generates those values in the page, we put the code to generate the values in a separate PHP script — count.php in this case.

Using PHP templates like this enables you to hand over your templates to front-end designers without worrying about what they might do to your PHP code. It also lets you focus on your PHP code without being distracted by the surrounding HTML code.

I like to name my PHP template files so that they end with .html.php. As far as your web server is concerned, though, these are still .php files; the .html.php suffix serves as a useful reminder that these files contain both HTML and PHP code.

To see how our pages work now, type https://v.je/count.php into your browser. You’ll see the results of the count.php script displayed in our count.html.php template.

Security Concerns

One problem with separating out the HTML and PHP code into different files is that someone could potentially run the .html.php code without having had it included from a corresponding PHP file. This isn’t a big problem, but anyone could visit count.html.php directly. If you type https://v.je/count.html.php into your web browser, instead of seeing the count from one to ten, you’ll see an error message: Notice: Undefined variable: output in /websites/default/public/count.html.php on line 9.

It’s better not to let people run code in a manner you’re not expecting. Depending on what the page is doing, this might let them bypass security checks you have in place and view content they shouldn’t have access to. For example, consider the following code:

if ($_POST['password'] == 'secret') {
  include 'protected.html.php';
}

Looking at this code, it appears that you need to submit a form and type secret in the password box to see the protected content in protected.html.php. However, if someone can navigate directly to protected.html.php and see the contents of the page, it makes the security check redundant. There are other potential security issues introduced by making all your files accessible via a URL. Avoiding security problems like these is easy. You can actually include files from a directory other than the public directory.

You may have wondered earlier why the development environment created a public directory inside the default directory and we then wrote all our files to the public directory. Well, this issue of security is the reason why. None of the files outside the public directory are accessible via a URL (by someone typing the file name into their web browser).

The include command can be tweaked to include files from another directory. In our case, that directory is going to be the default directory, which contains the public directory we’ve been writing our files to.

So the question is, when the include file is in a different directory, how does a PHP script find it? The most obvious method is to specify the location of the include file as an absolute path. Here’s how this would look on a Windows server:

<?php include 'C:/Program Files/Apache Software Foundation/Apache2.2/protected.html.php'; ?>

And here’s how it would look using the Docker environment we’re using:

<?php include '/websites/default/protected.html.php'; ?>

While this method will work, it’s undesirable because it ties your site’s code to your web server configuration. Because we’re using Docker, deploying the website would also use the same Docker environment, so this is not really an issue these days. However, you should ideally be able to drop your PHP-based website onto any PHP-enabled web server and just watch it run. That’s impractical if your code refers to drives and directories that are specific to one particular server. Even if you do have the luxury of working on a single server, you’ll be kicking yourself if you ever need to move your website to another drive/directory on that server.

A better method is to use a relative path — that is, the location of a file relative to the current file. When you use include 'count.html.php', this is actually a relative path: count.html.php is being included from the same directory as the script that was executed.

To include a file from the directory above, you can use the following code:

include '../count.html.php';

The ../ bit tells PHP to look for the file in the directory above the directory of the current script. It will look for count.html.php in the default directory instead of the public directory.

Go ahead and move count.html.php up a level into the default directory and amend count.php to reference the new location.

Example: PHP-Count-Template-Secured

<?php
$output = '';
for ($count = 1; $count <= 10; $count++) {
    $output .= $count . ' ';
}

include '../count.html.php';

If you run the code above, it will work. But there’s a potential problem when you include files in this way. Relative paths are relative to the script that was run, not to each file.

That is, if you open up default/count.html.php and add the line include 'count2.html.php'; you would expect count2.html.php to be included from the default directory. However, the path is relative to something called the current working directory, which, when you run a PHP script, is initially set to the directory that script is stored in. So running include 'count2.html.php'; from count.html.php will actually try to load count2.html.php from the public directory!

The current working directory is set at the start of the script and applies to all the include statements, regardless of what file they are in. To make things even more confusing, it’s possible to change the current working directory using the chdir() function.

Because of this, we can’t rely on the following:

include '../count.html.php';

It will work, but if the directory is changed, or count.php itself is an include file, it may not have the result we’re expecting.

To overcome this, we do actually need to use absolute paths. Luckily, PHP provides a constant called __DIR__ (that’s two underscores, before and after the word DIR) which will always contain the path that contains the current file.

For example, you could create a file called dir.php inside the public directory with the following code:

echo __DIR__;

This will display /websites/default/public, which is the full path to the directory containing dir.php. To read count.html.php from the directory above public, it’s possible to combine the /../ operator and the __DIR__ constant:

include __DIR__ . '/../count.html.php';

This will now include the file /websites/default/public/../count.html. That is, PHP will look in the public directory, then go up one level into default and include count.html.php.

This approach will work on any server, because __DIR__ will differ depending on where the file is stored, and it doesn’t depend on the changing current working directory. I’ll be using this approach for including files throughout this book.

From now on, we’ll only write files to the public directory that we actually want users to be able to access directly from their web browser. The public directory will contain any PHP scripts the user needs to access directly along with any images, JavaScript and CSS files required by the browser. Any files only referenced by an include statement will be placed outside the public directory so users can’t access them directly.

As the book goes on, I’m going to introduce you to several different types of include files. To keep things organized, it’s sensible to store different types of include files in different directories. We’ll store template files (with a .html.php extension) inside a directory called templates inside the default folder. We can then reference them in an include statement using include __DIR__ . '../templates/file.html.php';.

Many Templates, One Controller

What’s nice about using include statements to load your PHP template files is that you can have multiple include statements in a single PHP script, as well as have it display different templates under various circumstances!

A PHP script that responds to a browser request by selecting one of several PHP templates to fill in and send back is commonly called a “controller”. A controller contains the logic that controls which template is sent to the browser.

Let’s revisit one more example from earlier in this chapter — the welcome form that prompts a visitor for a first and last name.

We’ll start with the PHP template for the form. For this, we can just reuse the name.html file we created earlier. Create a directory templates inside default if you haven’t already, and save a copy of name.html called form.html.php into this directory. The only code you need to change in this file is the action attribute of the form tag.

Example: PHP-Form-Controller

<!doctype html>
<html>
  <head>
    <title>Enter your name</title>
    <link rel="stylesheet" href="form.css" />
    <meta charset="utf-8">  
  </head>
  <body>
  <form action="" method="post">
    <label for="firstname">First name:</label>
    <input type="text" name="firstname" id="firstname">

    <label for="lastname">Last name:</label>
    <input type="text" name="lastname" id="lastname">

    <input type="submit" value="GO">
  </form>
  </body>
</html>

As you can see, we’re leaving the action attribute blank. This tells the browser to submit the form back to the same URL it received it from — in this case, the URL of the controller that included this template file.

Let’s take a look at the controller for this example. Create an index.php file inside the public directory that contains the following code:

<?php
if (!isset($_POST['firstname'])) {
    include  __DIR__ . '/../templates/form.html.php';
} else {
    $firstName = $_POST['firstname'];
    $lastName = $_POST['lastname'];

    if ($firstName == 'Tom' && $lastName == 'Butler') {
        $output = 'Welcome, oh glorious leader!';
    } else {
        $output = 'Welcome to our website, ' .
      htmlspecialchars($firstName, ENT_QUOTES, 'UTF-8') . ' ' .
      htmlspecialchars($lastName, ENT_QUOTES, 'UTF-8') . '!';
    }

    include  __DIR__ . '/../templates/welcome.html.php';
}

This code should look quite familiar at first glance. It’s a lot like the name.php script we wrote earlier. Let me explain the differences:

  • The controller’s first task is to decide whether the current request is a submission of the form in form.html.php or not. You can do this by checking if the request contains a firstname variable. If it does, PHP will have stored the value in $_POST['firstname'].

isset is a built-in PHP function that will tell you if a particular variable (or array element) has been assigned a value or not. If $_POST['firstname'] has a value, isset($_POST['firstname']) will be true. If $_POST['firstname'] is unset, isset($_POST['firstname']) will be false.

For the sake of readability, I like to put the code that sends the form in my controller first. We need this if statement to check if $_POST['firstname'] isn’t set. To do this, we use the not operator (!). By putting this operator before the name of a function, you reverse the value that function returns — from true to false, or from false to true.

Thus, if the request doesn’t contain a firstname variable, then !isset($_POST['firstname']) will return true, and the body of the if statement will be executed.

  • If the request isn’t a form submission, the controller includes the form.html.php file to display the form.
  • If the request is a form submission, the body of the else statement is executed instead.

This code pulls the firstname and lastname variables out of the $_POST array, and then generates the appropriate welcome message for the name submitted.

  • Instead of echoing the welcome message, the controller stores the welcome message in a variable named $output.
  • After generating the appropriate welcome message, the controller includes the welcome.html.php template, which will display that welcome message.

All that’s left is to write the welcome.html.php file into the templates directory. Here it is:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Form Example</title>
  </head>
  <body>
    <p>
      <?php echo $output; ?>
    </p>
  </body>
</html>

That’s it! Fire up your browser and point it at https://v.je/index.php. You’ll be prompted for your name, and when you submit the form, you’ll see the appropriate welcome message. The URL should stay the same throughout this process.

You’ll have noticed I asked you to name the file index.php instead of name.php or similar. The reason I used index.php is because it has a special meaning. index.php is known as a directory index. If you don’t specify a filename when you visit the URL in your browser, the server will look for a file named index.php and display that. Try typing just https://v.je into your browser and you’ll see the index page.

Note: web servers can have different configurations and specify a different file to be the directory index. However, index.php will work on most web servers without any further configuration.

One of the benefits of maintaining the same URL throughout this process of prompting the user for a name and displaying the welcome message is that the user can bookmark the page at any time during this process and gain a sensible result. Whether it’s the form page or the welcome message that’s bookmarked, when the user returns, the form will be present once again. In the previous version of this example, where the welcome message had its own URL, returning to that URL without submitting the form would have generated a broken welcome message (“Welcome to our website, !”), or a PHP error message if, like ours, the server is running with error reporting enabled.

Note: in Chapter 11, where we discuss “sessions”, I show you how to remember the user’s name between visits.

Bring On the Database

In this chapter, we’ve seen the PHP server-side scripting language in action as we’ve explored all the basic language features: statements, variables, operators, comments, and control structures. The sample applications we’ve seen have been reasonably simple, but we’ve still taken the time to ensure they have attractive URLs, and that the HTML templates for the pages they generate are uncluttered by the PHP code that controls them.

As you may have begun to suspect, the real power of PHP is in its hundreds (even thousands) of built-in functions that let you access data in a MySQL database, send email, dynamically generate images, and even create Adobe Acrobat PDF files on the fly.

In Chapter 3, we’ll delve into the MySQL functions built into PHP, and then create a database of jokes. Then, in Chapter 4, we’ll see how to publish that joke database to the Web. These tasks will set the scene for the ultimate goal of this book: to create a complete content management system for your website in PHP and MySQL.

Original article source at: https://www.sitepoint.com/

#php #guide 

Beginner’s Guide to PHP: Introducing
Lawson  Wehner

Lawson Wehner

1672809264

Beginner’s Guide to MySQL: Introducing

The following article is an excerpt from PHP & MySQL: Novice to Ninja, 7th Edition, a hands-on guide to learning all the tools, principles, and techniques needed to build a professional web application. In this third tutorial in the series, you’ll learn what a database is, and how to work with your own databases using Structured Query Language (SQL).

As I explained in the last chapter, PHP is a server-side scripting language that lets you insert instructions into your web pages that your web server software will execute before it sends those pages to browsers that request them. We’ve looked at a few basic examples, including generating random numbers and using forms to capture input from a user.

Now, that’s all well and good, but it really gets interesting when a database is added to the mix. In this chapter, we’ll learn what a database is, and how to work with your own databases using Structured Query Language (SQL).

An Introduction to Databases

A database server is a program that can store large amounts of information in an organized format that’s easily accessible through programming languages like PHP. For example, you could tell PHP to look in the database for a list of jokes that you’d like to appear on your website.

In this example, the jokes would be stored entirely in the database. The advantage of this approach is twofold. First, instead of writing an HTML page for each joke, you could write a single PHP script designed to fetch any joke from the database and display it by generating an HTML page for it on the fly. Second, adding a joke to your website would be a simple matter of inserting the joke into the database. The PHP code would take care of the rest, automatically displaying the new joke along with the others when it fetched the list from the database.

Let’s run with this example as we look at how data is stored in a database. A database is composed of one or more tables, each of which contains a list of items, or things. For our joke database, we’d probably start with a table called joke that would contain a list of jokes. Each table in a database has one or more columns, or fields. Each column holds a certain piece of information about each item in the table. In our example, our joke table might have one column for the text of the jokes, and another for the dates on which the jokes were added to the database. Each joke stored in this way would be said to be a row or entry in the table. These rows and columns form a table that’s represented in the image below.

A typical database table containing a list of jokes

If you’ve ever created a spreadsheet, this will look familiar to you. A database table is similar, in that data is stored in rows and columns. The only difference is that, unlike Excel — where the columns are named A, B, C, and so on — when you create a database table you choose a name for each column.

Notice that, in addition to columns for the joke text (joketext) and the date of the joke (jokedate), there’s also a column named id. As a matter of good design, a database table should always provide a means by which each row can be identified uniquely. Since it’s possible that two identical jokes could be entered on the same date, we can’t rely on the joketext and jokedate columns to tell all the jokes apart. The function of the id column, therefore, is to assign a unique number to each joke, so that we have an easy way to refer to them and to keep track of which joke is which. We’ll take a closer look at database design issues like this in Chapter 5.

Note: it’s also possible to use a combination of columns as a unique identifier — such as manufacturer name and product name together. One manufacturer will likely have more than one product, and two manufacturers may have products with the same name. By combining the two names, it’s possible to uniquely identify each product.

To review, the table pictured above is a three-column table with two rows (or entries). Each row in the table contains three fields, one for each column in the table: the joke’s ID, its text, and the date of the joke. With this basic terminology under your belt, you’re ready to dive into creating a database yourself.

MySQL

The title of this book is PHP and MySQL: Novice to Ninja — where MySQL refers to the database we’re using. However, if you peruse the docker-compose.yml file you downloaded as part of setting up the Docker environment, you’ll notice that it actually installs a database called MariaDB.

In 2009, MySQL was bought by Oracle, a massive software company. Unsure about MySQL’s future, Michael Widenius — one of the founders of the original MySQL database — decided to fork MySQL to create a new database called MariaDB. (Forking means creating a new project from an existing project, using the original project’s source code as a basis.) As well as not being controlled by Oracle, MariaDB has some performance advantages over MySQL, which makes it a great choice.

MariaDB is a drop-in replacement for MySQL, and any tutorials you follow that teach you how to use MySQL will work exactly the same way with MariaDB. As a PHP developer, you won’t notice any difference between the two, and it’s possible to swap one out for the other.

Note: over time, the differences in MySQL and MariaDB have grown slightly, but the fundamental commands, tools and techniques you’ll use will be the same. There are some minor differences when it comes to some of the more advanced features supported by the two databases.

Despite this happening over ten years ago, most developers and package management systems use the two interchangeably. On Arch Linux, for example, if you install the mysql package, it actually installs MariaDB instead, and the XAMPP package I discussed in the first chapter installs MariaDB instead of MySQL.

Despite this, if you start developing PHP code using MariaDB, you’ll see constant references to MySQL, not MariaDB. That’s because client software (anything that connects to the server to interact with the database) doesn’t know if it’s connecting to MySQL or MariaDB. To this client software, MySQL is a protocol. In the same way you can plug in a keyboard or mouse via a USB port on your computer, you can connect to a MySQL server or MariaDB server via the MySQL protocol.

So when you hear a developer talk about “adding records to a MySQL database”, they’re often referring to using the MySQL protocol to manage a database, regardless of the specific implementation being used.

You’ll find developers frequently using the term “MySQL” even though they’re actually using MariaDB. For consistency’s sake, I’m going to do the same in this book. Rather than refer to the server as MariaDB and use the term MySQL when discussing connecting from PHP, I’ll just use MySQL throughout.

Using MySQL Workbench to Run SQL Queries

Just as a web server is designed to respond to requests from a client (a web browser), a database server responds to requests from client programs. Later in this book, we’ll write our own MySQL client programs in the form of PHP scripts, but for now we can use a client program written by the same people who write MySQL: MySQL Workbench. You can download MySQL Workbench for free from mysql.com/products/workbench/.

There are many different MySQL clients available to use, and earlier editions of this book used phpMyAdmin, a web-based MySQL client that has many of the same features. However, it’s not as easy to use as MySQL Workbench, and can often be very slow.

Once you’ve downloaded and installed MySQL Workbench, open it up, and you should see a screen like the one shown below.

If you can see this, you have MySQL Workbench running

Before you can add any data to your database, you need to connect to it. A MariaDB server is running in the Docker Environment you downloaded in Chapter 1, and you can connect to it using a MySQL client such as MySQL Workbench.

Connecting to the database requires three pieces of information:

  • a server address
  • a username
  • a password

For the Docker environment we’re using, the information is:

  • Server: v.je
  • Username: v.je
  • Password: v.je

You’ll notice that the server name is identical to the URL you’ve been connecting to in your web browser to view your PHP scripts. The Docker environment is running both the web server and the database server, so you only need to remember a single address.

To connect to a database in MySQL Workbench, press the + button next to the “MySQL Connections” label in the centre of the window. (Admittedly, it isn’t very clearly labeled, and its purpose isn’t very clear, but never mind!)

Add a connection

When you press the + button, you’ll see a new window.

Add a connection

Enter the server address and username. You’ll also need to give your connection a name. I’ve called it v.je, but you can call it whatever you like. This is just a name it’s listed as for future reference in MySQL Workbench.

Once you’ve entered the username and server, you can try connecting to the database by pressing the Test Connection button at the bottom of the window.

You should get a password prompt box.

Password prompt

If you don’t, follow these steps:

  1. Double-check that your environment is running. (If you’ve rebooted your PC since setting it up, you may need to run docker-compose up again in the project’s folder to get it running!)
  2. Make sure the username, password and server address are correct.

Tip: you can probably use the command docker-compose start here. start will start any existing containers, while up will create them if they don’t exist and then start them. Depending on what you’ve done on your computer between the chapters of this book, the containers (and other things like network connections) created by Docker will be recreated if needed. If you’ve moved between computers, performed a system restore or certain software updates, it’s possible the containers may need to be created again.

As such, up will work regardless of changes on your system, while start may or may not work depending on what’s happened since last time you ran it.

Note: usernames and passwords are case-sensitive, so make sure you type them both in lowercase!

Enter the password v.je into the box and tick the box that says “Save password”. By checking the box, you won’t have to enter the password each time you connect. Then press OK.

If the password was entered correctly, you’ll see a message telling you the connection was successful. Press OK in the “Set up new connection” window and you’ll see a box appear in the main MySQL window with some of the information you entered.

The main MySQL window showing information that was entered

Now that the connection is set up, it will be there each time you open MySQL workbench. You won’t need to add the connection each time.

You’re finally ready to actually connect to the database. To do this, simply double-click on the newly created box representing your connection and you’ll be presented with a different screen.

Initial screen

This looks a little daunting at first, as there are lots of different buttons and panels all representing different things. Down the left-hand side is a menu with lots of different options. The only one you need to worry about is the bottom section titled “SCHEMAS”.

Schema is just a fancy word for “database”. MySQL is a database server. In practical terms, this means that it can host lots of different databases, similarly to how a web server can host lots of different websites.

Creating a Database

Before you can add any information to a database, you need to create one. To create a database, right-click in the SCHEMAS panel and select Create schema. This gives you a window with several options, but you only need to enter one: the schema name.

Creating a schema

I chose to name the database ijdb, for Internet Joke Database (with a tip of the hat to the Internet Movie Database), because that fits with the example I gave at the beginning of this chapter: a website that displays a database of jokes. Feel free to give the database any name you like, though. (You’ll need to type it out frequently as you progress through this book, so don’t pick anything too complicated!)

Once you’ve typed a name, you can safely leave the other options at their default values and press Apply. When you do this, MySQL Workbench will ask you to confirm your action. (Get used to these dialogs. MySQL Workbench insists on confirmation for almost everything you do!) Press Apply again on the screen shown below.

Confirming the schema creation

Once you’ve pressed Apply, you’ll need to press Finish on the next screen. This is one of the annoying things about MySQL Workbench: it forces you to confirm and then Finish every action. However, it’s better than the alternative, as we’ll see shortly!

In the screenshot above, you’ll see a white panel with the words CREATE SCHEMA `ijdb`. This is an SQL Query, and you’ll see a lot more of these throughout this book. You could have typed out this command yourself and run it, avoiding the GUI and saving yourself going through MySQL Workbench’s confirmation dialogs. And for a command as simple as CREATE SCHEMA `ijdb`, the GUI is probably overkill. However, as you’ll see shortly, not all of the commands are this simple, and it’s a lot easier to use MySQL Workbench’s GUI for some of the more complex queries.

If you want to be able to delete databases (and this is probably a good ability to have, given the amount of experimentation I’m going to encourage you to do in this book), MySQL Workbench makes this easy. In the SCHEMAS panel in the main window, right-click on the schema you want to delete and select DROP Schema. MySQL uses the word DROP for deleting things. (Somewhat inconsistently, Delete is also used for some things!

Structured Query Language

Like the CREATE SCHEMA command we just saw, the commands we’ll use to direct MySQL throughout the rest of this book are part of a standard called Structured Query Language, or SQL (pronounced as either “sequel” or “ess-cue-ell”, so take your pick). Commands in SQL are also referred to as queries, and I’ll use these two terms interchangeably.

SQL is the standard language for interacting with most databases, so even if you move from MySQL to a database like Microsoft SQL Server in the future, you’ll find that the majority of commands are identical. It’s important that you understand the distinction between SQL and MySQL. MySQL is database server software that you’re using — and MariaDB, which you’re using, follows the same standards. SQL is the language that you use to interact with that database.

Most of these commands can be generated by MySQL Workbench, and that’s what we’ll use to create the structure of our database. However, you’ll need to learn some commands, as you’ll be executing them from your PHP scripts rather than MySQL Workbench!

Tip: in this book, I’ll teach you the essentials of SQL that every PHP developer needs to know. If you decide to make a career out of building database-driven websites, it pays to know some of the more advanced details of SQL, especially when it comes to making your sites run as quickly and smoothly as possible. To dive deeper into SQL, I highly recommend the book Simply SQL, by Rudy Limeback, or Jump Start MySQL, by Timothy Boronczyk.

Note: most MySQL commands are not case-sensitive, which means you can type CREATE DATABASE, create database, or even CrEaTe DaTaBaSe, and it will know what you mean. Database names and table names, however, are case-sensitive when the MySQL server is running on an operating system with a case-sensitive file system (such as Linux, macOS, or when running inside Docker).

Additionally, table, column, and other names must be spelled exactly the same when they’re used more than once in the same query.

For consistency, this book will respect the accepted convention of typing database commands in all capitals, and database entities (databases, tables, columns, and so on) in all lowercase.

This also makes it easier for people (like you!) to read the queries. MySQL doesn’t care, but you’ll be able to identify a command quickly and easily because it’s in capitals, and a reference to a table, column or database because it’s in lowercase.

Once your database has been created, it will appear in the SCHEMAS list on the left-hand side.

The Internet Joke Database schema

Now that you have a database, you need to tell MySQL Workbench that you want to use it. To do this, simply double-click the newly created schema and its name will go bold. You can only have one schema selected at a time, and you need to tell MySQL Workbench which you’d like to use.

The ijdb schema selected

You’re now ready to use your database. Since a database is empty until you add tables to it, our first order of business is to create a table that will hold your jokes. (Now might be a good time to think of some!)

Creating a Table

If you expand your newly created ijdb schema by pressing the arrow next to the name, you’ll see a few entries.

The ijdb schema expanded

The only one we’re concerned with for the purposes of this book is the Tables entry. Because your schema has just been created, it doesn’t have any tables.

A table describes the format of your data. You’ll need to know the structure of the data you’d like to store. Before creating a table, you need to think about exactly what you want to store. For the jokes example, we want to store these pieces of information:

  • the text of the joke
  • the date it was added

Along with the text and date, we’ll also need some way to identify each joke. To do this, we’ll give each joke a unique ID.

Each piece of information is placed in a field in the table, and each field has a “type”. Types can be used to store data in different formats like numbers, text and dates.

There are three main kinds of types that you’ll encounter:

  • numbers, for storing numeric values
  • text, for storing strings
  • dates/times, for storing timestamps

There are lots of column types in MySQL, but you only really need an understanding of three for most purposes!

To create a table using MySQL Workbench, expand the database in the SCHEMAS list, then right-click on the Tables entry and select Create Table.

The middle panel of the window will change to show you something like what’s pictured below.

MySQL Workbench New Table window

Every table is given a name to identify it and a series of columns. Firstly, enter the table’s name as “joke” and add the following columns in the column list:

  • id, which will act as a unique identifier for each joke so we can retrieve it later
  • joketext, which will store the text of the joke
  • jokedate, which will store the date the joke was added

Creating the joke table

You’ll notice there’s a second column called Datatype. Each column in a database table must be assigned a type. The three types we will need are:

  • INT, meaning “integer” for the numeric jokeid
  • TEXT, to store some text for the joke
  • DATE, to store the date the joke was published

This helps to keep your data organized, and allows you to compare the values within a column in powerful ways, as we’ll see later.

If we were to stop setting up the table at this point, you could start adding records to the table (and I’ll show you how to do that very shortly!). However, you’d have to provide all three pieces of information: the joke ID, the joke text, and the joke date. This means that, to add the next joke, you’d need to keep track of how many were in there in order to assign the next ID.

This sounds like extra work, but fortunately MySQL Workbench provides a convenient way of avoiding it. Along with the name of the column and data type it stores, you’ll notice there’s a series of checkboxes for each field in the table.

There are three we’re interested in here for our ID field:

  • PK. This means “primary key”. Ticking this box specifies that this column is to act as a unique identifier for the entries in the table, so all values in this column must be unique, ensuring that no two jokes will share the same ID.
  • NN. This stands for “Not Null”, and means that when a record is added, a value must be placed in the field. For our ID column, ticking this box tells MySQL not to accept jokes that don’t have an ID.
  • AI. This is the clever bit that will save us work. No, “AI” is not “Artificial Intelligence”, some kind of computer-brain doing our work for us. In this case, it stands for “Auto Increment”, and by checking this box (and it’s only allowed on INT fields!), whenever a record (in our case, a joke) is added to the table, it will automatically be assigned the next available ID. This is a real time saver and a feature worth remembering.

Your table should now look like the one pictured below.

The joke table complete

Press the Apply button, and the joke table will be created. You’ll see the following query appear in the window:

CREATE TABLE `ijdb`.`joke` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `joketext` TEXT NULL,
  `jokedate` DATE NULL,
  PRIMARY KEY (`id`));

You’ll notice a lot of the same information has been repeated that we entered into the GUI. The GUI just generates this code for us, which is a much quicker and easier way of creating tables than remembering all of the syntax and vocabulary needed to write the query yourself.

As a developer, you don’t need to create tables often. But you will need to interact with them — adding and removing records and retrieving them from the database — so it’s worth spending time learning how to write queries to do this. For creating tables, however, it’s usually a lot quicker and easier to use the MySQL Workbench GUI, because once a table has been created, you won’t need to write another create table statement.

We need to look at just one more task: deleting a table. This task is frighteningly easy, so be careful! If you delete a table, you can’t get it back.

In the SCHEMAS list, right-click on the table you want to delete and select Drop Table. Don’t run this command with your joke table unless you actually do want to be rid of it. If you really want to try it, be prepared to recreate your joke table from scratch. When you delete a table, the table is removed permanently, along with any data stored inside it. There’s no way to recover the data after the table has been dropped, so be very careful when using this command!

Adding Data

Now that the table has been created, it’s time to add some data to it. Although this can be done using MySQL Workbench’s GUI, this time we’re going to write the query ourselves. Eventually, we’ll need to be able to write our own database queries directly from PHP, so it’s good to get some practice writing them.

To run a query, you need to open up a query window. The simplest way to do this is to expand your database in the SCHEMAS list. Expand the Tables entry, and you’ll see the joke table that you just created. Right-click on the table and click on the topmost option “Select Rows – Limit 1000”.

This will give you a slightly different screen that’s split into two panels horizontally.

A new query panel

The top half is a text box into which you can type commands to ask your database server questions or make it perform tasks. The bottom half is the result of that query. You’ll see there’s already a query in the top panel:

SELECT * FROM `ijdb`.`joke`;

We’ll come back to what this means shortly. Along with this query in the top panel, there’s a list of rows in the bottom panel — or rather there would be, if there were anything in the table! Because the table was just created, it’s currently empty. Before you can view the contents of the table, you need to add some records.

All that’s left is to put some jokes into the database. The command that inserts data into a database is called, appropriately enough, INSERT. This command can take two basic forms:

INSERT INTO tableName SET
  column1Name = column1Value,
  column2Name = column2Value,
  …
INSERT INTO tableName
  (column1Name, column2Name, …)
  VALUES (column1Value, column2Value, …)

So, to add a joke to our table, we can use either of these commands:

INSERT INTO joke SET
joketext = "A programmer was found dead in the shower. The instructions read: lather, rinse, repeat.",
jokedate = "2021-10-29"
INSERT INTO joke
(joketext, jokedate) VALUES (
"A programmer was found dead in the shower. The instructions read: lather, rinse, repeat.",
"2021-10-29")

Note that the order of the column/value pairs isn’t important, but pairing the right values with the right columns, position-wise, is. If the first column mentioned in the first set of parentheses is joketext, then the first entry in the VALUES list must be the text that’s going to be placed in the joketext column. The second column name in the first parentheses gets its values from the same position in the VALUES list. Otherwise, the order of the columns isn’t important. Go ahead and swap the order of the column and value pairs and try the query.

As you typed the query, you’ll have noticed that we used double quotes (") to mark where the text of the joke started and ended. A piece of text enclosed in quotes this way is called a text string, and this is how you represent most data values in SQL. For instance, the dates are typed as text strings, too, in the form "YYYY-MM-DD".

If you prefer, you can type text strings surrounded with single quotes (') instead of double quotes:

INSERT INTO joke SET
joketext = '',
jokedate = '2021-10-29'

You might be wondering what happens when there are quotes used within the joke’s text. Well, if the text contains single quotes, surround it with double quotes. Conversely, if the text contains double quotes, surround it with single quotes.

If the text you want to include in your query contains both single and double quotes, you’ll have to escape the conflicting characters within your text string. You escape a character in SQL by adding a backslash (\) immediately before it (which, conveniently, is the same as in PHP). This tells MySQL to ignore any “special meaning” this character might have. In the case of single or double quotes, it tells MySQL not to interpret the character as the end of the text string.

To make this as clear as possible, here’s an example of an INSERT command for a joke containing single quotes, even though single quotes have been used to mark the string:

INSERT INTO joke
(joketext, jokedate) VALUES (
'!false - it\'s funny because it\'s true',
"2021-10-29")

As you can see, I’ve marked the start and end of the text string for the joke text using single quotes. I’ve therefore had to escape the two single quotes (the apostrophes) within the string by putting backslashes before them. MySQL would see these backslashes and know to treat the single quotes as characters within the string, rather than end-of-string markers.

If you’re especially clever, you might now be wondering how to include actual backslashes in SQL text strings. The answer is to type a double-backslash (\\), which MySQL will treat as a single backslash in the string of text.

Write your insert query into the top text box in MySQL Workbench and press the yellow lightning bolt icon above it to execute the query.

Executing an INSERT query using MySQL Workbench

When the query executes, a panel will appear at the bottom of the screen telling you if the query was executed successfully.

Checking a query has executed successfully

If you get an error and the query isn’t successful, take a look at the error message. It should give you a hint where to look. Double-check your syntax, and check your quotes and parentheses are in the right place.

Tip: if you have a lower screen resolution than it’s expecting, MySQL Workbench hides the bottom panel. To display it, hover your mouse just below the scroll bar at the bottom of the window and you’ll get a resize cursor. You can then drag the panel into view.

Add both the jokes (and any others you can think of!) to the database using INSERT queries. Now that you know how to add entries to a table, let’s see how we can view those entries.

A Word of Warning

You’ll have noticed something slightly peculiar about the queries that have been generated by MySQL Workbench. We don’t get a query that looks like this:

SELECT * FROM joke

Instead, this is the query that’s generated:

SELECT * FROM `joke`

There are strange quotes around `joke`. Those aren’t actually quotes, or even apostrophes like we’ve been using to designate strings. They’re backticks.

This is a safety precaution. There are lots of words in SQL that have meaning to the language. You’ve seen a few already: SELECT, FROM and INSERT. But there are hundreds of others, known as reserved words. Imagine if you called your table SELECT. The query you would need to run would look like this:

SELECT * FROM SELECT

Unfortunately, this can cause MySQL to get a little confused. It may see SELECT as a command rather than as a table name. What’s worse, date is one of these words, and it’s not improbable that you might think to create a column in one of your tables called date. What would you expect to happen when the following query runs?

INSERT INTO joke
(joketext, date) VALUES (
'!false - it\'s funny because it\'s true',
"2021-04-01")

Because the word date already has meaning in SQL, it may not be seen as a column name but as part of the query, like VALUES or INTO.

MySQL is usually good at guessing whether you’re referring to a table/column name or a command it needs to follow, but there are times when it isn’t able to make that distinction. To avoid this kind of confusion, it’s good practice to surround all table and column names with backticks. The backticks tell MySQL to treat the string as a name rather than an instruction. It’s good to get into the habit of doing this from the very start, as it avoids issues later on that often aren’t immediately obvious.

From now on, I’ll surround all table, schema and column names with backticks. This will also help you — as a programmer — to distinguish between commands and column names. For instance, the INSERT query above would be written like this:

INSERT INTO `joke`
(`joketext`, `date`) VALUES (
'!false - it\'s funny because it\'s true',
"2021-04-01")

Tip: on many English-language keyboard layouts, the backtick key is the one to the immediate left of the numeric 1 key and below Esc. Its location may differ on non-English keyboards and/or on various devices such as laptops and tablets.

Viewing Stored Data

The command that we use to view data stored in database tables is SELECT. You saw an example SELECT query generated for you by MySQL Workbench earlier. The SELECT query is the most complicated command in SQL. The reason for this complexity is that the chief strength of a database is its flexibility in data retrieval. At this early point in our experience with databases, we need only focus on fairly simple lists of results, so let’s consider the simpler forms of the SELECT command here.

This command will list everything that’s stored in the joke table:

SELECT * FROM `joke`

This command says “select everything from joke”, with the * meaning “all columns”. By default, a SELECT query will return every record in the table. If you try this command, your results will resemble the image below.

MySQL Workbench results

Notice that there are some values in the id column, even though you didn’t specify them in the INSERT queries you ran earlier. MySQL has automatically assigned an ID to the joke. This is because you checked the “AI” (Auto Increment) checkbox when you created the table. If you hadn’t checked the box, you’d have needed to specify the ID for each joke you inserted.

If you were doing serious work on such a database, you might be tempted to stop and read all the hilarious jokes in the database at this point. To save yourself the distraction, you might want to tell MySQL to omit the joketext column. The command for doing this is as follows:

SELECT `id`, `jokedate` FROM joke

This time, instead of telling it to “select everything”, we told it precisely which columns we wanted to see. The result should look like the image below.

You can select only what you need

What if we’d like to see some of the joke text? As well as being able to name specific columns that we want the SELECT command to show us, we can use functions to modify each column’s display. One function, called LEFT, enables us to tell MySQL to display a column’s contents up to a specified number of characters. For example, let’s say we wanted to see only the first 20 characters of the joketext column. Here’s the command we’d use:

SELECT `id`, LEFT(`joketext`, 20), `jokedate` FROM `joke`

The LEFT function trims the text to a specified length

See how that worked? Another useful function is COUNT, which lets us count the number of results returned. If, for example, you wanted to find out how many jokes were stored in your table, you could use the following command:

SELECT COUNT(`id`) FROM `joke`

As you can see in the image below, you have just two jokes in your table.

The COUNT function counts the rows

Note: you can use COUNT(*) for the same result, but this is slower, as all the columns will be selected from the table. By using the primary key, only one column needs to be retrieved.

So far, the examples we’ve looked at have fetched all the entries in the table. However, you can limit your results to only those database entries that have the specific attributes you want. You set these restrictions by adding what’s called a WHERE clause to the SELECT command. Consider this example:

SELECT COUNT(*) FROM `joke` WHERE `jokedate` >= "2021-01-01"

This query will count the number of jokes that have dates greater than or equal to January 1, 2021. In the case of dates, “greater than or equal to” means “on or after”. Another variation on this theme lets you search for entries that contain a certain piece of text. Check out this query:

SELECT `joketext` FROM `joke` WHERE `joketext` LIKE "%programmer%"

This query displays the full text of all jokes containing the text “programmer” in their joketext column. The LIKE keyword tells MySQL that the named column must match the given pattern. In this case, the pattern we’ve used is "%programer%". The % signs (called wildcards) indicate that the text “programmer” may be preceded and/or followed by any string of text. (Interestingly, LIKE is case-insensitive, so this pattern will also match a joke that contains “Programmer”, or even “FuNkYProGRammeR”.)

Conditions may also be combined in the WHERE clause to further restrict results. For example, to display knock-knock jokes from April 2021 only, you could use the following query:

SELECT `joketext` FROM `joke` WHERE
`joketext` LIKE "%knock%" AND
`jokedate` >= "2021-04-01" AND
`jokedate` < "2021-05-01"

Enter a few more jokes into the table. (For example, “Why did the programmer quit his job? He didn’t get arrays.”) Then experiment with SELECT queries.

You can do a lot with the SELECT command, so I’d encourage you to become quite familiar with it. We’ll look at some of its more advanced features later, when we need them.

Modifying Stored Data

Having entered data into a database table, you might find that you’d like to change it. Whether you’re correcting a spelling mistake, or changing the date attached to a joke, such alterations are made using the UPDATE command. This command contains elements of the SELECT and INSERT commands, since the command both picks out entries for modification and sets column values. The general form of the UPDATE command is as follows:

UPDATE `tableName` SET
  `colName` = newValue, …
WHERE conditions

So, for example, if we wanted to change the date on the joke we entered earlier, we’d use the following command:

UPDATE `joke` SET `jokedate` = "2021-04-01" WHERE id = "1"

Here’s where that id column comes in handy, enabling you to easily single out a joke for changes. The WHERE clause used here works just as it did in the SELECT command. This next command, for example, changes the date of all entries that contain the word “programmer”:

UPDATE `joke` SET `jokedate` = "2021-04-01"
WHERE `joketext` LIKE "%programmer%"

Note: believe it or not, the WHERE clause in the UPDATE command is optional. Consequently, you should be very careful when typing this command! If you leave the WHERE clause out, the UPDATE command will then apply to all entries in the table.

The following command will set the date for all the records in the table!

UPDATE `joke` SET `jokedate` = "2021-04-01"

Deleting Stored Data

Deleting entries in SQL is dangerously easy, which you’ve probably noticed is a recurring theme. Here’s the command syntax:

DELETE FROM `tableName` WHERE conditions

To delete all programmer jokes from your table, you’d use the following query:

DELETE FROM `joke` WHERE `joketext` LIKE "%programmer%"

Note: as with UPDATE, the WHERE clause in the DELETE command is optional. Consequently, you should be very careful when using it. If you leave the WHERE clause out, the DELETE command will then apply to all entries in the table.

The following command will empty the joke table in one fell swoop:<,em>

DELETE FROM `joke`

Scary, huh?

Let PHP Do the Typing

There’s a lot more to the MySQL database server software and SQL than the handful of basic commands I’ve presented here, but these commands are by far the most commonly used and most useful!

At this stage, you might be thinking that databases seem a little cumbersome. SQL can be tricky to type, as its commands tend to be long and verbose compared with those of other computer languages. You’re probably dreading the thought of typing in a complete library of jokes in the form of INSERT commands.

Don’t sweat it! As we proceed through this book, you’ll be surprised how few SQL queries you actually type by hand. Generally, you’ll be writing PHP scripts that type your SQL for you. For example, if you want to be able to insert a bunch of jokes into your database, you’ll typically create a PHP script for adding jokes that includes the necessary INSERT query, with a placeholder for the joke text. You can then run that PHP script whenever you have jokes to add. The PHP script prompts you to enter your joke, then issues the appropriate INSERT query to your MySQL server.

For now, however, it’s important to develop a good feel for typing SQL by hand. It will give you a strong sense of the inner workings of MySQL databases, and will make you appreciate all the more the work that PHP will save you from having to do!

To date, we’ve only worked with a single table, but to realize the true power of a relational database, you’ll need to learn how to use multiple tables together to represent potentially complex relationships between the items stored in your database. I’ll cover all this and more in Chapter 5, in which I’ll discuss database design principles and show off some more advanced examples.

In the meantime, we’ve accomplished our objective, and you can comfortably interact with MySQL using the MySQL Workbench query window. In Chapter 4, the fun continues as we delve into the PHP language, and use it to create several dynamically generated web pages.

If you like, you can practice with MySQL a little before you move on, by creating a decent-sized joke table (for our purposes, five should be enough). This library of jokes will come in handy when you reach Chapter 5.

Original article source at: https://www.sitepoint.com/

#mysql #guide 

Beginner’s Guide to MySQL: Introducing
Bongani  Ngema

Bongani Ngema

1672058640

Beginner’s Guide: How to Use Airtable

Airtable is a cloud-based application that combines the best of both spreadsheets and databases into one collaborative environment.

No matter the task list or project, you can manage just about anything with Airtable. Whether you’re in need of a way to organize your tasks, or if you want to be able to work on a project with others without the need for collaboration software, Airtable can be your go-to organizational tool.

Where apps like Notion take a free-form approach to information management, structure is at Airtable’s core. But don’t let that fool you — Airtable’s feature set, flexible data types, and automations are incredibly powerful.

To see advanced Airtable usage in action, learn how to build interactive Gantt charts with Airtable as a CMS, Gatsby, and React.

This Airtable tutorial will take you through everything this tool has to offer, and explain how it can make your life easier. First, let’s walk through the basic organizational structures and vocabulary associated with Airtable.

Master the basics of Airtable

1. Set up bases within your team’s workspace.

Airtable first base setup
Think of your team’s office as the workspace. Within that office, there are likely several departments or even teams with various ongoing projects at play. Each project in real life is a separate base in Airtable.

Why are projects in Airtable called “bases”? Short for databases, each project is designed to hold sets of information. Airtable comes with predesigned templates, and gives you access to the Airtable Universe of other designed templates. You can always upload a spreadsheet for a simple base, or you can even design your own base from scratch.

 

Airtable team bases

Depending on how big or small your team is, or how many projects you have in play, you might choose to have several different workspaces within your business. That’s totally ok, and actually speaks to another feature of Airtable: it is fully customizable, capable of snapping into your structure and workflow. Airtable bends to fit your needs.

2. Then, set up tables and records within a base.

Airtable new base

Inside of Airtable bases, you’ll find tables, or lists of a certain type of thing. You may have a table of tasks, or a table of contacts. Each entry in the table is called a record, and each record has a set of attributes attached to it that are known as fields. Every layer of organization that we just enumerated—table, record, and field—is fully customizable. You get to choose every aspect of what’s stored in Airtable.

3. Choose your view—or toggle between what works best.

Airtable lets you view your records in countless ways, including grids, galleries, Kanban boards, calendars, and more.

Airtable base calendar view

The flexibility of perspective on the information you store in Airtable can help you see things in a new light, inspiring new ideas or giving visibility to trends. Regardless, access to these different views again reinforces how Airtable lets you customize everything to fit your workflow.

These views can also help you construct the logic that helps you link records throughout your base.

4. Graduate to Airtable Apps.

Pro and Enterprise-level Airtable plans get access to Apps, which contribute more advanced visualizations (like pivot table automation, maps, and even videos) as well as integrations into other applications, like Google Cloud, and third-party plug-ins.

Airtable apps

You may need an API key from these other services, but that is getting easier by the day as most major business platforms and tools are opening themselves up to developers.

5. Add in collaborators.

You can invite other people to join your base or workspace as a collaborator. There are different tiers of access you can grant each collaborator, ranging from view-only access through the ability to create new bases of their own.

Appreciate Airtable’s most popular features

So far in this Airtable Guide, we’ve got you familiar with the basic structures and terms associated with Airtable. Now that we’ve covered the basics, let’s consider some of the coolest features it offers.

Build spreadsheets across different mediums.

Put images inside of your spreadsheet, and have them accessible across sheets! Airtable takes spreadsheets and completely blows them up, so that they are no longer boring rows of strictly alphanumeric characters. Many people who hate conventional spreadsheets are not comfortable with all of these letters and numbers thrown their way.

Leverage import tools to standardize your data

Gathering information from multiple sources has never been as easy as it is with Airtable. Automatic importing tools allow you to pull data, with full control over which fields they populate and how they are formatted. Even if you have a lot of data scattered across multiple places and documented in various ways, you can use Airtable’s importing functionality to bring it all together into a one-stop shop for your team.

Color-coding and other organization for better compliance

The best organizational techniques and rules are the ones that work, but getting groups of people on-board with institutional systems can be difficult if they feel cumbersome. Fortunately, the Airtable interface is user-friendly, and the options that you have for customization can make Airtable easier to follow than other tools like spreadsheets.

Create relationships between objects in different tables

This bears repeating because it is such a powerful functionality of Airtable. Not only does it save time and ensure consistent records across users, bases, and workspaces, but it also is more consistent with real-world logic.

Airtable linked fields

Objects and people in the real world exist in one central location, although their presence is important as part of the different teams and other groups in which they exist. There is not a separate copy of you that operates within your family unit versus your office; it’s the same you, just accessed in different environments. Why should the same not be true of your data? Well, with Airtable, it is.

Stop thinking about your data in terms of linear relationships; that’s old-school. Nowadays, it’s all about networks of information, and easily navigating the relationships that exist between separate pieces of data.

Fully customize your notifications

You can actually use third-party integrations like Zapier to build workflows within Airtable. Certain actions or entries can trigger other events to happen. Maybe you have a calendar base set up and you want to know when someone adds an upcoming event; you can set up a notification that can share as much or as little about this entry as you wish, through whichever medium you prefer.

Automate backups of your data

Save time and protect your information for the future by building workflows that automatically trigger data back-ups. You can store these back-ups wherever you prefer. By removing the human element behind this back-up step, you reduce the potential impact of any human error and increase the likelihood of positive long-term outcomes.

There is no “one-size-fits-all.”

Having this much power to customize absolutely every aspect of your data storage and organization may seem overwhelming. But this responsibility comes with the power to maximize your efficiency and fully optimize your team’s workflow.

Leverage Airtable community support

Everyone knows there is a learning curve to getting started with Airtable, but even the most experienced users can find themselves stuck on how to do something. And even if you have found a way to do something, you may want to find out if there’s a better way.

Fortunately, the collaborative and growth-oriented spirit behind the Airtable product extends throughout its community of users. It’s as though you have a massive database (see what we did there?) of Airtable developers at your beck and call. You can browse existing discussions or post your own questions to get the insights you crave. Airtable moderates, and so you’ll see them chiming in with their “official” perspective.

Of course, Airtable’s product development teams are hard at work, making sure that it is constantly getting better. As you use Airtable, you will discover all kinds of new features beyond the scope of this piece, and that might have even just gone live.

You will also think up new ways to organize yourself and the data you need. Finally, you can seamlessly integrate data management mastery and collaboration into your business’ operations.

Original article source at: https://www.sitepoint.com

#airtable #guide 

Beginner’s Guide: How to Use Airtable
Rupert  Beatty

Rupert Beatty

1669929600

Quick Start Guide with AWS

What’s AWS ?

Amazon Web Services is a comprehensive, evolving cloud computing platform provided by Amazon that includes a mixture of infrastructure-as-a-service (IaaS), platform-as-a-service (PaaS) and packaged-software-as-a-service (SaaS) offerings. AWS services can offer an organization tools such as compute power, database storage and content delivery services.

AWS (Amazon Web Services) is a Cloud Provider. It provide you with servers and services that you can use on demand and scale easily. It has revolutionized IT over time.
AWS powers some of the biggest websites in the world is
Amazon.com
Netflix

AWS Cloud History

It was internally established at Amazon.com in 2002. they understood that the IT departments could be outsourced. One of their key advantages was their Amazon infrastructure, so they thought, “You know what, maybe we can do IT for someone else, “for other people,” and they introduced their first publicly available product, SQS, in 2004. They revamped and expanded their service in 2006, adding SQS, S3, and EC2 to the mix. They then elaborated by saying, “You know what? We could be anywhere; we don’t have to be in America. Then fast forward to the present day, where there are a tonne of programmes still operating or previously operating on AWS, including NASA, Netflix, Air BNB, Dropbox, and Netflix.

Cloud History

AWS Cloud Use Cases

  • Enables you to build sophisticated, scalable applications
  • Applicable to a diverse set of industries
  • Use cases include
    • Enterprise IT, Backup & Storage, Big Data analytics
    • Website hosting, Mobile & Social Apps
    • Gaming

Regions in AWS

AWS has Regions all around the world:

  • Names can be us-east-1, eu-west-3…
  • A region is a cluster of data centers.
  • Most AWS services are region-scoped

Global Infrastructure

How to select an AWS Region ?

If you need to launch a new application,where should you do it?

  • Compliance with data governance and legal requirements: data never leaves a region without your explicit permission
  • Proximity to customers: reduced latency.
  • Available services within a Region: new services and new features aren’t available in every Region.
  • Pricing: pricing varies region to region and is transparent in the service pricing page.

let’s understand with example:

You are launching a new application. Where should you do it? Should you do it in America, in Europe in South America, or in Australia? Well, the answer is, of course, it depends.

Some factors that may impact your choice of an AWS region. The first one is compliance.

Sometimes governments want the data to be local to the country you are deploying the application. For example, France, data in France may have to stay in France and therefore you should launch your application in the French region. Then, there is also a concept of latency.

If most of your users are going to be in America, it makes a lot of sense to deploy your application in America, close to your users, because they will have a reduced latency. If you deploy your application in Australia and your users are in America, they will have a lot of lags in using your application. Also, not all regions have all services. Some regions do not have services. And so obviously if you are leveraging a service with your application, you need to make sure that the region you are deploying into is available and does have that service.

And finally, pricing does vary from region to region and you need to consult the applicant, the services, and pricing, (indistinct) to see what the differences are between the regions. But this could be obviously a factor that could impact your deployment of an application into a specific region. Now, availability zones are what actually is going into the region.

Availability Zones Of AWS

  • There will be many availability zones in each region. Usually three, with a minimum of two and a maximum of six. But three is more common. Example:
    • ap-southeast-2a
    • ap-southeast-2b
    • ap-southeast-2c
  • Each availability zone (AZ) is one or more discrete data centers with redundant power, networking, and connectivity.
  • They’re separate from each other, so that they’re isolated from disasters.
  • They’re connected with high bandwidth, ultra-low latency networking.

AWS Region

Point of Presence:

The only thing we need to know about AWS for the global infrastructure is the points of presence or edge locations.

  • Amazon has 216 Points of Presence (205 Edge Locations & 11 Regional Caches) in 84 cities across 42 countries.
  • When we offer material to end consumers with the least amount of latency as feasible, this will be incredibly beneficial.

Original article source at: https://blog.knoldus.com/

#aws #guide 

Quick Start Guide with AWS
Sandra Doss

Sandra Doss

1668531993

How To Search For A Developer Job Abroad — Smashing Magazine

While obtaining a job internationally may seem daunting, this guide will walk you through all the steps you need to find & secure a developer job abroad.

#developer #jobsearch #career #guide 

How To Search For A Developer Job Abroad — Smashing Magazine
Rupert  Beatty

Rupert Beatty

1667617740

Swift-style-guide: Linkedin's Official Swift Style Guide

Swift Style Guide

Make sure to read Apple's API Design Guidelines.

Specifics from these guidelines + additional remarks are mentioned below.

This guide was last updated for Swift 4.0 on February 14, 2018.

1. Code Formatting

  • 1.1 Use 4 spaces for tabs.
  • 1.2 Avoid uncomfortably long lines with a hard maximum of 160 characters per line (Xcode->Preferences->Text Editing->Page guide at column: 160 is helpful for this)
  • 1.3 Ensure that there is a newline at the end of every file.
  • 1.4 Ensure that there is no trailing whitespace anywhere (Xcode->Preferences->Text Editing->Automatically trim trailing whitespace + Including whitespace-only lines).
  • 1.5 Do not place opening braces on new lines - we use the 1TBS style.
class SomeClass {
    func someMethod() {
        if x == y {
            /* ... */
        } else if x == z {
            /* ... */
        } else {
            /* ... */
        }
    }

    /* ... */
}
  • 1.6 When writing a type for a property, constant, variable, a key for a dictionary, a function argument, a protocol conformance, or a superclass, don't add a space before the colon.
// specifying type
let pirateViewController: PirateViewController

// dictionary syntax (note that we left-align as opposed to aligning colons)
let ninjaDictionary: [String: AnyObject] = [
    "fightLikeDairyFarmer": false,
    "disgusting": true
]

// declaring a function
func myFunction<T, U: SomeProtocol>(firstArgument: U, secondArgument: T) where T.RelatedType == U {
    /* ... */
}

// calling a function
someFunction(someArgument: "Kitten")

// superclasses
class PirateViewController: UIViewController {
    /* ... */
}

// protocols
extension PirateViewController: UITableViewDataSource {
    /* ... */
}
  • 1.7 In general, there should be a space following a comma.
let myArray = [1, 2, 3, 4, 5]
  • 1.8 There should be a space before and after a binary operator such as +, ==, or ->. There should also not be a space after a ( and before a ).
let myValue = 20 + (30 / 2) * 3
if 1 + 1 == 3 {
    fatalError("The universe is broken.")
}
func pancake(with syrup: Syrup) -> Pancake {
    /* ... */
}
  • 1.9 We follow Xcode's recommended indentation style (i.e. your code should not change if CTRL-I is pressed). When declaring a function that spans multiple lines, prefer using that syntax to which Xcode, as of version 7.3, defaults.
// Xcode indentation for a function declaration that spans multiple lines
func myFunctionWithManyParameters(parameterOne: String,
                                  parameterTwo: String,
                                  parameterThree: String) {
    // Xcode indents to here for this kind of statement
    print("\(parameterOne) \(parameterTwo) \(parameterThree)")
}

// Xcode indentation for a multi-line `if` statement
if myFirstValue > (mySecondValue + myThirdValue)
    && myFourthValue == .someEnumValue {

    // Xcode indents to here for this kind of statement
    print("Hello, World!")
}
  • 1.10 When calling a function that has many parameters, put each argument on a separate line with a single extra indentation.
someFunctionWithManyArguments(
    firstArgument: "Hello, I am a string",
    secondArgument: resultFromSomeFunction(),
    thirdArgument: someOtherLocalProperty)
  • 1.11 When dealing with an implicit array or dictionary large enough to warrant splitting it into multiple lines, treat the [ and ] as if they were braces in a method, if statement, etc. Closures in a method should be treated similarly.
someFunctionWithABunchOfArguments(
    someStringArgument: "hello I am a string",
    someArrayArgument: [
        "dadada daaaa daaaa dadada daaaa daaaa dadada daaaa daaaa",
        "string one is crazy - what is it thinking?"
    ],
    someDictionaryArgument: [
        "dictionary key 1": "some value 1, but also some more text here",
        "dictionary key 2": "some value 2"
    ],
    someClosure: { parameter1 in
        print(parameter1)
    })
  • 1.12 Prefer using local constants or other mitigation techniques to avoid multi-line predicates where possible.
// PREFERRED
let firstCondition = x == firstReallyReallyLongPredicateFunction()
let secondCondition = y == secondReallyReallyLongPredicateFunction()
let thirdCondition = z == thirdReallyReallyLongPredicateFunction()
if firstCondition && secondCondition && thirdCondition {
    // do something
}

// NOT PREFERRED
if x == firstReallyReallyLongPredicateFunction()
    && y == secondReallyReallyLongPredicateFunction()
    && z == thirdReallyReallyLongPredicateFunction() {
    // do something
}

2. Naming

2.1 There is no need for Objective-C style prefixing in Swift (e.g. use just GuybrushThreepwood instead of LIGuybrushThreepwood).

2.2 Use PascalCase for type names (e.g. struct, enum, class, typedef, associatedtype, etc.).

2.3 Use camelCase (initial lowercase letter) for function, method, property, constant, variable, argument names, enum cases, etc.

2.4 When dealing with an acronym or other name that is usually written in all caps, actually use all caps in any names that use this in code. The exception is if this word is at the start of a name that needs to start with lowercase - in this case, use all lowercase for the acronym.

// "HTML" is at the start of a constant name, so we use lowercase "html"
let htmlBodyContent: String = "<p>Hello, World!</p>"
// Prefer using ID to Id
let profileID: Int = 1
// Prefer URLFinder to UrlFinder
class URLFinder {
    /* ... */
}
  • 2.5 All constants that are instance-independent should be static. All such static constants should be placed in a marked section of their class, struct, or enum. For classes with many constants, you should group constants that have similar or the same prefixes, suffixes and/or use cases.
// PREFERRED    
class MyClassName {
    // MARK: - Constants
    static let buttonPadding: CGFloat = 20.0
    static let indianaPi = 3
    static let shared = MyClassName()
}

// NOT PREFERRED
class MyClassName {
    // Don't use `k`-prefix
    static let kButtonPadding: CGFloat = 20.0

    // Don't namespace constants
    enum Constant {
        static let indianaPi = 3
    }
}
  • 2.6 For generics and associated types, use a PascalCase word that describes the generic. If this word clashes with a protocol that it conforms to or a superclass that it subclasses, you can append a Type suffix to the associated type or generic name.
class SomeClass<Model> { /* ... */ }
protocol Modelable {
    associatedtype Model
}
protocol Sequence {
    associatedtype IteratorType: Iterator
}
  • 2.7 Names should be descriptive and unambiguous.
// PREFERRED
class RoundAnimatingButton: UIButton { /* ... */ }

// NOT PREFERRED
class CustomButton: UIButton { /* ... */ }
  • 2.8 Do not abbreviate, use shortened names, or single letter names.
// PREFERRED
class RoundAnimatingButton: UIButton {
    let animationDuration: NSTimeInterval

    func startAnimating() {
        let firstSubview = subviews.first
    }

}

// NOT PREFERRED
class RoundAnimating: UIButton {
    let aniDur: NSTimeInterval

    func srtAnmating() {
        let v = subviews.first
    }
}
  • 2.9 Include type information in constant or variable names when it is not obvious otherwise.
// PREFERRED
class ConnectionTableViewCell: UITableViewCell {
    let personImageView: UIImageView

    let animationDuration: TimeInterval

    // it is ok not to include string in the ivar name here because it's obvious
    // that it's a string from the property name
    let firstName: String

    // though not preferred, it is OK to use `Controller` instead of `ViewController`
    let popupController: UIViewController
    let popupViewController: UIViewController

    // when working with a subclass of `UIViewController` such as a table view
    // controller, collection view controller, split view controller, etc.,
    // fully indicate the type in the name.
    let popupTableViewController: UITableViewController

    // when working with outlets, make sure to specify the outlet type in the
    // property name.
    @IBOutlet weak var submitButton: UIButton!
    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var nameLabel: UILabel!

}

// NOT PREFERRED
class ConnectionTableViewCell: UITableViewCell {
    // this isn't a `UIImage`, so shouldn't be called image
    // use personImageView instead
    let personImage: UIImageView

    // this isn't a `String`, so it should be `textLabel`
    let text: UILabel

    // `animation` is not clearly a time interval
    // use `animationDuration` or `animationTimeInterval` instead
    let animation: TimeInterval

    // this is not obviously a `String`
    // use `transitionText` or `transitionString` instead
    let transition: String

    // this is a view controller - not a view
    let popupView: UIViewController

    // as mentioned previously, we don't want to use abbreviations, so don't use
    // `VC` instead of `ViewController`
    let popupVC: UIViewController

    // even though this is still technically a `UIViewController`, this property
    // should indicate that we are working with a *Table* View Controller
    let popupViewController: UITableViewController

    // for the sake of consistency, we should put the type name at the end of the
    // property name and not at the start
    @IBOutlet weak var btnSubmit: UIButton!
    @IBOutlet weak var buttonSubmit: UIButton!

    // we should always have a type in the property name when dealing with outlets
    // for example, here, we should have `firstNameLabel` instead
    @IBOutlet weak var firstName: UILabel!
}

2.10 When naming function arguments, make sure that the function can be read easily to understand the purpose of each argument.

2.11 As per Apple's API Design Guidelines, a protocol should be named as nouns if they describe what something is doing (e.g. Collection) and using the suffixes able, ible, or ing if it describes a capability (e.g. Equatable, ProgressReporting). If neither of those options makes sense for your use case, you can add a Protocol suffix to the protocol's name as well. Some example protocols are below.

// here, the name is a noun that describes what the protocol does
protocol TableViewSectionProvider {
    func rowHeight(at row: Int) -> CGFloat
    var numberOfRows: Int { get }
    /* ... */
}

// here, the protocol is a capability, and we name it appropriately
protocol Loggable {
    func logCurrentState()
    /* ... */
}

// suppose we have an `InputTextView` class, but we also want a protocol
// to generalize some of the functionality - it might be appropriate to
// use the `Protocol` suffix here
protocol InputTextViewProtocol {
    func sendTrackingEvent()
    func inputText() -> String
    /* ... */
}

3. Coding Style

3.1 General

3.1.1 Prefer let to var whenever possible.

3.1.2 Prefer the composition of map, filter, reduce, etc. over iterating when transforming from one collection to another. Make sure to avoid using closures that have side effects when using these methods.

// PREFERRED
let stringOfInts = [1, 2, 3].flatMap { String($0) }
// ["1", "2", "3"]

// NOT PREFERRED
var stringOfInts: [String] = []
for integer in [1, 2, 3] {
    stringOfInts.append(String(integer))
}

// PREFERRED
let evenNumbers = [4, 8, 15, 16, 23, 42].filter { $0 % 2 == 0 }
// [4, 8, 16, 42]

// NOT PREFERRED
var evenNumbers: [Int] = []
for integer in [4, 8, 15, 16, 23, 42] {
    if integer % 2 == 0 {
        evenNumbers.append(integer)
    }
}

3.1.3 Prefer not declaring types for constants or variables if they can be inferred anyway.

3.1.4 If a function returns multiple values, prefer returning a tuple to using inout arguments (it’s best to use labeled tuples for clarity on what you’re returning if it is not otherwise obvious). If you use a certain tuple more than once, consider using a typealias. If you’re returning 3 or more items in a tuple, consider using a struct or class instead.

func pirateName() -> (firstName: String, lastName: String) {
    return ("Guybrush", "Threepwood")
}

let name = pirateName()
let firstName = name.firstName
let lastName = name.lastName

3.1.5 Be wary of retain cycles when creating delegates/protocols for your classes; typically, these properties should be declared weak.

3.1.6 Be careful when calling self directly from an escaping closure as this can cause a retain cycle - use a capture list when this might be the case:

myFunctionWithEscapingClosure() { [weak self] (error) -> Void in
    // you can do this

    self?.doSomething()

    // or you can do this

    guard let strongSelf = self else {
        return
    }

    strongSelf.doSomething()
}

3.1.7 Don't use labeled breaks.

3.1.8 Don't place parentheses around control flow predicates.

// PREFERRED
if x == y {
    /* ... */
}

// NOT PREFERRED
if (x == y) {
    /* ... */
}
  • 3.1.9 Avoid writing out an enum type where possible - use shorthand.
// PREFERRED
imageView.setImageWithURL(url, type: .person)

// NOT PREFERRED
imageView.setImageWithURL(url, type: AsyncImageView.Type.person)
  • 3.1.10 Don’t use shorthand for class methods since it is generally more difficult to infer the context from class methods as opposed to enums.
// PREFERRED
imageView.backgroundColor = UIColor.white

// NOT PREFERRED
imageView.backgroundColor = .white

3.1.11 Prefer not writing self. unless it is required.

3.1.12 When writing methods, keep in mind whether the method is intended to be overridden or not. If not, mark it as final, though keep in mind that this will prevent the method from being overwritten for testing purposes. In general, final methods result in improved compilation times, so it is good to use this when applicable. Be particularly careful, however, when applying the final keyword in a library since it is non-trivial to change something to be non-final in a library as opposed to have changing something to be non-final in your local project.

3.1.13 When using a statement such as else, catch, etc. that follows a block, put this keyword on the same line as the block. Again, we are following the 1TBS style here. Example if/else and do/catch code is below.

if someBoolean {
    // do something
} else {
    // do something else
}

do {
    let fileContents = try readFile("filename.txt")
} catch {
    print(error)
}

3.1.14 Prefer static to class when declaring a function or property that is associated with a class as opposed to an instance of that class. Only use class if you specifically need the functionality of overriding that function or property in a subclass, though consider using a protocol to achieve this instead.

3.1.15 If you have a function that takes no arguments, has no side effects, and returns some object or value, prefer using a computed property instead.

3.2 Access Modifiers

  • 3.2.1 Write the access modifier keyword first if it is needed.
// PREFERRED
private static let myPrivateNumber: Int

// NOT PREFERRED
static private let myPrivateNumber: Int
  • 3.2.2 The access modifier keyword should not be on a line by itself - keep it inline with what it is describing.
// PREFERRED
open class Pirate {
    /* ... */
}

// NOT PREFERRED
open
class Pirate {
    /* ... */
}

3.2.3 In general, do not write the internal access modifier keyword since it is the default.

3.2.4 If a property needs to be accessed by unit tests, you will have to make it internal to use @testable import ModuleName. If a property should be private, but you declare it to be internal for the purposes of unit testing, make sure you add an appropriate bit of documentation commenting that explains this. You can make use of the - warning: markup syntax for clarity as shown below.

/**
 This property defines the pirate's name.
 - warning: Not `private` for `@testable`.
 */
let pirateName = "LeChuck"

3.2.5 Prefer private to fileprivate where possible.

3.2.6 When choosing between public and open, prefer open if you intend for something to be subclassable outside of a given module and public otherwise. Note that anything internal and above can be subclassed in tests by using @testable import, so this shouldn't be a reason to use open. In general, lean towards being a bit more liberal with using open when it comes to libraries, but a bit more conservative when it comes to modules in a codebase such as an app where it is easy to change things in multiple modules simultaneously.

3.3 Custom Operators

Prefer creating named functions to custom operators.

If you want to introduce a custom operator, make sure that you have a very good reason why you want to introduce a new operator into global scope as opposed to using some other construct.

You can override existing operators to support new types (especially ==). However, your new definitions must preserve the semantics of the operator. For example, == must always test equality and return a boolean.

3.4 Switch Statements and enums

3.4.1 When using a switch statement that has a finite set of possibilities (enum), do NOT include a default case. Instead, place unused cases at the bottom and use the break keyword to prevent execution.

3.4.2 Since switch cases in Swift break by default, do not include the break keyword if it is not needed.

3.4.3 The case statements should line up with the switch statement itself as per default Swift standards.

3.4.4 When defining a case that has an associated value, make sure that this value is appropriately labeled as opposed to just types (e.g. case hunger(hungerLevel: Int) instead of case hunger(Int)).

enum Problem {
    case attitude
    case hair
    case hunger(hungerLevel: Int)
}

func handleProblem(problem: Problem) {
    switch problem {
    case .attitude:
        print("At least I don't have a hair problem.")
    case .hair:
        print("Your barber didn't know when to stop.")
    case .hunger(let hungerLevel):
        print("The hunger level is \(hungerLevel).")
    }
}

3.4.5 Prefer lists of possibilities (e.g. case 1, 2, 3:) to using the fallthrough keyword where possible).

3.4.6 If you have a default case that shouldn't be reached, preferably throw an error (or handle it some other similar way such as asserting).

func handleDigit(_ digit: Int) throws {
    switch digit {
    case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
        print("Yes, \(digit) is a digit!")
    default:
        throw Error(message: "The given number was not a digit.")
    }
}

3.5 Optionals

3.5.1 The only time you should be using implicitly unwrapped optionals is with @IBOutlets. In every other case, it is better to use a non-optional or regular optional property. Yes, there are cases in which you can probably "guarantee" that the property will never be nil when used, but it is better to be safe and consistent. Similarly, don't use force unwraps.

3.5.2 Don't use as! or try!.

3.5.3 If you don't plan on actually using the value stored in an optional, but need to determine whether or not this value is nil, explicitly check this value against nil as opposed to using if let syntax.

// PREFERRED
if someOptional != nil {
    // do something
}

// NOT PREFERRED
if let _ = someOptional {
    // do something
}
  • 3.5.4 Don't use unowned. You can think of unowned as somewhat of an equivalent of a weak property that is implicitly unwrapped (though unowned has slight performance improvements on account of completely ignoring reference counting). Since we don't ever want to have implicit unwraps, we similarly don't want unowned properties.
// PREFERRED
weak var parentViewController: UIViewController?

// NOT PREFERRED
weak var parentViewController: UIViewController!
unowned var parentViewController: UIViewController
  • 3.5.5 When unwrapping optionals, use the same name for the unwrapped constant or variable where appropriate.
guard let myValue = myValue else {
    return
}
  • 3.5.6 Use XCTUnwrap instead of forced unwrapping in tests. ```swift func isEvenNumber(_ number: Int) -> Bool { return number % 2 == 0 }

// PREFERRED func testWithXCTUnwrap() throws { let number: Int? = functionThatReturnsOptionalNumber() XCTAssertTrue(isEvenNumber(try XCTUnwrap(number))) }

// NOT PREFERRED func testWithForcedUnwrap() { let number: Int? = functionThatReturnsOptionalNumber() XCTAssertTrue(isEvenNumber(number!)) // may crash the simulator }


### 3.6 Protocols

When implementing protocols, there are two ways of organizing your code:

1. Using `// MARK:` comments to separate your protocol implementation from the rest of your code
2. Using an extension outside your `class`/`struct` implementation code, but in the same source file

Keep in mind that when using an extension, however, the methods in the extension can't be overridden by a subclass, which can make testing difficult. If this is a common use case, it might be better to stick with method #1 for consistency. Otherwise, method #2 allows for cleaner separation of concerns.

Even when using method #2, add `// MARK:` statements anyway for easier readability in Xcode's method/property/class/etc. list UI.

### 3.7 Properties

* **3.7.1** If making a read-only, computed property, provide the getter without the `get {}` around it.

```swift
var computedProperty: String {
    if someBool {
        return "I'm a mighty pirate!"
    }
    return "I'm selling these fine leather jackets."
}
  • 3.7.2 When using get {}, set {}, willSet, and didSet, indent these blocks.
  • 3.7.3 Though you can create a custom name for the new or old value for willSet/didSet and set, use the standard newValue/oldValue identifiers that are provided by default.
var storedProperty: String = "I'm selling these fine leather jackets." {
    willSet {
        print("will set to \(newValue)")
    }
    didSet {
        print("did set from \(oldValue) to \(storedProperty)")
    }
}

var computedProperty: String  {
    get {
        if someBool {
            return "I'm a mighty pirate!"
        }
        return storedProperty
    }
    set {
        storedProperty = newValue
    }
}
  • 3.7.4 You can declare a singleton property as follows:
class PirateManager {
    static let shared = PirateManager()

    /* ... */
}

3.8 Closures

  • 3.8.1 If the types of the parameters are obvious, it is OK to omit the type name, but being explicit is also OK. Sometimes readability is enhanced by adding clarifying detail and sometimes by taking repetitive parts away - use your best judgment and be consistent.
// omitting the type
doSomethingWithClosure() { response in
    print(response)
}

// explicit type
doSomethingWithClosure() { response: NSURLResponse in
    print(response)
}

// using shorthand in a map statement
[1, 2, 3].flatMap { String($0) }
  • 3.8.2 If specifying a closure as a type, you don’t need to wrap it in parentheses unless it is required (e.g. if the type is optional or the closure is within another closure). Always wrap the arguments in the closure in a set of parentheses - use () to indicate no arguments and use Void to indicate that nothing is returned.
let completionBlock: (Bool) -> Void = { (success) in
    print("Success? \(success)")
}

let completionBlock: () -> Void = {
    print("Completed!")
}

let completionBlock: (() -> Void)? = nil

3.8.3 Keep parameter names on same line as the opening brace for closures when possible without too much horizontal overflow (i.e. ensure lines are less than 160 characters).

3.8.4 Use trailing closure syntax unless the meaning of the closure is not obvious without the parameter name (an example of this could be if a method has parameters for success and failure closures).

// trailing closure
doSomething(1.0) { (parameter1) in
    print("Parameter 1 is \(parameter1)")
}

// no trailing closure
doSomething(1.0, success: { (parameter1) in
    print("Success with \(parameter1)")
}, failure: { (parameter1) in
    print("Failure with \(parameter1)")
})

3.9 Arrays

3.9.1 In general, avoid accessing an array directly with subscripts. When possible, use accessors such as .first or .last, which are optional and won’t crash. Prefer using a for item in items syntax when possible as opposed to something like for i in 0 ..< items.count. If you need to access an array subscript directly, make sure to do proper bounds checking. You can use for (index, value) in items.enumerated() to get both the index and the value.

3.9.2 Never use the += or + operator to append/concatenate to arrays. Instead, use .append() or .append(contentsOf:) as these are far more performant (at least with respect to compilation) in Swift's current state. If you are declaring an array that is based on other arrays and want to keep it immutable, instead of let myNewArray = arr1 + arr2, use let myNewArray = [arr1, arr2].joined().

3.10 Error Handling

Suppose a function myFunction is supposed to return a String, however, at some point it can run into an error. A common approach is to have this function return an optional String? where we return nil if something went wrong.

Example:

func readFile(named filename: String) -> String? {
    guard let file = openFile(named: filename) else {
        return nil
    }

    let fileContents = file.read()
    file.close()
    return fileContents
}

func printSomeFile() {
    let filename = "somefile.txt"
    guard let fileContents = readFile(named: filename) else {
        print("Unable to open file \(filename).")
        return
    }
    print(fileContents)
}

Instead, we should be using Swift's try/catch behavior when it is appropriate to know the reason for the failure.

You can use a struct such as the following:

struct Error: Swift.Error {
    public let file: StaticString
    public let function: StaticString
    public let line: UInt
    public let message: String

    public init(message: String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) {
        self.file = file
        self.function = function
        self.line = line
        self.message = message
    }
}

Example usage:

func readFile(named filename: String) throws -> String {
    guard let file = openFile(named: filename) else {
        throw Error(message: "Unable to open file named \(filename).")
    }

    let fileContents = file.read()
    file.close()
    return fileContents
}

func printSomeFile() {
    do {
        let fileContents = try readFile(named: filename)
        print(fileContents)
    } catch {
        print(error)
    }
}

There are some exceptions in which it does make sense to use an optional as opposed to error handling. When the result should semantically potentially be nil as opposed to something going wrong while retrieving the result, it makes sense to return an optional instead of using error handling.

In general, if a method can "fail", and the reason for the failure is not immediately obvious if using an optional return type, it probably makes sense for the method to throw an error.

3.11 Using guard Statements

  • 3.11.1 In general, we prefer to use an "early return" strategy where applicable as opposed to nesting code in if statements. Using guard statements for this use-case is often helpful and can improve the readability of the code.
// PREFERRED
func eatDoughnut(at index: Int) {
    guard index >= 0 && index < doughnuts.count else {
        // return early because the index is out of bounds
        return
    }

    let doughnut = doughnuts[index]
    eat(doughnut)
}

// NOT PREFERRED
func eatDoughnut(at index: Int) {
    if index >= 0 && index < doughnuts.count {
        let doughnut = doughnuts[index]
        eat(doughnut)
    }
}
  • 3.11.2 When unwrapping optionals, prefer guard statements as opposed to if statements to decrease the amount of nested indentation in your code.
// PREFERRED
guard let monkeyIsland = monkeyIsland else {
    return
}
bookVacation(on: monkeyIsland)
bragAboutVacation(at: monkeyIsland)

// NOT PREFERRED
if let monkeyIsland = monkeyIsland {
    bookVacation(on: monkeyIsland)
    bragAboutVacation(at: monkeyIsland)
}

// EVEN LESS PREFERRED
if monkeyIsland == nil {
    return
}
bookVacation(on: monkeyIsland!)
bragAboutVacation(at: monkeyIsland!)
  • 3.11.3 When deciding between using an if statement or a guard statement when unwrapping optionals is not involved, the most important thing to keep in mind is the readability of the code. There are many possible cases here, such as depending on two different booleans, a complicated logical statement involving multiple comparisons, etc., so in general, use your best judgement to write code that is readable and consistent. If you are unsure whether guard or if is more readable or they seem equally readable, prefer using guard.
// an `if` statement is readable here
if operationFailed {
    return
}

// a `guard` statement is readable here
guard isSuccessful else {
    return
}

// double negative logic like this can get hard to read - i.e. don't do this
guard !operationFailed else {
    return
}
  • 3.11.4 If choosing between two different states, it makes more sense to use an if statement as opposed to a guard statement.
// PREFERRED
if isFriendly {
    print("Hello, nice to meet you!")
} else {
    print("You have the manners of a beggar.")
}

// NOT PREFERRED
guard isFriendly else {
    print("You have the manners of a beggar.")
    return
}

print("Hello, nice to meet you!")
  • 3.11.5 You should also use guard only if a failure should result in exiting the current context. Below is an example in which it makes more sense to use two if statements instead of using two guards - we have two unrelated conditions that should not block one another.
if let monkeyIsland = monkeyIsland {
    bookVacation(onIsland: monkeyIsland)
}

if let woodchuck = woodchuck, canChuckWood(woodchuck) {
    woodchuck.chuckWood()
}
  • 3.11.6 Often, we can run into a situation in which we need to unwrap multiple optionals using guard statements. In general, combine unwraps into a single guard statement if handling the failure of each unwrap is identical (e.g. just a return, break, continue, throw, or some other @noescape).
// combined because we just return
guard let thingOne = thingOne,
    let thingTwo = thingTwo,
    let thingThree = thingThree else {
    return
}

// separate statements because we handle a specific error in each case
guard let thingOne = thingOne else {
    throw Error(message: "Unwrapping thingOne failed.")
}

guard let thingTwo = thingTwo else {
    throw Error(message: "Unwrapping thingTwo failed.")
}

guard let thingThree = thingThree else {
    throw Error(message: "Unwrapping thingThree failed.")
}
  • 3.11.7 Don’t use one-liners for guard statements.
// PREFERRED
guard let thingOne = thingOne else {
    return
}

// NOT PREFERRED
guard let thingOne = thingOne else { return }

4. Documentation/Comments

4.1 Documentation

If a function is more complicated than a simple O(1) operation, you should generally consider adding a doc comment for the function since there could be some information that the method signature does not make immediately obvious. If there are any quirks to the way that something was implemented, whether technically interesting, tricky, not obvious, etc., this should be documented. Documentation should be added for complex classes/structs/enums/protocols and properties. All public functions/classes/properties/constants/structs/enums/protocols/etc. should be documented as well (provided, again, that their signature/name does not make their meaning/functionality immediately obvious).

After writing a doc comment, you should option click the function/property/class/etc. to make sure that everything is formatted correctly.

Be sure to check out the full set of features available in Swift's comment markup described in Apple's Documentation.

Guidelines:

4.1.1 160 character column limit (like the rest of the code).

4.1.2 Even if the doc comment takes up one line, use block (/** */).

4.1.3 Do not prefix each additional line with a *.

4.1.4 Use the new - parameter syntax as opposed to the old :param: syntax (make sure to use lower case parameter and not Parameter). Option-click on a method you wrote to make sure the quick help looks correct.

class Human {
    /**
     This method feeds a certain food to a person.

     - parameter food: The food you want to be eaten.
     - parameter person: The person who should eat the food.
     - returns: True if the food was eaten by the person; false otherwise.
    */
    func feed(_ food: Food, to person: Human) -> Bool {
        // ...
    }
}

4.1.5 If you’re going to be documenting the parameters/returns/throws of a method, document all of them, even if some of the documentation ends up being somewhat repetitive (this is preferable to having the documentation look incomplete). Sometimes, if only a single parameter warrants documentation, it might be better to just mention it in the description instead.

4.1.6 For complicated classes, describe the usage of the class with some potential examples as seems appropriate. Remember that markdown syntax is valid in Swift's comment docs. Newlines, lists, etc. are therefore appropriate.

/**
 ## Feature Support

 This class does some awesome things. It supports:

 - Feature 1
 - Feature 2
 - Feature 3

 ## Examples

 Here is an example use case indented by four spaces because that indicates a
 code block:

     let myAwesomeThing = MyAwesomeClass()
     myAwesomeThing.makeMoney()

 ## Warnings

 There are some things you should be careful of:

 1. Thing one
 2. Thing two
 3. Thing three
 */
class MyAwesomeClass {
    /* ... */
}
  • 4.1.7 When mentioning code, use code ticks - `
/**
 This does something with a `UIViewController`, perchance.
 - warning: Make sure that `someValue` is `true` before running this function.
 */
func myFunction() {
    /* ... */
}
  • 4.1.8 When writing doc comments, prefer brevity where possible.

4.2 Other Commenting Guidelines

  • 4.2.1 Always leave a space after //.
  • 4.2.2 Always leave comments on their own line.
  • 4.2.3 When using // MARK: - whatever, leave a newline after the comment.
class Pirate {

    // MARK: - instance properties

    private let pirateName: String

    // MARK: - initialization

    init() {
        /* ... */
    }

}

Download Details:

Author: linkedin
Source Code: https://github.com/linkedin/swift-style-guide 
License: View license

#swift #style #guide #ios 

Swift-style-guide: Linkedin's Official Swift Style Guide
Anna Shipman

Anna Shipman

1665648034

How to Setup an EV Code Signing Certificate?

An Extended Validated(EV) code signing certificate offers the highest level of security and verifies the publisher's identity by removing the unknown publisher warning as well as the notorious SmartScreen filter. Hence, along with an additional layer of security, it also comes with some extra validation steps that the user has to fulfil through which the certificate authority(CA) will verify the legitimacy of the certificate requesting organisation as per guidelines of the CA/B Forum. Once the validation process is successfully completed, the certificate authority(CA) will send the EV Code Signing certificate along with an HSM device bearing the private key by courier to the requesting organisation's verified address.

This makes us clear that the collection process of an EV Code Signing certificate differs from that of a standard code signing certificate. But, this isn't enough to enable you to digitally sign your software and applications until you install and successfully complete the setup process of the EV code signing certificate issued to you.

Let's learn How to Setup an EV Code Signing Certificate issued to you in an Easy step-by-step guide.

 #howto #guide #codesign #softwaresecurity #cybersec 

How to Setup an EV Code Signing Certificate?
Dexter  Goodwin

Dexter Goodwin

1663113000

9 Favorite JavaScript Tours and Guides Libraries

In today's post we will learn about 9 Favorite JavaScript Tours And Guides Libraries. 

What is Guided Tour?

Guided Tour is an interactive, wizard-style user interface that can be used to guide your users through a tour of your app.

Great for how-tos, application help, newbie guides, new features, featured content, and step-by-step workflow demonstrations of your web applications.

Table of contents:

  • Intro.js - A better way for new feature introduction and step-by-step users guide for your website and project.
  • Bootstrap-tour - Quick and easy product tours with Twitter Bootstrap Popovers.
  • Tourist - Simple, flexible tours for your app.
  • Chardin.js - Simple overlay instructions for your apps.
  • Pageguide - An interactive guide for web page elements using jQuery and CSS3.
  • Hopscotch - A framework to make it easy for developers to add product tours to their pages.
  • Joyride - jQuery feature tour plugin.
  • Focusable - Set a spotlight focus on DOM element adding a overlay layer to the rest of the page.
  • Driver.js - Powerful yet light-weight, vanilla JavaScript engine to drive the user's focus across the page

1 - Intro.js: A better way for new feature introduction and step-by-step users guide for your website and project.

Intro.js - User Onboarding and Product Walkthrough Library

Where to get

You can obtain your local copy of Intro.js from:

1) This GitHub repository, using git clone https://github.com/usablica/intro.js.git

2) Using yarn yarn add intro.js

3) Using npm npm install intro.js --save

4) Download it from CDN (1, 2)

How to use

Intro.js can be added to your site in three simple steps:

1) Include intro.js and introjs.css (or the minified version for production) in your page. Use introjs-rtl.min.css for Right-to-Left language support.

CDN hosted files are available at jsDelivr (click Show More) & cdnjs.

2) Add data-intro and data-step to your HTML elements. To add hints you should use data-hint attribute.

For example:

<a href='http://google.com/' data-intro='Hello step one!'></a>

See all attributes here.

3) Call this JavaScript function:

introJs().start();

Optionally, pass one parameter to introJs function to limit the presentation section.

For example introJs(".introduction-farm").start(); runs the introduction only for elements with class='introduction-farm'.

View on Github

2 - Bootstrap-tour: Quick and easy product tours with Twitter Bootstrap Popovers.

Quick and easy way to build your product tours with Bootstrap Popovers.

Compatible with Bootstrap >= 2.3.0

Develop

Files to be developed are located under ./src/. Compiled sources are then automatically put under ./build/, ./test/ and ./docs/.

Requirements

To begin, you need a few standard dependencies installed. These commands will install ruby, gem, node, yarn, and gulp's command line runner:

Debian/Ubuntu Linux

$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
$ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
$ sudo apt-get update && sudo apt-get install ruby-full yarn

Mac OS X

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew install ruby yarn

Development requirements

$ yarn global add gulp-cli
$ yarn
$ gem install jekyll

For Mac OS X Mavericks (10.9) users: You will need to jump through all these hoops before you can install Jekyll.

View on Github

3 - Tourist: Simple, flexible tours for your app.

Tourist.js is a simple library for creating guided tours through your app. It's better suited to complex, single-page apps than websites. One of our main requirements was the ability to control the interface for each step. For example, a step in the tour might need to open a window or menu to work correctly. Tourist gives you hooks to do this.

Basically, you specify a series of steps which explain elements to point at and what to say. Tourist.js manages moving between those steps.

Install

The code is available via bower install tourist. Once you have the code, you just need to include the javascript file. An optional CSS file with minimal styling is included as well.

<script src="tourist.js"></script>

<!-- Optional! -->
<link rel="stylesheet" href="tourist.css" type="text/css" media="screen">

Dependencies

Tourist depends on Backbone and jQuery. jQuery UI is optional. Tourist uses an easing function from jQuery UI if present in the show effect with the Bootstrap tip implementation.

Tourist comes with the ability to use either Bootstrap 3 popovers (default) or QTip2 tips, so you'll need either Bootstrap 3 CSS (only the CSS is necessary!) or QTip2 installed. You can write your own tooltip connector if you'd like.

Basic Usage

Making a simple tour is easy:

var steps = [{
  // this is a step object
  content: '<p>Hey user, check this out!</p>',
  highlightTarget: true,
  nextButton: true,
  target: $('#thing1'),
  my: 'bottom center',
  at: 'top center'
}, {
  ...
}, ...]

var tour = new Tourist.Tour({
  steps: steps,
  tipOptions:{ showEffect: 'slidein' }
});
tour.start();

View on Github

4 - Chardin.js: Simple overlay instructions for your apps.

nstalling

Simple! Fork this repo or download chardinjs.css and chardinjs.min.js and add the following assets to your HTML:

<link href="chardinjs.css" rel="stylesheet">
<script src="chardinjs.min.js"></script>

There's a chardinjs-rails gem.

Adding data for the instructions

Add the instructions to your elements:

data-intro: Text to show with the instructions/tooltip. data-position: (left, top, right, bottom), where to place the text with respect to the element. In addition you can alter the relative position of the tooltip text by placing a colon and a percentage value (-100 to 100) after the position text, eg "top:-50". This will slide the tooltip along the length or height of the element away from the centre. If you want to increae the distance of the tooltip from the element, you can do it by placing a comma and a percentage value (100, 200, 300, 400 or 500) after the tooltip offset, eg "top:0,200". This will shift the tooltip to be twice farther away from the element than by default.

<img src="img/chardin.png" data-intro="An awesome 18th-century painter, who found beauty in everyday, common things." data-position="right" />

You can also run Chardin in sequenced mode, where one element will be displayed at a time, moving on to the next with a mouse click (or automatically after a set delay). Add data-chardin-sequenced="true" entry to the body tag. Also add data-chardin-auto="true" and data-chardin-delay="100" for automatic movement through the elements. Delay is in milliseconds. The default sequence is as loaded by the DOM, but this can be overridden using the tag data-sequence with a number. If no auto-traversal is set, clicking will move sequentially through the elements, clicking with the shift key down will move backwards through them.

<body data-chardin-sequenced="true" data-chardin-auto="false" data-chardin-delay="800" >

View on Github

5 - Pageguide: An interactive guide for web page elements using jQuery and CSS3.

An interactive, responsive, and smart guide for web page elements using jQuery and CSS3. Works great for dynamic pages and single-page apps as well as static pages. 

Quick Start

Three quick start options are available:

  • Download the latest release
  • Clone the repo: git clone https://github.com/tracelytics/pageguide.git
  • Install with Bower: bower install pageguide

Pageguide comes with an example implementation (the files are in /example) which you can run locally with Grunt. Assuming you have a working copy of npm installed on your machine, open up a terminal, navigate to the root pageguide directory, and run:

$ npm install
$ grunt server

Then navigate to http://localhost:3000/example/ in your browser.

Read the Getting Started page for information on the framework contents and more.

How-To:

  1. Add references in your code to jQuery, pageguide.min.js & pageguide.min.css
  2. Add a single pageguide init() call within a document.ready callback.
  3. Add a simple <ul> to the bottom of the pages you want the pageguide to appear on.
  4. Customize the page guide tour title.
  5. (Optional) Add a welcome message to display to your users on page load.

View on Github

6 - Hopscotch: A framework to make it easy for developers to add product tours to their pages.

Hopscotch is a framework to make it easy for developers to add product tours to their pages. Hopscotch accepts a tour JSON object as input and provides an API for the developer to control rendering the tour display and managing the tour progress.

What's Here?

  • /archives contains .zip and .tar.gz files of prior and current distributions of Hopscotch.
  • /demo has a simple demo page with a Hopscotch tour. Much of the content duplicates what's on the github.io page.
  • /dist includes compiled files for the current version of Hopscotch. This folder gets zipped up into an archive when a new release is published.
  • /src contains source files for Hopscotch, including JavaScript and Less. If you're making changes to contribute back to the core repository, this is where you'll want to make them.
  • /test is our testing suite for the core framework, written using Jasmine.

How do I get started with Hopscotch?

The Hopscotch files included in /dist is a good starting point for working with Hopscotch. Out of the box, Hopscotch includes the core JavaScript for running and interacting with tours, a default template for rendering bubbles, and a default CSS file to provide a basic look and feel for your tours. To get started, simply include these files on your page, then use the Hopscotch API to start a tour. While Hopscotch will use YUI or jQuery if they're present, they're not required.

Check out linkedin.github.io/hopscotch for usage examples and a live sample tour. If you'd like to tweak some of the default assets included with Hopscotch to best suit your project's needs, read on for details about how to modify and rebuild a custom version of Hopscotch.

How do I build Hopscotch?

Hopscotch is built using Grunt.js. Learn more about how to get started with Grunt. Running grunt will build Hopscotch (publishing artifacts to /tmp) and run the test suite against the newly built artifacts.

View on Github

7 - joyride: jQuery feature tour plugin.

Joyride is an easy to configure site tour wizard for Foundation for Sites.

Installation

To install Joyride you can either use NPM (NPM repository) or download the files directly.

  • npm start - Calls the build process and opens the demo in your browser.
  • npm test - Runs the JavaScript tests.
  • npm run test:javascript - Runs tests for JavaScript with Mocha using PhantomJS.
  • npm run test:visual - Runs visual tests/live demos.

Usage

All versions of joyride depend on jQuery and what-input. While jQuery is mandatory, what-input is used for styling purposes and not necessary for joyride to work.

Regardless of the way you use Joyride, you need to initialize it like all Foundation plugins by calling:

$(document).foundation();

The following HTML is an example on how to use Joyride. You can also have a look at the visual test cases in the test/visual/ folder.

<ol data-joyride data-autostart="true" id="docs-joyride">
  <li data-target="#basic-joyride">
    <p>This is the default one without settings</p>
  </li>
  <li data-target="#footer" data-position="bottom" data-closable="false">
    <p>This one isn't closable</p>
  </li>
  <li>
    <p>If no target is specified, you create a modal.</p>
  </li>
  <li data-target="#open-issues">
    <p>Your ride ends here!</p>
    <p class="text-center">
      <button class="button success" data-joyride-close>OK, thanks!</button>
    </p>
  </li>
</ol>

View on Github

8 - Focusable: Set a spotlight focus on DOM element adding a overlay layer to the rest of the page.

An awesome and lightweight library for performing spotlight in your DOM elements, setting an animated overlay to the rest of the page. 

Installation

$ npm i focusable-element --save

$ bower i focusable-element

API

Set spotlight (jQuery style)

$('#my-element').setFocus(options);

Set spotlight (through library)

Focusable.setFocus($('#my-element'), options);

Refresh current focused element

Focusable.refresh();

Hide spotlight

Focusable.hide();

Get focused element

Focusable.getActiveElement();

Get options

Focusable.getOptions();

View on Github

9 - Driver.js: Powerful yet light-weight, vanilla JavaScript engine to drive the user's focus across the page

So, yet another tour library?

No, it is not. Tours are just one of the many use-cases. Driver.js can be used wherever you need some sort of overlay for the page; some common usecases could be: e.g. dimming the background when user is interacting with some component i.e. the way Facebook does when you try to create a post, using it as a focus shifter to bring user's attention to some component on page, or using it to simulate those "Turn off the Lights" widgets that you might have seen on video players online, etc.

Driver.js is written in Vanilla JS, has zero dependencies and is highly customizable. It has several options allowing you to manipulate how it behaves and also provides you the hooks to manipulate the elements as they are highlighted, about to be highlighted, or deselected.

Installation

You can install it using yarn or npm, whatever you prefer.

yarn add driver.js
npm install driver.js

Or include it using CDN. If you want a specific version, put it as driver.js@0.5 in the name

<script src="https://unpkg.com/driver.js/dist/driver.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/driver.js/dist/driver.min.css">

Or grab the code from dist directory and include it directly.

<link rel="stylesheet" href="/dist/driver.min.css">
<script src="/dist/driver.min.js"></script>

Usage and Demo

If you are using some sort of module bundler, import the library and the CSS file

import Driver from 'driver.js';
import 'driver.js/dist/driver.min.css';

otherwise use the script and link tags to import the JavaScript and CSS files.

Demos and many more usage examples can be found in the docs page.

Highlighting Single Element – Demo

You can highlight a single element by simply passing the selector.

const driver = new Driver();
driver.highlight('#create-post');

A real world usage example for this is: using it to dim the background and highlight the required element e.g. the way Facebook does it when creating a post.

Highlight and Popover – Demo

You can show additional details beside the highlighted element using the popover.

const driver = new Driver();
driver.highlight({
  element: '#some-element',
  popover: {
    title: 'Title for the Popover',
    description: 'Description for it',
  }
});

Also, title and description can have HTML as well.

Positioning the Popover – Demo

By default, driver automatically finds the suitable position for the popover and displays it. You can override it using position property.

const driver = new Driver();
driver.highlight({
  element: '#some-element',
  popover: {
    title: 'Title for the Popover',
    description: 'Description for it',
    // position can be left, left-center, left-bottom, top,
    // top-center, top-right, right, right-center, right-bottom,
    // bottom, bottom-center, bottom-right, mid-center
    position: 'left',
  }
});

You can also add offset to the popover position by using the offset property

const driver = new Driver();
driver.highlight({
  element: '#some-element',
  popover: {
    title: 'Title for the Popover',
    description: 'Description for it',
    position: 'bottom',
    // Will show it 20 pixels away from the actual position of popover
    // You may also provide the negative values
    offset: 20,
  }
});

Creating Feature Introductions – Demo

Feature introductions are helpful when onboarding new users and giving them an idea about different parts of the application; you can create them seamlessly with Driver. Define the steps and call the start when you want to start presenting. User will be able to control the steps using the keyboard or using the buttons on popovers.

const driver = new Driver();

// Define the steps for introduction
driver.defineSteps([
  {
    element: '#first-element-introduction',
    popover: {
      className: 'first-step-popover-class',
      title: 'Title on Popover',
      description: 'Body of the popover',
      position: 'left'
    }
  },
  {
    element: '#second-element-introduction',
    popover: {
      title: 'Title on Popover',
      description: 'Body of the popover',
      position: 'top'
    }
  },
  {
    element: '#third-element-introduction',
    popover: {
      title: 'Title on Popover',
      description: 'Body of the popover',
      position: 'right'
    }
  },
]);

// Start the introduction
driver.start();

You can also hide the buttons and control the introductions programmatically by using the API methods listed below.

View on Github

Thank you for following this article.

Related videos:

Top 10 JavaScript Libraries You Must Know

#javascript #guide 

9 Favorite JavaScript Tours and Guides Libraries
Royce  Reinger

Royce Reinger

1649392464

Flight Rules for Git: Guide About What to Do When Things Go Wrong

Flight rules for Git

What are "flight rules"?

A guide for astronauts (now, programmers using Git) about what to do when things go wrong.

Flight Rules are the hard-earned body of knowledge recorded in manuals that list, step-by-step, what to do if X occurs, and why. Essentially, they are extremely detailed, scenario-specific standard operating procedures. [...]

NASA has been capturing our missteps, disasters and solutions since the early 1960s, when Mercury-era ground teams first started gathering "lessons learned" into a compendium that now lists thousands of problematic situations, from engine failure to busted hatch handles to computer glitches, and their solutions.

— Chris Hadfield, An Astronaut's Guide to Life on Earth.

Conventions for this document

For clarity's sake all examples in this document use a customized bash prompt in order to indicate the current branch and whether or not there are staged changes. The branch is enclosed in parentheses, and a * next to the branch name indicates staged changes.

All commands should work for at least git version 2.13.0. See the git website to update your local git version. 

Table of Contents generated with DocToc

Repositories

I want to start a local repository

To initialize an existing directory as a Git repository:

(my-folder) $ git init

I want to clone a remote repository

To clone (copy) a remote repository, copy the URL for the repository, and run:

$ git clone [url]

This will save it to a folder named the same as the remote repository's. Make sure you have a connection to the remote server you are cloning from (for most purposes this means making sure you are connected to the internet).

To clone it into a folder with a different name than the default repository name:

$ git clone [url] name-of-new-folder

I set the wrong remote repository

There are a few possible problems here:

If you cloned the wrong repository, simply delete the directory created after running git clone and clone the correct repository.

If you set the wrong repository as the origin of an existing local repository, change the URL of your origin by running:

$ git remote set-url origin [url of the actual repo]

For more, see this StackOverflow topic.

I want to add code to someone else's repository

Git doesn't allow you to add code to someone else's repository without access rights. Neither does GitHub, which is not the same as Git, but rather a hosted service for Git repositories. However, you can suggest code using patches, or, on GitHub, forks and pull requests.

First, a bit about forking. A fork is a copy of a repository. It is not a git operation, but is a common action on GitHub, Bitbucket, GitLab — or anywhere people host Git repositories. You can fork a repository through the hosted UI.

Suggesting code via pull requests

After you've forked a repository, you normally need to clone the repository to your machine. You can do some small edits on GitHub, for instance, without cloning, but this isn't a github-flight-rules list, so let's go with how to do this locally.

# if you are using ssh
$ git clone git@github.com:k88hudson/git-flight-rules.git

# if you are using https
$ git clone https://github.com/k88hudson/git-flight-rules.git

If you cd into the resulting directory, and type git remote, you'll see a list of the remotes. Normally there will be one remote - origin - which will point to k88hudson/git-flight-rules. In this case, we also want a remote that will point to your fork.

First, to follow a Git convention, we normally use the remote name origin for your own repository and upstream for whatever you've forked. So, rename the origin remote to upstream

$ git remote rename origin upstream

You can also do this using git remote set-url, but it takes longer and is more steps.

Then, set up a new remote that points to your project.

$ git remote add origin git@github.com:YourName/git-flight-rules.git

Note that now you have two remotes.

  • origin references your own repository.
  • upstream references the original one.

From origin, you can read and write. From upstream, you can only read.

When you've finished making whatever changes you like, push your changes (normally in a branch) to the remote named origin. If you're on a branch, you could use --set-upstream to avoid specifying the remote tracking branch on every future push using this branch. For instance:

$ (feature/my-feature) git push --set-upstream origin feature/my-feature

There is no way to suggest a pull request using the CLI using Git (although there are tools, like hub, which will do this for you). So, if you're ready to make a pull request, go to your GitHub (or another Git host) and create a new pull request. Note that your host automatically links the original and forked repositories.

After all of this, do not forget to respond to any code review feedback.

Suggesting code via patches

Another approach to suggesting code changes that doesn't rely on third party sites such as Github is to use git format-patch.

format-patch creates a .patch file for one or more commits. This file is essentially a list of changes that looks similar to the commit diffs you can view on Github.

A patch can be viewed and even edited by the recipient and applied using git am.

For example, to create a patch based on the previous commit you would run git format-patch HEAD^ which would create a .patch file called something like 0001-My-Commit-Message.patch.

To apply this patch file to your repository you would run git am ./0001-My-Commit-Message.patch.

Patches can also be sent via email using the git send-email command. For information on usage and configuration see: https://git-send-email.io

I need to update my fork with latest updates from the original repository

After a while, the upstream repository may have been updated, and these updates need to be pulled into your origin repo. Remember that like you, other people are contributing too. Suppose that you are in your own feature branch and you need to update it with the original repository updates.

You probably have set up a remote that points to the original project. If not, do this now. Generally we use upstream as a remote name:

$ (main) git remote add upstream <link-to-original-repository>
# $ (main) git remote add upstream git@github.com:k88hudson/git-flight-rules.git

Now you can fetch from upstream and get the latest updates.

$ (main) git fetch upstream
$ (main) git merge upstream/main

# or using a single command
$ (main) git pull upstream main

Editing Commits

 

What did I just commit?

Let's say that you just blindly committed changes with git commit -a and you're not sure what the actual content of the commit you just made was. You can show the latest commit on your current HEAD with:

(main)$ git show

Or

$ git log -n1 -p

If you want to see a file at a specific commit, you can also do this (where <commitid> is the commit you're interested in):

$ git show <commitid>:filename

I wrote the wrong thing in a commit message

If you wrote the wrong thing and the commit has not yet been pushed, you can do the following to change the commit message without changing the changes in the commit:

$ git commit --amend --only

This will open your default text editor, where you can edit the message. On the other hand, you can do this all in one command:

$ git commit --amend --only -m 'xxxxxxx'

If you have already pushed the message, you can amend the commit and force push, but this is not recommended.

 

I committed with the wrong name and email configured

If it's a single commit, amend it

$ git commit --amend --no-edit --author "New Authorname <authoremail@mydomain.com>"

An alternative is to correctly configure your author settings in git config --global author.(name|email) and then use

$ git commit --amend --reset-author --no-edit

If you need to change all of history, see the man page for git filter-branch.

I want to remove a file from the previous commit

In order to remove changes for a file from the previous commit, do the following:

$ git checkout HEAD^ myfile
$ git add myfile
$ git commit --amend --no-edit

In case the file was newly added to the commit and you want to remove it (from Git alone), do:

$ git rm --cached myfile
$ git commit --amend --no-edit

This is particularly useful when you have an open patch and you have committed an unnecessary file, and need to force push to update the patch on a remote. The --no-edit option is used to keep the existing commit message.

 

I want to delete or remove my last commit

If you need to delete pushed commits, you can use the following. However, it will irreversibly change your history, and mess up the history of anyone else who had already pulled from the repository. In short, if you're not sure, you should never do this, ever.

$ git reset HEAD^ --hard
$ git push --force-with-lease [remote] [branch]

If you haven't pushed, to reset Git to the state it was in before you made your last commit (while keeping your staged changes):

(my-branch*)$ git reset --soft HEAD@{1}

This only works if you haven't pushed. If you have pushed, the only truly safe thing to do is git revert SHAofBadCommit. That will create a new commit that undoes all the previous commit's changes. Or, if the branch you pushed to is rebase-safe (ie. other devs aren't expected to pull from it), you can just use git push --force-with-lease. For more, see the above section.

 

Delete/remove arbitrary commit

The same warning applies as above. Never do this if possible.

$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT
$ git push --force-with-lease [remote] [branch]

Or do an interactive rebase and remove the line(s) corresponding to commit(s) you want to see removed.

 

I tried to push my amended commit to a remote, but I got an error message

To https://github.com/yourusername/repo.git
! [rejected]        mybranch -> mybranch (non-fast-forward)
error: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Note that, as with rebasing (see below), amending replaces the old commit with a new one, so you must force push (--force-with-lease) your changes if you have already pushed the pre-amended commit to your remote. Be careful when you do this – always make sure you specify a branch!

(my-branch)$ git push origin mybranch --force-with-lease

In general, avoid force pushing. It is best to create and push a new commit rather than force-pushing the amended commit as it will cause conflicts in the source history for any other developer who has interacted with the branch in question or any child branches. --force-with-lease will still fail, if someone else was also working on the same branch as you, and your push would overwrite those changes.

If you are absolutely sure that nobody is working on the same branch or you want to update the tip of the branch unconditionally, you can use --force (-f), but this should be avoided in general.

 

I accidentally did a hard reset, and I want my changes back

If you accidentally do git reset --hard, you can normally still get your commit back, as git keeps a log of everything for a few days.

Note: This is only valid if your work is backed up, i.e., either committed or stashed. git reset --hard will remove uncommitted modifications, so use it with caution. (A safer option is git reset --keep.)

(main)$ git reflog

You'll see a list of your past commits, and a commit for the reset. Choose the SHA of the commit you want to return to, and reset again:

(main)$ git reset --hard SHA1234

And you should be good to go.

I accidentally committed and pushed a merge

If you accidentally merged a feature branch to the main development branch before it was ready to be merged, you can still undo the merge. But there's a catch: A merge commit has more than one parent (usually two).

The command to use

(feature-branch)$ git revert -m 1 <commit>

where the -m 1 option says to select parent number 1 (the branch into which the merge was made) as the parent to revert to.

Note: the parent number is not a commit identifier. Rather, a merge commit has a line Merge: 8e2ce2d 86ac2e7. The parent number is the 1-based index of the desired parent on this line, the first identifier is number 1, the second is number 2, and so on.

I accidentally committed and pushed files containing sensitive data

If you accidentally pushed files containing sensitive, or private data (passwords, keys, etc.), you can amend the previous commit. Keep in mind that once you have pushed a commit, you should consider any data it contains to be compromised. These steps can remove the sensitive data from your public repo or your local copy, but you cannot remove the sensitive data from other people's pulled copies. If you committed a password, change it immediately. If you committed a key, re-generate it immediately. Amending the pushed commit is not enough, since anyone could have pulled the original commit containing your sensitive data in the meantime.

If you edit the file and remove the sensitive data, then run

(feature-branch)$ git add edited_file
(feature-branch)$ git commit --amend --no-edit
(feature-branch)$ git push --force-with-lease origin [branch]

If you want to remove an entire file (but keep it locally), then run

(feature-branch)$ git rm --cached sensitive_file
echo sensitive_file >> .gitignore
(feature-branch)$ git add .gitignore
(feature-branch)$ git commit --amend --no-edit
(feature-branch)$ git push --force-with-lease origin [branch]

Alternatively store your sensitive data in local environment variables.

If you want to completely remove an entire file (and not keep it locally), then run

(feature-branch)$ git rm sensitive_file
(feature-branch)$ git commit --amend --no-edit
(feature-branch)$ git push --force-with-lease origin [branch]

If you have made other commits in the meantime (i.e. the sensitive data is in a commit before the previous commit), you will have to rebase.

I want to remove a large file from ever existing in repo history

If the file you want to delete is secret or sensitive, instead see how to remove sensitive files.

Even if you delete a large or unwanted file in a recent commit, it still exists in git history, in your repo's .git folder, and will make git clone download unneeded files.

The actions in this part of the guide will require a force push, and rewrite large sections of repo history, so if you are working with remote collaborators, check first that any local work of theirs is pushed.

There are two options for rewriting history, the built-in git-filter-branch or bfg-repo-cleaner. bfg is significantly cleaner and more performant, but it is a third-party download and requires java. We will describe both alternatives. The final step is to force push your changes, which requires special consideration on top of a regular force push, given that a great deal of repo history will have been permanently changed.

Recommended Technique: Use third-party bfg

Using bfg-repo-cleaner requires java. Download the bfg jar from the link here. Our examples will use bfg.jar, but your download may have a version number, e.g. bfg-1.13.0.jar.

To delete a specific file.

(main)$ git rm path/to/filetoremove
(main)$ git commit -m "Commit removing filetoremove"
(main)$ java -jar ~/Downloads/bfg.jar --delete-files filetoremove

Note that in bfg you must use the plain file name even if it is in a subdirectory.

You can also delete a file by pattern, e.g.:

(main)$ git rm *.jpg
(main)$ git commit -m "Commit removing *.jpg"
(main)$ java -jar ~/Downloads/bfg.jar --delete-files *.jpg

With bfg, the files that exist on your latest commit will not be affected. For example, if you had several large .tga files in your repo, and then in an earlier commit, you deleted a subset of them, this call does not touch files present in the latest commit

Note, if you renamed a file as part of a commit, e.g. if it started as LargeFileFirstName.mp4 and a commit changed it to LargeFileSecondName.mp4, running java -jar ~/Downloads/bfg.jar --delete-files LargeFileSecondName.mp4 will not remove it from git history. Either run the --delete-files command with both filenames, or with a matching pattern.

Built-in Technique: Use git-filter-branch

git-filter-branch is more cumbersome and has less features, but you may use it if you cannot install or run bfg.

In the below, replace filepattern may be a specific name or pattern, e.g. *.jpg. This will remove files matching the pattern from all history and branches.

(main)$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch filepattern' --prune-empty --tag-name-filter cat -- --all

Behind-the-scenes explanation:

--tag-name-filter cat is a cumbersome, but simplest, way to apply the original tags to the new commits, using the command cat.

--prune-empty removes any now-empty commits.

Final Step: Pushing your changed repo history

Once you have removed your desired files, test carefully that you haven't broken anything in your repo - if you have, it is easiest to re-clone your repo to start over. To finish, optionally use git garbage collection to minimize your local .git folder size, and then force push.

(main)$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
(main)$ git push origin --force --tags

Since you just rewrote the entire git repo history, the git push operation may be too large, and return the error “The remote end hung up unexpectedly”. If this happens, you can try increasing the git post buffer:

(main)$ git config http.postBuffer 524288000
(main)$ git push --force

If this does not work, you will need to manually push the repo history in chunks of commits. In the command below, try increasing <number> until the push operation succeeds.

(main)$ git push -u origin HEAD~<number>:refs/head/main --force

Once the push operation succeeds the first time, decrease <number> gradually until a conventional git push succeeds.

 

I need to change the content of a commit which is not my last

Consider you created some (e.g. three) commits and later realize you missed doing something that belongs contextually into the first of those commits. This bothers you, because if you'd create a new commit containing those changes, you'd have a clean code base, but your commits weren't atomic (i.e. changes that belonged to each other weren't in the same commit). In such a situation you may want to change the commit where these changes belong to, include them and have the following commits unaltered. In such a case, git rebase might save you.

Consider a situation where you want to change the third last commit you made.

(your-branch)$ git rebase -i HEAD~4

gets you into interactive rebase mode, which allows you to edit any of your last three commits. A text editor pops up, showing you something like

pick 9e1d264 The third last commit
pick 4b6e19a The second to last commit
pick f4037ec The last commit

which you change into

edit 9e1d264 The third last commit
pick 4b6e19a The second to last commit
pick f4037ec The last commit

This tells rebase that you want to edit your third last commit and keep the other two unaltered. Then you'll save (and close) the editor. Git will then start to rebase. It stops on the commit you want to alter, giving you the chance to edit that commit. Now you can apply the changes which you missed applying when you initially committed that commit. You do so by editing and staging them. Afterwards you'll run

(your-branch)$ git commit --amend

which tells Git to recreate the commit, but to leave the commit message unedited. Having done that, the hard part is solved.

(your-branch)$ git rebase --continue

will do the rest of the work for you.

Staging

I want to stage all tracked files and leave untracked files

$ git add -u

To stage part of tracked files

# to stage files with ext .txt
$ git add -u *.txt

# to stage all files inside directory src
$ git add -u src/

I need to add staged changes to the previous commit

(my-branch*)$ git commit --amend

If you already know you don't want to change the commit message, you can tell git to reuse the commit message:

(my-branch*)$ git commit --amend -C HEAD

I want to stage part of a new file, but not the whole file

Normally, if you want to stage part of a file, you run this:

$ git add --patch filename.x

-p will work for short. This will open interactive mode. You would be able to use the s option to split the commit - however, if the file is new, you will not have this option. To add a new file, do this:

$ git add -N filename.x

Then, you will need to use the e option to manually choose which lines to add. Running git diff --cached or git diff --staged will show you which lines you have staged compared to which are still saved locally.

I want to add changes in one file to two different commits

git add will add the entire file to a commit. git add -p will allow to interactively select which changes you want to add.

I staged too many edits, and I want to break them out into a separate commit

git reset -p will open a patch mode reset dialog. This is similar to git add -p, except that selecting "yes" will unstage the change, removing it from the upcoming commit.

I want to stage my unstaged edits, and unstage my staged edits

In many cases, you should unstage all of your staged files and then pick the file you want and commit it. However, if you want to switch the staged and unstaged edits, you can create a temporary commit to store your staged files, stage your unstaged files and then stash them. Then, reset the temporary commit and pop your stash.

$ git commit -m "WIP"
$ git add . # This will also add untracked files.
$ git stash
$ git reset HEAD^
$ git stash pop --index 0

NOTE 1: The reason to use pop here is want to keep idempotent as much as possible. NOTE 2: Your staged files will be marked as unstaged if you don't use the --index flag. (This link explains why.)

Unstaged Edits

I want to move my unstaged edits to a new branch

$ git checkout -b my-branch

I want to move my unstaged edits to a different, existing branch

$ git stash
$ git checkout my-branch
$ git stash pop

I want to discard my local uncommitted changes (staged and unstaged)

If you want to discard all your local staged and unstaged changes, you can do this:

(my-branch)$ git reset --hard
# or
(main)$ git checkout -f

This will unstage all files you might have staged with git add:

$ git reset

This will revert all local uncommitted changes (should be executed in repo root):

$ git checkout .

You can also revert uncommitted changes to a particular file or directory:

$ git checkout [some_dir|file.txt]

Yet another way to revert all uncommitted changes (longer to type, but works from any subdirectory):

$ git reset --hard HEAD

This will remove all local untracked files, so only files tracked by Git remain:

$ git clean -fd

-x will also remove all ignored files.

I want to discard specific unstaged changes

When you want to get rid of some, but not all changes in your working copy.

Checkout undesired changes, keep good changes.

$ git checkout -p
# Answer y to all of the snippets you want to drop

Another strategy involves using stash. Stash all the good changes, reset working copy, and reapply good changes.

$ git stash -p
# Select all of the snippets you want to save
$ git reset --hard
$ git stash pop

Alternatively, stash your undesired changes, and then drop stash.

$ git stash -p
# Select all of the snippets you don't want to save
$ git stash drop

I want to discard specific unstaged files

When you want to get rid of one specific file in your working copy.

$ git checkout myFile

Alternatively, to discard multiple files in your working copy, list them all.

$ git checkout myFirstFile mySecondFile

I want to discard only my unstaged local changes

When you want to get rid of all of your unstaged local uncommitted changes

$ git checkout .

I want to discard all of my untracked files

When you want to get rid of all of your untracked files

$ git clean -f

I want to unstage a specific staged file

Sometimes we have one or more files that accidentally ended up being staged, and these files have not been committed before. To unstage them:

$ git reset -- <filename>

This results in unstaging the file and make it look like it's untracked.

Branches

I want to list all branches

List local branches

$ git branch

List remote branches

$ git branch -r

List all branches (both local and remote)

$ git branch -a

 

Create a branch from a commit

$ git checkout -b <branch> <SHA1_OF_COMMIT>

 

I pulled from/into the wrong branch

This is another chance to use git reflog to see where your HEAD pointed before the bad pull.

(main)$ git reflog
ab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward
c5bc55a HEAD@{1}: checkout: checkout message goes here

Simply reset your branch back to the desired commit:

$ git reset --hard c5bc55a

Done.

 

I want to discard local commits so my branch is the same as one on the server

Confirm that you haven't pushed your changes to the server.

git status should show how many commits you are ahead of origin:

(my-branch)$ git status
# On branch my-branch
# Your branch is ahead of 'origin/my-branch' by 2 commits.
#   (use "git push" to publish your local commits)
#

One way of resetting to match origin (to have the same as what is on the remote) is to do this:

(main)$ git reset --hard origin/my-branch

 

I committed to main instead of a new branch

Create the new branch while remaining on main:

(main)$ git branch my-branch

Reset the branch main to the previous commit:

(main)$ git reset --hard HEAD^

HEAD^ is short for HEAD^1. This stands for the first parent of HEAD, similarly HEAD^2 stands for the second parent of the commit (merges can have 2 parents).

Note that HEAD^2 is not the same as HEAD~2 (see this link for more information).

Alternatively, if you don't want to use HEAD^, find out what the commit hash you want to set your main branch to (git log should do the trick). Then reset to that hash. git push will make sure that this change is reflected on your remote.

For example, if the hash of the commit that your main branch is supposed to be at is a13b85e:

(main)$ git reset --hard a13b85e
HEAD is now at a13b85e

Checkout the new branch to continue working:

(main)$ git checkout my-branch

 

I want to keep the whole file from another ref-ish

Say you have a working spike (see note), with hundreds of changes. Everything is working. Now, you commit into another branch to save that work:

(solution)$ git add -A && git commit -m "Adding all changes from this spike into one big commit."

When you want to put it into a branch (maybe feature, maybe develop), you're interested in keeping whole files. You want to split your big commit into smaller ones.

Say you have:

  • branch solution, with the solution to your spike. One ahead of develop.
  • branch develop, where you want to add your changes.

You can solve it bringing the contents to your branch:

(develop)$ git checkout solution -- file1.txt

This will get the contents of that file in branch solution to your branch develop:

# On branch develop
# Your branch is up-to-date with 'origin/develop'.
# Changes to be committed:
#  (use "git reset HEAD <file>..." to unstage)
#
#        modified:   file1.txt

Then, commit as usual.

Note: Spike solutions are made to analyze or solve the problem. These solutions are used for estimation and discarded once everyone gets clear visualization of the problem. ~ Wikipedia.

 

I made several commits on a single branch that should be on different branches

Say you are on your main branch. Running git log, you see you have made two commits:

(main)$ git log

commit e3851e817c451cc36f2e6f3049db528415e3c114
Author: Alex Lee <alexlee@example.com>
Date:   Tue Jul 22 15:39:27 2014 -0400

    Bug #21 - Added CSRF protection

commit 5ea51731d150f7ddc4a365437931cd8be3bf3131
Author: Alex Lee <alexlee@example.com>
Date:   Tue Jul 22 15:39:12 2014 -0400

    Bug #14 - Fixed spacing on title

commit a13b85e984171c6e2a1729bb061994525f626d14
Author: Aki Rose <akirose@example.com>
Date:   Tue Jul 21 01:12:48 2014 -0400

    First commit

Let's take note of our commit hashes for each bug (e3851e8 for #21, 5ea5173 for #14).

First, let's reset our main branch to the correct commit (a13b85e):

(main)$ git reset --hard a13b85e
HEAD is now at a13b85e

Now, we can create a fresh branch for our bug #21:

(main)$ git checkout -b 21
(21)$

Now, let's cherry-pick the commit for bug #21 on top of our branch. That means we will be applying that commit, and only that commit, directly on top of whatever our head is at.

(21)$ git cherry-pick e3851e8

At this point, there is a possibility there might be conflicts. See the There were conflicts section in the interactive rebasing section above for how to resolve conflicts.

Now let's create a new branch for bug #14, also based on main

(21)$ git checkout main
(main)$ git checkout -b 14
(14)$

And finally, let's cherry-pick the commit for bug #14:

(14)$ git cherry-pick 5ea5173

 

I want to delete local branches that were deleted upstream

Once you merge a pull request on GitHub, it gives you the option to delete the merged branch in your fork. If you aren't planning to keep working on the branch, it's cleaner to delete the local copies of the branch so you don't end up cluttering up your working checkout with a lot of stale branches.

$ git fetch -p upstream

where, upstream is the remote you want to fetch from.

 

I accidentally deleted my branch

If you're regularly pushing to remote, you should be safe most of the time. But still sometimes you may end up deleting your branches. Let's say we create a branch and create a new file:

(main)$ git checkout -b my-branch
(my-branch)$ git branch
(my-branch)$ touch foo.txt
(my-branch)$ ls
README.md foo.txt

Let's add it and commit.

(my-branch)$ git add .
(my-branch)$ git commit -m 'foo.txt added'
(my-branch)$ foo.txt added
 1 files changed, 1 insertions(+)
 create mode 100644 foo.txt
(my-branch)$ git log

commit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012
Author: siemiatj <siemiatj@example.com>
Date:   Wed Jul 30 00:34:10 2014 +0200

    foo.txt added

commit 69204cdf0acbab201619d95ad8295928e7f411d5
Author: Kate Hudson <katehudson@example.com>
Date:   Tue Jul 29 13:14:46 2014 -0400

    Fixes #6: Force pushing after amending commits

Now we're switching back to main and 'accidentally' removing our branch.

(my-branch)$ git checkout main
Switched to branch 'main'
Your branch is up-to-date with 'origin/main'.
(main)$ git branch -D my-branch
Deleted branch my-branch (was 4e3cd85).
(main)$ echo oh noes, deleted my branch!
oh noes, deleted my branch!

At this point you should get familiar with 'reflog', an upgraded logger. It stores the history of all the action in the repo.

(main)$ git reflog
69204cd HEAD@{0}: checkout: moving from my-branch to main
4e3cd85 HEAD@{1}: commit: foo.txt added
69204cd HEAD@{2}: checkout: moving from main to my-branch

As you can see we have commit hash from our deleted branch. Let's see if we can restore our deleted branch.

(main)$ git checkout -b my-branch-help
Switched to a new branch 'my-branch-help'
(my-branch-help)$ git reset --hard 4e3cd85
HEAD is now at 4e3cd85 foo.txt added
(my-branch-help)$ ls
README.md foo.txt

Voila! We got our removed file back. git reflog is also useful when rebasing goes terribly wrong.

I want to delete a branch

To delete a remote branch:

(main)$ git push origin --delete my-branch

You can also do:

(main)$ git push origin :my-branch

To delete a local branch:

(main)$ git branch -d my-branch

To delete a local branch that has not been merged to the current branch or an upstream:

(main)$ git branch -D my-branch

I want to delete multiple branches

Say you want to delete all branches that start with fix/:

(main)$ git branch | grep 'fix/' | xargs git branch -d

I want to rename a branch

To rename the current (local) branch:

(main)$ git branch -m new-name

To rename a different (local) branch:

(main)$ git branch -m old-name new-name

To delete the old-name remote branch and push the new-name local branch:

(main)$ git push origin :old_name new_name

 

I want to checkout to a remote branch that someone else is working on

First, fetch all branches from remote:

(main)$ git fetch --all

Say you want to checkout to daves from the remote.

(main)$ git checkout --track origin/daves
Branch daves set up to track remote branch daves from origin.
Switched to a new branch 'daves'

(--track is shorthand for git checkout -b [branch] [remotename]/[branch])

This will give you a local copy of the branch daves, and any update that has been pushed will also show up remotely.

I want to create a new remote branch from current local one

$ git push <remote> HEAD

If you would also like to set that remote branch as upstream for the current one, use the following instead:

$ git push -u <remote> HEAD

With the upstream mode and the simple (default in Git 2.0) mode of the push.default config, the following command will push the current branch with regards to the remote branch that has been registered previously with -u:

$ git push

The behavior of the other modes of git push is described in the doc of push.default.

I want to set a remote branch as the upstream for a local branch

You can set a remote branch as the upstream for the current local branch using:

$ git branch --set-upstream-to [remotename]/[branch]
# or, using the shorthand:
$ git branch -u [remotename]/[branch]

To set the upstream remote branch for another local branch:

$ git branch -u [remotename]/[branch] [local-branch]

 

I want to set my HEAD to track the default remote branch

By checking your remote branches, you can see which remote branch your HEAD is tracking. In some cases, this is not the desired branch.

$ git branch -r
  origin/HEAD -> origin/gh-pages
  origin/main

To change origin/HEAD to track origin/main, you can run this command:

$ git remote set-head origin --auto
origin/HEAD set to main

I made changes on the wrong branch

You've made uncommitted changes and realise you're on the wrong branch. Stash changes and apply them to the branch you want:

(wrong_branch)$ git stash
(wrong_branch)$ git checkout <correct_branch>
(correct_branch)$ git stash apply

 

I want to split a branch into two

You've made a lot of commits on a branch and now want to separate it into two, ending with a branch up to an earlier commit and another with all the changes.

Use git log to find the commit where you want to split. Then do the following:

(original_branch)$ git checkout -b new_branch
(new_branch)$ git checkout original_branch
(original_branch)$ git reset --hard <sha1 split here>

If you had previously pushed the original_branch to remote, you will need to do a force push. For more information check Stack Overlflow

Rebasing and Merging

 

I want to undo rebase/merge

You may have merged or rebased your current branch with a wrong branch, or you can't figure it out or finish the rebase/merge process. Git saves the original HEAD pointer in a variable called ORIG_HEAD before doing dangerous operations, so it is simple to recover your branch at the state before the rebase/merge.

(my-branch)$ git reset --hard ORIG_HEAD

 

I rebased, but I don't want to force push

Unfortunately, you have to force push, if you want those changes to be reflected on the remote branch. This is because you have changed the history. The remote branch won't accept changes unless you force push. This is one of the main reasons many people use a merge workflow, instead of a rebasing workflow - large teams can get into trouble with developers force pushing. Use this with caution. A safer way to use rebase is not to reflect your changes on the remote branch at all, and instead to do the following:

(main)$ git checkout my-branch
(my-branch)$ git rebase -i main
(my-branch)$ git checkout main
(main)$ git merge --ff-only my-branch

For more, see this SO thread.

 

I need to combine commits

Let's suppose you are working in a branch that is/will become a pull-request against main. In the simplest case when all you want to do is to combine all commits into a single one and you don't care about commit timestamps, you can reset and recommit. Make sure the main branch is up to date and all your changes committed, then:

(my-branch)$ git reset --soft main
(my-branch)$ git commit -am "New awesome feature"

If you want more control, and also to preserve timestamps, you need to do something called an interactive rebase:

(my-branch)$ git rebase -i main

If you aren't working against another branch you'll have to rebase relative to your HEAD. If you want to squash the last 2 commits, for example, you'll have to rebase against HEAD~2. For the last 3, HEAD~3, etc.

(main)$ git rebase -i HEAD~2

After you run the interactive rebase command, you will see something like this in your text editor:

pick a9c8a1d Some refactoring
pick 01b2fd8 New awesome feature
pick b729ad5 fixup
pick e3851e8 another fix

# Rebase 8074d12..b729ad5 onto 8074d12
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

All the lines beginning with a # are comments, they won't affect your rebase.

Then you replace pick commands with any in the list above, and you can also remove commits by removing corresponding lines.

For example, if you want to leave the oldest (first) commit alone and combine all the following commits with the second oldest, you should edit the letter next to each commit except the first and the second to say f:

pick a9c8a1d Some refactoring
pick 01b2fd8 New awesome feature
f b729ad5 fixup
f e3851e8 another fix

If you want to combine these commits and rename the commit, you should additionally add an r next to the second commit or simply use s instead of f:

pick a9c8a1d Some refactoring
pick 01b2fd8 New awesome feature
s b729ad5 fixup
s e3851e8 another fix

You can then rename the commit in the next text prompt that pops up.

Newer, awesomer features

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# rebase in progress; onto 8074d12
# You are currently editing a commit while rebasing branch 'main' on '8074d12'.
#
# Changes to be committed:
#   modified:   README.md
#

If everything is successful, you should see something like this:

(main)$ Successfully rebased and updated refs/heads/main.

Safe merging strategy

--no-commit performs the merge but pretends the merge failed and does not autocommit, giving the user a chance to inspect and further tweak the merge result before committing. no-ff maintains evidence that a feature branch once existed, keeping project history consistent.

(main)$ git merge --no-ff --no-commit my-branch

I need to merge a branch into a single commit

(main)$ git merge --squash my-branch

 

I want to combine only unpushed commits

Sometimes you have several work in progress commits that you want to combine before you push them upstream. You don't want to accidentally combine any commits that have already been pushed upstream because someone else may have already made commits that reference them.

(main)$ git rebase -i @{u}

This will do an interactive rebase that lists only the commits that you haven't already pushed, so it will be safe to reorder/fix/squash anything in the list.

I need to abort the merge

Sometimes the merge can produce problems in certain files, in those cases we can use the option abort to abort the current conflict resolution process, and try to reconstruct the pre-merge state.

(my-branch)$ git merge --abort

This command is available since Git version >= 1.7.4

I need to update the parent commit of my branch

Say I have a main branch, a feature-1 branch branched from main, and a feature-2 branch branched off of feature-1. If I make a commit to feature-1, then the parent commit of feature-2 is no longer accurate (it should be the head of feature-1, since we branched off of it). We can fix this with git rebase --onto.

(feature-2)$ git rebase --onto feature-1 <the first commit in your feature-2 branch that you don't want to bring along> feature-2

This helps in sticky scenarios where you might have a feature built on another feature that hasn't been merged yet, and a bugfix on the feature-1 branch needs to be reflected in your feature-2 branch.

Check if all commits on a branch are merged

To check if all commits on a branch are merged into another branch, you should diff between the heads (or any commits) of those branches:

(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll

This will tell you if any commits are in one but not the other, and will give you a list of any nonshared between the branches. Another option is to do this:

(main)$ git log main ^feature/120-on-scroll --no-merges

Possible issues with interactive rebases

 

The rebase editing screen says 'noop'

If you're seeing this:

noop

That means you are trying to rebase against a branch that is at an identical commit, or is ahead of your current branch. You can try:

  • making sure your main branch is where it should be
  • rebase against HEAD~2 or earlier instead

 

There were conflicts

If you are unable to successfully complete the rebase, you may have to resolve conflicts.

First run git status to see which files have conflicts in them:

(my-branch)$ git status
On branch my-branch
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

  both modified:   README.md

In this example, README.md has conflicts. Open that file and look for the following:

   <<<<<<< HEAD
   some code
   =========
   some code
   >>>>>>> new-commit

You will need to resolve the differences between the code that was added in your new commit (in the example, everything from the middle line to new-commit) and your HEAD.

If you want to keep one branch's version of the code, you can use --ours or --theirs:

(main*)$ git checkout --ours README.md
  • When merging, use --ours to keep changes from the local branch, or --theirs to keep changes from the other branch.
  • When rebasing, use --theirs to keep changes from the local branch, or --ours to keep changes from the other branch. For an explanation of this swap, see this note in the Git documentation.

If the merges are more complicated, you can use a visual diff editor:

(main*)$ git mergetool -t opendiff

After you have resolved all conflicts and tested your code, git add the files you have changed, and then continue the rebase with git rebase --continue

(my-branch)$ git add README.md
(my-branch)$ git rebase --continue

If after resolving all the conflicts you end up with an identical tree to what it was before the commit, you need to git rebase --skip instead.

If at any time you want to stop the entire rebase and go back to the original state of your branch, you can do so:

(my-branch)$ git rebase --abort

 

Stash

Stash all edits

To stash all the edits in your working directory

$ git stash

If you also want to stash untracked files, use -u option.

$ git stash -u

Stash specific files

To stash only one file from your working directory

$ git stash push working-directory-path/filename.ext

To stash multiple files from your working directory

$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext

 

Stash with message

$ git stash save <message>

or

$ git stash push -m <message>

 

Apply a specific stash from list

First check your list of stashes with message using

$ git stash list

Then apply a specific stash from the list using

$ git stash apply "stash@{n}"

Here, 'n' indicates the position of the stash in the stack. The topmost stash will be position 0.

Furthermore, using a time-based stash reference is also possible.

$ git stash apply "stash@{2.hours.ago}"

 

Stash while keeping unstaged edits

You can manually create a stash commit, and then use git stash store.

$ git stash create
$ git stash store -m <message> CREATED_SHA1

Finding

I want to find a string in any commit

To find a certain string which was introduced in any commit, you can use the following structure:

$ git log -S "string to find"

Commons parameters:

--source means to show the ref name given on the command line by which each commit was reached.

--all means to start from every branch.

--reverse prints in reverse order, it means that will show the first commit that made the change.

 

I want to find by author/committer

To find all commits by author/committer you can use:

$ git log --author=<name or email>
$ git log --committer=<name or email>

Keep in mind that author and committer are not the same. The --author is the person who originally wrote the code; on the other hand, the --committer, is the person who committed the code on behalf of the original author.

I want to list commits containing specific files

To find all commits containing a specific file you can use:

$ git log -- <path to file>

You would usually specify an exact path, but you may also use wild cards in the path and file name:

$ git log -- **/*.js

While using wildcards, it's useful to inform --name-status to see the list of committed files:

$ git log --name-status -- **/*.js

 

I want to view the commit history for a specific function

To trace the evolution of a single function you can use:

$ git log -L :FunctionName:FilePath

Note that you can combine this with further git log options, like revision ranges and commit limits.

Find a tag where a commit is referenced

To find all tags containing a specific commit:

$ git tag --contains <commitid>

Submodules

 

Clone all submodules

$ git clone --recursive git://github.com/foo/bar.git

If already cloned:

$ git submodule update --init --recursive

 

Remove a submodule

Creating a submodule is pretty straight-forward, but deleting them less so. The commands you need are:

$ git submodule deinit submodulename
$ git rm submodulename
$ git rm --cached submodulename
$ rm -rf .git/modules/submodulename

Miscellaneous Objects

Copy a folder or file from one branch to another

$ git checkout <branch-you-want-the-directory-from> -- <folder-name or file-name>

Restore a deleted file

First find the commit when the file last existed:

$ git rev-list -n 1 HEAD -- filename

Then checkout that file:

git checkout deletingcommitid^ -- filename

Delete tag

$ git tag -d <tag_name>
$ git push <remote> :refs/tags/<tag_name>

 

Recover a deleted tag

If you want to recover a tag that was already deleted, you can do so by following these steps: First, you need to find the unreachable tag:

$ git fsck --unreachable | grep tag

Make a note of the tag's hash. Then, restore the deleted tag with following, making use of git update-ref:

$ git update-ref refs/tags/<tag_name> <hash>

Your tag should now have been restored.

Deleted Patch

If someone has sent you a pull request on GitHub, but then deleted their original fork, you will be unable to clone their repository or to use git am as the .diff, .patch URLs become unavailable. But you can checkout the PR itself using GitHub's special refs. To fetch the content of PR#1 into a new branch called pr_1:

$ git fetch origin refs/pull/1/head:pr_1
From github.com:foo/bar
 * [new ref]         refs/pull/1/head -> pr_1

Exporting a repository as a Zip file

$ git archive --format zip --output /full/path/to/zipfile.zip main

Push a branch and a tag that have the same name

If there is a tag on a remote repository that has the same name as a branch you will get the following error when trying to push that branch with a standard $ git push <remote> <branch> command.

$ git push origin <branch>
error: dst refspec same matches more than one.
error: failed to push some refs to '<git server>'

Fix this by specifying you want to push the head reference.

$ git push origin refs/heads/<branch-name>

If you want to push a tag to a remote repository that has the same name as a branch, you can use a similar command.

$ git push origin refs/tags/<tag-name>

Tracking Files

 

I want to change a file name's capitalization, without changing the contents of the file

(main)$ git mv --force myfile MyFile

I want to overwrite local files when doing a git pull

(main)$ git fetch --all
(main)$ git reset --hard origin/main

 

I want to remove a file from Git but keep the file

(main)$ git rm --cached log.txt

I want to revert a file to a specific revision

Assuming the hash of the commit you want is c5f567:

(main)$ git checkout c5f567 -- file1/to/restore file2/to/restore

If you want to revert to changes made just 1 commit before c5f567, pass the commit hash as c5f567~1:

(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore

I want to list changes of a specific file between commits or branches

Assuming you want to compare last commit with file from commit c5f567:

$ git diff HEAD:path_to_file/file c5f567:path_to_file/file

Same goes for branches:

$ git diff main:path_to_file/file staging:path_to_file/file

I want Git to ignore changes to a specific file

This works great for config templates or other files that require locally adding credentials that shouldn't be committed.

$ git update-index --assume-unchanged file-to-ignore

Note that this does not remove the file from source control - it is only ignored locally. To undo this and tell Git to notice changes again, this clears the ignore flag:

$ git update-index --no-assume-unchanged file-to-stop-ignoring

Debugging with Git

The git-bisect command uses a binary search to find which commit in your Git history introduced a bug.

Suppose you're on the main branch, and you want to find the commit that broke some feature. You start bisect:

$ git bisect start

Then you should specify which commit is bad, and which one is known to be good. Assuming that your current version is bad, and v1.1.1 is good:

$ git bisect bad
$ git bisect good v1.1.1

Now git-bisect selects a commit in the middle of the range that you specified, checks it out, and asks you whether it's good or bad. You should see something like:

$ Bisecting: 5 revision left to test after this (roughly 5 step)
$ [c44abbbee29cb93d8499283101fe7c8d9d97f0fe] Commit message
$ (c44abbb)$

You will now check if this commit is good or bad. If it's good:

$ (c44abbb)$ git bisect good

and git-bisect will select another commit from the range for you. This process (selecting good or bad) will repeat until there are no more revisions left to inspect, and the command will finally print a description of the first bad commit.

Configuration

I want to add aliases for some Git commands

On OS X and Linux, your git configuration file is stored in ~/.gitconfig. I've added some example aliases I use as shortcuts (and some of my common typos) in the [alias] section as shown below:

[alias]
    a = add
    amend = commit --amend
    c = commit
    ca = commit --amend
    ci = commit -a
    co = checkout
    d = diff
    dc = diff --changed
    ds = diff --staged
    extend = commit --amend -C HEAD
    f = fetch
    loll = log --graph --decorate --pretty=oneline --abbrev-commit
    m = merge
    one = log --pretty=oneline
    outstanding = rebase -i @{u}
    reword = commit --amend --only
    s = status
    unpushed = log @{u}
    wc = whatchanged
    wip = rebase -i @{u}
    zap = fetch -p
    day = log --reverse --no-merges --branches=* --date=local --since=midnight --author=\"$(git config --get user.name)\"
    delete-merged-branches = "!f() { git checkout --quiet main && git branch --merged | grep --invert-match '\\*' | xargs -n 1 git branch --delete; git checkout --quiet @{-1}; }; f"

I want to add an empty directory to my repository

You can’t! Git doesn’t support this, but there’s a hack. You can create a .gitignore file in the directory with the following contents:

 # Ignore everything in this directory
 *
 # Except this file
 !.gitignore

Another common convention is to make an empty file in the folder, titled .gitkeep.

$ mkdir mydir
$ touch mydir/.gitkeep

You can also name the file as just .keep , in which case the second line above would be touch mydir/.keep

I want to cache a username and password for a repository

You might have a repository that requires authentication. In which case you can cache a username and password so you don't have to enter it on every push and pull. Credential helper can do this for you.

$ git config --global credential.helper cache
# Set git to use the credential memory cache
$ git config --global credential.helper 'cache --timeout=3600'
# Set the cache to timeout after 1 hour (setting is in seconds)

To find a credential helper:

$ git help -a | grep credential
# Shows you possible credential helpers

For OS specific credential caching:

$ git config --global credential.helper osxkeychain
# For OSX
$ git config --global credential.helper manager
# Git for Windows 2.7.3+
$ git config --global credential.helper gnome-keyring
# Ubuntu and other GNOME-based distros

More credential helpers can likely be found for different distributions and operating systems.

I want to make Git ignore permissions and filemode changes

$ git config core.fileMode false

If you want to make this the default behaviour for logged-in users, then use:

$ git config --global core.fileMode false

I want to set a global user

To configure user information used across all local repositories, and to set a name that is identifiable for credit when review version history:

$ git config --global user.name “[firstname lastname]”

To set an email address that will be associated with each history marker:

git config --global user.email “[valid-email]”

I've no idea what I did wrong

So, you're screwed - you reset something, or you merged the wrong branch, or you force pushed and now you can't find your commits. You know, at some point, you were doing alright, and you want to go back to some state you were at.

This is what git reflog is for. reflog keeps track of any changes to the tip of a branch, even if that tip isn't referenced by a branch or a tag. Basically, every time HEAD changes, a new entry is added to the reflog. This only works for local repositories, sadly, and it only tracks movements (not changes to a file that weren't recorded anywhere, for instance).

(main)$ git reflog
0a2e358 HEAD@{0}: reset: moving to HEAD~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to main
c10f740 HEAD@{2}: checkout: moving from main to 2.2

The reflog above shows a checkout from main to the 2.2 branch and back. From there, there's a hard reset to an older commit. The latest activity is represented at the top labeled HEAD@{0}.

If it turns out that you accidentally moved back, the reflog will contain the commit main pointed to (0254ea7) before you accidentally dropped 2 commits.

$ git reset --hard 0254ea7

Using git reset it is then possible to change main back to the commit it was before. This provides a safety net in case history was accidentally changed.

(copied and edited from Source).

Git Shortcuts

Git Bash

Once you're comfortable with what the above commands are doing, you might want to create some shortcuts for Git Bash. This allows you to work a lot faster by doing complex tasks in really short commands.

alias sq=squash

function squash() {
    git rebase -i HEAD~$1
}

Copy those commands to your .bashrc or .bash_profile.

PowerShell on Windows

If you are using PowerShell on Windows, you can also set up aliases and functions. Add these commands to your profile, whose path is defined in the $profile variable. Learn more at the About Profiles page on the Microsoft documentation site.

Set-Alias sq Squash-Commits

function Squash-Commits {
  git rebase -i HEAD~$1
}

Other Resources

Books

Tutorials

Scripts and Tools

  • firstaidgit.io A searchable selection of the most frequently asked Git questions
  • git-extra-commands - a collection of useful extra Git scripts
  • git-extras - GIT utilities -- repo summary, repl, changelog population, author commit percentages and more
  • git-fire - git-fire is a Git plugin that helps in the event of an emergency by adding all current files, committing, and pushing to a new branch (to prevent merge conflicts).
  • git-tips - Small Git tips
  • git-town - Generic, high-level Git workflow support! http://www.git-town.com

GUI Clients

  • GitKraken - The downright luxurious Git client,for Windows, Mac & Linux
  • git-cola - another Git client for Windows and OS X
  • GitUp - A newish GUI that has some very opinionated ways of dealing with Git's complications
  • gitx-dev - another graphical Git client for OS X
  • Sourcetree - Simplicity meets power in a beautiful and free Git GUI. For Windows and Mac.
  • Tower - graphical Git client for OS X (paid)
  • tig - terminal text-mode interface for Git
  • Magit - Interface to Git implemented as an Emacs package.
  • GitExtensions - a shell extension, a Visual Studio 2010-2015 plugin and a standalone Git repository tool.
  • Fork - a fast and friendly Git client for Mac (beta)
  • gmaster - a Git client for Windows that has 3-way merge, analyze refactors, semantic diff and merge (beta)
  • gitk - a Git client for linux to allow simple view of repo state.
  • SublimeMerge - Blazing fast, extensible client that provides 3-way merges, powerful search and syntax highlighting, in active development.

🌍 EnglishEspañolРусский简体中文한국어Tiếng ViệtFrançais日本語

Author: K88hudson
Source Code: https://github.com/k88hudson/git-flight-rules 
License: CC-BY-SA-4.0 License

#git #guide 

Flight Rules for Git: Guide About What to Do When Things Go Wrong
Dipesh Malvia

Dipesh Malvia

1646916046

React Interview Preparation Guide | What and How to Learn for UI and React Jobs.

React Interview Preparation Guide | What and How to Learn for UI and React Jobs.

In this video I am going to discuss how to prepare for interviews if you are looking for UI development or React developer roles. I will talk about the topics, how to plan your training and links from where you can learn. 

🔥 Video contents... ENJOY 👇 

  • 0:00:00 - Intro 
  • 0:03:07 - UI Basics 
  • 0:06:07 - React Fundamentals 
  • 0:10:07 - Essential React Hooks 
  • 0:11:15 - State Management & Redux 
  • 0:13:25 - React Performance 
  • 0:16:36 - React TypeScript 
  • 0:18:06 - React Debugging 
  • 0:20:20 - Outro 

⭐️ Support my channel⭐️

https://www.buymeacoffee.com/dipeshmalvia

⭐️ Links⭐️ 

  • https://developer.mozilla.org/en-US/ 
  • https://reactjs.org/ 
  • https://blog.logrocket.com/windowing-wars-react-virtualized-vs-react-window/ 
  • https://www.typescriptlang.org/docs/handbook/react.html 

⭐️ React Roadmap for Developers in 2021⭐️ 

🔗 Social Medias 🔗 

⭐️ Tags ⭐️ 

  • - React Interview Preparation Guide - React Fundamentals Topics - Redux State Management Interview Topics - React TypeScript Tutorials - React Debugging Guide 

⭐️ Hashtags ⭐️ 

#react #redux #Interview #guide 

Disclaimer: It doesn't feel good to have a disclaimer in every video but this is how the world is right now. All videos are for educational purpose and use them wisely. Any video may have a slight mistake, please take decisions based on your research. This video is not forcing anything on you.

 

https://youtu.be/3HjP-IZ01bY

React Interview Preparation Guide | What and How to Learn for UI and React Jobs.
Royce  Reinger

Royce Reinger

1645525620

The Strictest and Most Opinionated Python Linter Ever!

wemake-python-styleguide


Welcome to the strictest and most opinionated Python linter ever.

wemake-python-styleguide logo 

wemake-python-styleguide is actually a flake8 plugin with some other plugins as dependencies.

Quickstart

pip install wemake-python-styleguide

You will also need to create a setup.cfg file with the configuration.

We highly recommend to also use:

  • flakehell for easy integration into a legacy codebase
  • nitpick for sharing and validating configuration across multiple projects

Running

flake8 your_module.py

This app is still just good old flake8! And it won't change your existing workflow.

invocation results

See "Usage" section in the docs for examples and integrations.

We also support GitHub Actions as first class-citizens. Try it out!

Strict is the new cool

Strict linting offers the following benefits to developers and companies:

  1. Ensures consistency - no matter who works on it, the end product will always be the same dependable code
  2. Helps avoid potential bugs - strict rules make sure that you don't make common mistakes
  3. Efficient code reviews - each piece of code has a similar familiar style and syntax. If it passes all the checks, there's little left to review!
  4. Fewer code revisions - strict linting ensures that you don't have to re-write the codebase again and again
  5. Reduce code redundancy - Sometimes we write complex code as we are thinking in a certain way about a problem. The linter offers suggestions that can help simplify the code and eliminate redundant statements

What we are about

The ultimate goal of this project is to make all people write exactly the same Python code.

 flake8pylintblackmypywemake-python-styleguide
Formats code?
Finds style issues?🤔🤔
Finds bugs?🤔
Finds complex code?🤔
Has a lot of strict rules?🤔
Has a lot of plugins?🤔

We have several primary objectives:

  1. Enforce python3.6+ usage
  2. Significantly reduce the complexity of your code and make it more maintainable
  3. Enforce "There should be one -- and preferably only one -- obvious way to do it" rule to coding and naming styles
  4. Protect developers from possible errors and enforce best practices

You can find all error codes and plugins in the docs.

What we are not

We are not planning to do the following things:

  1. Assume or check types, use mypy together with our linter
  2. Reformat code, since we believe that developers should do that
  3. Check for SyntaxError or logical bugs, write tests instead
  4. Appeal to everyone. But, you can switch off any rules that you don't like

Supporting us :tada:

We in wemake.services make all our tools open-source by default, so the community can benefit from them. If you use our tools and they make your life easier and brings business value, you can return us a favor by supporting the work we do.

Gold Tier

Show your style :sunglasses:

If you use our linter - it means that your code is awesome. You can be proud of it! And you should share your accomplishment with others by including a badge in your README file. It looks like this:

wemake-python-styleguide

Markdown

[![wemake-python-styleguide](https://img.shields.io/badge/style-wemake-000000.svg)](https://github.com/wemake-services/wemake-python-styleguide)

Restructured text

.. image:: https://img.shields.io/badge/style-wemake-000000.svg
   :target: https://github.com/wemake-services/wemake-python-styleguide

Author: Wemake-services
Source Code: https://github.com/wemake-services/wemake-python-styleguide 
License: MIT License

#python #guide 

The Strictest and Most Opinionated Python Linter Ever!

The Business Side Of iOS Mobile App Development

We are happy to present our newest guide! This time we've focused on the iOS development.

What will you learn from this guide?

More than enough to get started building your mobile product for iOS. Here are some of the most crucial details in this guide:

 

Interesded? Get access to the full guide here.

#ios #mobile-apps #guide 

Rupert  Beatty

Rupert Beatty

1638272940

How to Use the MongoDB Shell or Compass query with a GUID

Just a small one for today. Have you ever tried to query MongoDB with a GUID? Well I did and it can be confusing!

Problem

Some time ago I created a project for storing product prices but for multiple markets around the world. Markets would be a dynamic thing, meaning different ones being added every once and a while, and old ones potentially removed. Since the data to be stored were fairly simple, I was lead to a design featuring one documentDB per market. The document-oriented database selected was MongoDB, but I always had in mind a future move to Azure Cosmos DB, so avoiding vendor lock was a requirement. 

#mongodb #guide #blazor 

How to Use the MongoDB Shell or Compass query with a GUID