· 4 years ago · Apr 21, 2021, 02:06 PM
1
2© Andrew Beak 2017
3Andrew BeakPHP 7 Zend Certification Study Guidehttps://doi.org/10.1007/978-1-4842-3246-0_1
41. PHP Basics
5Andrew Beak1
6(1)
7Grafham, Cambridgeshire, UK
8
9Introduction
10This chapter focuses on the nitty gritty details of PHP as a language. This is a big chapter and it covers one of the most important aspects of the exam. The best advice that I can give is not to skim over it. There are a lot of places where PHP has some peculiarities and even with a few years of experience you might not have encountered them all.
11Basic Language Features
12All statements in PHP must be terminated with a semicolon. An exception to this is if the statement happens to be the last statement before a closing tag.
13Whitespace has no semantic meaning in PHP. There is no need to line code up, but most coding standards enforce this to improve code readability. Whitespace may not appear in the middle of function names, variable names, or keywords.
14Multiple statements are allowed on a single line.
15Code blocks are denoted by the brace symbols { }.
16PHP language construct and function names are not case-sensitive, but variable and constant names are.
17<?php
18ECHO 'Hello World'; // works
19$variable = 'Hello World';
20echo $VARIABLE; // won't work
21Inserting PHP into Web Pages
22Although PHP is a general scripting language and can be used for other purposes, it is most commonly deployed as a server-side scripting language used for building web pages.
23The PHP parser does not parse anything that is not included in the tags that indicate PHP script. Content outside of PHP tags is simply output without inspection. This allows PHP to be embedded in HTML.
24There are several ways to delimit PHP script, but only the first two in this table are commonly used:
25Type
26
27Open
28
29Close
30
31Note
32Standard
33
34<?php
35
36?>
37
38Echo
39
40<?=
41
42?>
43
44Short
45
46<?
47
48?>
49
50Deprecated
51Script
52
53<script language='php'>
54
55</script>
56
57Do not use
58ASP
59
60<%
61
62%>
63
64Deprecated
65The echo tag allows you to easily echo a PHP variable and the shortened tag makes your HTML document easier to read. It is commonly used in templates where you want to output several values into various positions on a page. Using the short syntax keeps your template code much neater.
66Its usage is easiest to understand when it’s shown along with the equivalent in standard opening codes. The following two tags are identical:
67<?= $variable ?>
68<?php echo $variable ?>
69Note
70The echo statement is the last statement before a closing tag and so it does not need a semicolon to terminate it.
71You can use PHP logic between opening and closing tags, as in this example:
72Balance:
73<?php
74if ($bankBalance > 0): ?>
75<p class='black'>
76<?php else: ?>
77<p class='red'>
78<?php endif; ?>
79<?= $bankBalance?>
80</p>
81Let’s step through the code:
82
83 1.
84 The PHP parser will output Balance: without evaluating it because it is not in the PHP tags.
85
86 2.
87 The PHP tag then checks if the balance is greater than zero and terminates. The <p class='black'> tag is only output if that condition is true; otherwise, the <p class='red'> tag is output.
88
89 3.
90 We use the echo tag syntax to output the $bankBalance variable.
91
92 4.
93 Finally, the closing paragraph tag is output without being parsed because the PHP script has been closed.
94
95
96Note
97This approach will also work using the curly brace syntax of an if statement.
98It is quite common in PHP programs to omit the closing tag ?> in a file. This is acceptable to the parser and is a useful way to prevent problems with newline characters appearing after the closing tag.
99These newline characters are sent as output by the PHP interpreter and could interfere with the HTTP headers or cause other unintended side-effects. By not closing the script in a PHP file, you prevent the chance of newline characters being sent.
100Tip
101It is a common coding standard to require that the closing tag is omitted in included files, but this is not a PHP requirement.
102Language Constructs
103Language constructs are different from functions in that they are baked right into the language.
104Language constructs can be understood directly by the parser and do not need to be broken down. Functions, on the other hand, are mapped and simplified to a set of language constructs before they are parsed.
105Language constructs are not functions, and so cannot be used as a callback function. They follow rules that are different from functions when it comes to parameters and the use of parentheses.
106For example, echo doesn’t always need parentheses when you call it and, if you call it with more than one argument, then you can’t use parentheses.
107<?php
108// one parameter, no brackets
109echo 'hello\r\n';
110// two parameters, brackets (syntax error)
111//echo('hello', 'world');
112// two parameters, no brackets
113echo 'hello', 'world';
114Furthermore, echo does not return a value, whereas every function will always return a value (or null).
115The PHP Manual page on reserved keywords1 has a complete list, but here are some of the constructs that you should be familiar with:
116Construct
117
118Used For
119assert
120
121Debug command to test a condition and do something if it is not true.
122echo
123
124Outputting a value to stdout.
125print
126
127Outputting a value to stdout.
128exit
129
130Optionally outputting a message and terminating the program.
131die
132
133This is an alias for exit.
134return
135
136Terminates a function and returns control to the calling scope, or if called in the global scope, terminates the program.
137include
138
139Includes a file and evaluates it. PHP will issue a warning if the file is not found or cannot be read.
140include_once
141
142If you specify include_once then PHP will make sure that it includes the file only once.
143require
144
145PHP will include a file and evaluate it. If the file is not found or cannot be read, then a fatal error will be generated.
146require_once
147
148As for include_once, but a fatal error will be generated instead of a warning.
149eval
150
151The argument is evaluated as PHP and affects the calling scope.
152empty
153
154Returns a Boolean value depending on whether the variable is empty or not. Empty variables include null variables, empty strings, arrays with no elements, numeric values of 0, a string value of 0, and Boolean values of false.
155isset
156
157Returns true if the variable has been set and false otherwise.
158unset
159
160Clears a variable.
161list
162
163Assigns multiple variables at one time from an array.
164One possible tricky exam question that might come up is in understanding the small difference between print and echo. The echo construct does not return a value, not even null, and so is not suitable for use inside an expression. The print construct will however return a value.
165The reason not to use include_once() and require_once() all the time is a performance issue. PHP tracks a list of files that has been included to support the functionality of these functions. This requires memory so these functions are rather used when they are necessary and not in favor of include or require.
166Comments
167There are three styles to mark comments:
168<?php
169# Perl style comments
170// C style comments
171/*
172 Multiline comment
173*/
174API documentation can additionally conform to external standards such as those used by the PHPDocumentor project.2 This tool examines your API style comments and automatically creates documentation for you.
175API documentation looks very similar to multiline comments:
176<?php
177/**
178 API documentation has two asterisks, this is not a PHP
179 syntax distinction, but is just a convention.
180*/
181Representing Numbers
182There are four ways in which an integer may be expressed in a PHP script:
183Notation
184
185Example
186
187Note
188Decimal
189
1901234
191
192Binary
193
1940b10011010010
195
196Identified by leading 0b or 0B
197Octal
198
19902322
200
201Identified by leading 0
202Hexadecimal
203
2040x4D2
205
206Identified by leading 0x or 0X
207Floating point numbers (called doubles in some other languages) can be expressed either in standard decimal format or in exponential format.
208Form
209
210Example
211Decimal
212
213123.456
214Exponential
215
2160.123456e3 or 0.123456E3
217Note
218The letter “e” in the exponential form is case-insensitive, as are the other letters used in the integer formats.
219Variables
220In this section, I’m going to be focusing on how PHP handles variables. I’m assuming that you’ve had enough experience with PHP that I don’t need to explain what variables are or how to use them. We’ll be looking at the various types of variables PHP offers, how to change the type of a variable, and how to check if a variable is set or not.
221Variable Types
222PHP is a loosely typed language. It is important not to think that PHP variables don’t have a type. They most definitely do, it’s just that they may change type during runtime and don’t need their type to be declared explicitly when initialized.
223PHP will implicitly cast the variable to the data type required for an operation. For example, if an operation requires a number, such as the addition (+) operation, then PHP will convert the operands into a numeric format.
224You’ll be introduced to type juggling in the “Casting Variables” section and you’ll need to know the rules PHP follows when changing a variable type. For now, you just need to know that PHP variables have a type, that type can change, and although you can explicitly change the type PHP does this implicitly for you.
225PHP has three categories of variable—scalars, composite, and resources. A scalar variable is one that can only hold one value at a time. Composite variables can contain several values at a time.
226A resource variable points to something not native to PHP like a handle provided by the OS to a file or a database connection. These variables cannot be cast.
227Finally, PHP has the null type, which is used for variables that have not had a value set to them. You can also assign the null value to a variable, but you cannot cast to a null type in PHP 7.1.
228Scalar Types
229There are four scalar types:
230Type
231
232Alias
233
234Contains
235Boolean
236
237bool
238
239True or False
240Integer
241
242int
243
244A signed numeric integer
245Float
246
247A signed numeric double or float data
248String
249
250An ordered collection of binary data
251Some types have aliases. For example, consider this code that shows that bool is an alias for boolean:
252<?php
253$a = (boolean)true;
254$b = (bool)true;
255var_dump($a === $b); // bool(true)
256Strings in PHP are not simply a list of characters. Internally PHP strings contain information about their length and are not null terminated. This means that they may contain binary information such as an image file that has been read from disk. In other words, PHP strings are binary safe.
257Composite Types
258There are two composite types: arrays and objects. Each of these has its own section in this book.
259Casting Variables
260This is a very important section of understanding PHP and even very experienced developers may not be aware of some of the rules that PHP uses to cast variables.
261PHP implicitly casts variables to the type required to perform an operation.
262It is also possible to explicitly cast variables using one of two options:
263
264 Use a casting operator
265 Use a PHP function
266
267Casting operators are used by putting the name of the data type you want to cast into brackets before the variable name. For example:
268<?php
269$a = '123'; // $a is a string
270$a = (int)$a; // $a is now an integer
271$a = (bool)$a; // $a is now Boolean and is true
272You can cast a variable to null, as in the following example, but this behavior is deprecated in PHP 7.2 so you shouldn’t do it even though PHP 7.1 supports it.
273<?php
274$a = 'Hello World';
275$a = (unset)$a; // Deprecated in PHP 7.2
276var_dump($a); // NULL
277There are also PHP functions that will convert a variable to a data type. These are named in a way that is self-documenting: floatval, intval, strval, and boolval.
278Additionally, the intdiv function will potentially cast a double to an integer when it returns the integer result of dividing two integers.
279You can also call the settype function on a variable that takes the desired data type as a second argument.
280There are some rules that need to be remembered regarding how variables are cast in PHP. You should read the manual page on type juggling3 carefully, because there are many trips and traps in type juggling. Also make sure that you read the pages linked to from the type juggling page.
281Instead of exhaustively listing the rules, I’ll focus on some of the rules that may be counter-intuitive or are commonly mistaken.
282Casting from float to integer does not round the value up or down, but rather truncates the decimal portion.
283<?php
284$a = 1234.56;
285echo (int)$a; // 1234 (not 1235)
286$a = -1234.56
287echo (int)$a; // -1234
288Some general rules for casting to Boolean are that:
289
290 Empty arrays and strings are cast to false.
291 Strings always evaluate to Boolean true unless they have a value that’s considered “empty” by PHP.
292 Strings containing numbers evaluate to true if the number is not zero. Recall that such strings return false when the empty() function is called on them.
293 Any integer (or float) that is non-zero is true, so negative numbers are true.
294
295Objects can have the magic method __toString() defined on them. This can be overloaded if you want to have a custom way to cast your object to string. We look at this in the section on “Casting Objects to String”.
296Converting a string to a number results in 0 unless the string begins with valid numeric data (see the PHP Manual4 for more detail). By default, the variable type of the cast number will be integer, unless an exponent or decimal point is encountered, in which case it will be a float.
297Here is an example script that shows some string conversions:
298<?php
299$examples = [
300 '12 o clock',
301 'Half past 12',
302 '12.30',
303 '7.2e2 minutes after midnight'
304];
305foreach ($examples as $example) {
306 $result = 0 + $example;
307 var_dump($result);
308}
309/*
310This outputs:
311 int(12)
312 int(0)
313 double(12.3)
314 double(720)
315*/
316Floats and Integers
317Be very careful when casting between floats and integers. The PHP Manual5 has a very good example of how internal implementation details of numeric types can have counter-intuitive results:
318<?php
319echo (int) ( (0.1+0.7) * 10 ); // 7
320echo (int) ( (0.1+0.5) * 10); // 6
321One would expect the first example to display 8, but in fact the internal floating-point representation is just slightly less than 8.
322When PHP converts a floating point number to integer it rounds toward zero, so it becomes 7.
323The reason behind this is that some numbers are rational in base 10 but are irrational in base 2. Although 0.7 can be expressed as a rational number in base 10, when expressed in base 2 it is irrational. Because there are a limited number of bits available to store the number, it is inevitable that some loss of precision will occur.
324PHP integers are always signed. The range of values that an integer can take will depend on the system PHP is running on.
325You can determine the size of an integer in bytes at runtime by querying the constant PHP_INT_SIZE. The constants PHP_INT_MAX and PHP_INT_MIN will give you the maximum and minimum values that can be stored in an integer, respectively. There are similar constants for other numeric types. They are listed in the PHP Manual page on reserved constants.6
326Caution
327You should not rely on floats precision up to the last digit.
328You should avoid testing floats directly for equality and rather test if they are the same up to a given degree of precision, as in this example:
329<?php
330$pi = 3.14159625;
331$indiana = 3.2;
332$epsilon = 0.00001; // degree of error
333if(abs($pi - $indiana) < $epsilon) {
334 echo 'Those values look the same to me';
335} else {
336 echo 'Those values are different';
337}
338This code is checking if the values are the same to five degrees of precision. This script will output Those values are different because the difference is greater than the degree of error that we defined.
339Naming Variables
340PHP variables begin with the dollar symbol $ and PHP variable names adhere to the following rules:
341
342 Names are case sensitive
343 Names may contain letters, numbers, and the underscore character
344 Names may not begin with a number
345
346Coding conventions differ on the use of camelCase, StudlyCase, or snake_case, but all of these formats are valid PHP variable name formats.
347PHP also allows for variable variable names. This is best illustrated by example:
348<?php
349$a = 'foo';
350$$a = 'bar'; // $a is 'foo', so variable $foo is set
351echo $foo; // bar
352PHP 7 will always evaluate access strictly left to right. Older versions had a complicated set of rules to determine how it would evaluate this sort of syntax. Happily, PHP 7 is simpler and consistent and I won’t worry about explaining older versions.
353Here is a more complicated example that illustrates how PHP evaluates from left to right:
354<?php
355$a = 'foo';
356$$a['bar'] = 'Murky code';
357// this assert passes
358assert($$a['bar'] === $foo['bar']);
359var_dump($foo);
360/*
361 array(1) {
362 ['bar']=>
363 array(1) {
364 ['baz']=>
365 string(10) 'Murky code'
366 }
367 }
368*/
369There are several caveats to using variable variable names. They could impact on your code security and can also make your code a little murky to read.
370Checking If a Variable Has Been Set
371The command isset() will return true if a variable has been set and false otherwise. It is preferable to use this function instead of checking if the variable is null because it won’t cause PHP to generate a warning.
372The command empty() will return true if a variable is not set and will not generate a warning. This is not a bulletproof way to test if a variable is set.
373Note
374Remember that the string “0” is considered empty, but is actually set.
375Variables become unset when they become out of scope and you can use the command unset() to manually clear a variable. We’ll see later in the book that the garbage collector is responsible for freeing up the memory allocated to variables that have been unset.
376Constants
377Constants7 are similar to variables but are immutable. They have the same naming rules as variables, but by convention will have uppercase names.
378They can be defined using the define 8 function as shown:
379<?php
380define('PI', 3.142);
381echo PI;
382define('UNITS', ['MILES_CONVERSION' => 1.6, 'INCHES_CONVERSION' => '2.54']);
383echo '5km in miles is ' . 5 * UNITS['MILES_CONVERSION'];
384/*
385 3.1425km in miles is 8
386*/
387The third parameter of define is optional and indicates whether the constant name is case sensitive or not.
388You can also use the const keyword to define constants. Constants can only contain arrays or scalar values and not resources or objects.
389<?php
390const UNITS = ['MILES_CONVERSION' => 1.6,
391 'INCHES_CONVERSION' => '2.54'];
392echo '5km in miles is ' . 5 * UNITS['MILES_CONVERSION'];
393/*
394 5km in miles is 8
395*/
396Only the const keyword can be used to create a namespaced constant, as in this example where we create constants in the 'Foo' namespace and then try to reference them in the 'Bar' namespace.
397<?php
398namespace Foo;
399const AVOCADO = 6.02214086;
400// using define() will generate a warning
401define(MOLE, 'hill');
402namespace Bar;
403echo \Foo\AVOCADO;
404// referencing the constant we tried to define() results in a fatal error
405echo \Foo\MOLE;
406You cannot assign a variable to a constant.
407You can use static scalar values to define a constant, like this:
408const STORAGE_PATH = __DIR__ . '/storage';
409Note
410Note the use of the “magic” constant __DIR__ that is set by PHP at runtime and contains the path that the script resides in on the file system. These constants are discussed in the section “Magic Constants”.
411The constant() function9 is used to retrieve the value of a constant.
412<?php
413const MILES_CONVERSION = 1.6;
414echo 'There are ' . constant('MILES_CONVERSION') . ' miles in a kilometer';
415/*
416 There are 1.6 miles in a kilometer
417*/
418Superglobals
419PHP has several superglobals10 that are available automatically to the script. Superglobals are available in every scope.
420You can alter the values of superglobals, but it’s generally suggested to rather assign a locally scoped variable to the superglobal and modify that. You need to know what each of the superglobals stores.
421Suberglobal
422
423Stores
424$GLOBALS
425
426An array of variables that exist in the global scope.
427$_SERVER
428
429An array of information about paths, headers, and other information relevant to the server environment.
430$_GET
431
432Variables sent in a GET request.
433$_POST
434
435Variables sent in a POST request.
436$_FILES
437
438An associative array of files that were uploaded as part of a POST request.
439$_COOKIE
440
441An associative array of variables passed to the current script via HTTP cookies.
442$_SESSION
443
444An associative array containing session variables available to the current script.
445$_REQUEST
446
447POST, GET, and COOKIE request variables.
448$_ENV
449
450An associative array of variables passed to the current script via the environment method.
451The $_SERVER superglobal has many keys, and you should be familiar with them. The PHP Manual11 has a list of them and you should make sure that you’ve read the manual page and understood all of the keys.
452Tip
453Note that the $_SERVER['argv'] contains arguments sent to the script, which is distinct from $_ENV. Knowledge of this level of detail is required for the certification exam.
454Magic Constants
455Magic constants are those which PHP provides automatically to every running script. There are quite a lot of reserved constants12 and you will need to know the error constants, as well as the commonly used predefined constants.13
456Constant
457
458Contains
459__LINE__
460
461The current line number of the PHP script being executed
462__FILE__
463
464The fully resolved (including symlinks) name and path of the file being executed
465__CLASS__
466
467The name of the class being executed
468__METHOD__
469
470The name of the class method being executed
471__FUNCTION__
472
473The name of the function being executed
474__TRAIT__
475
476The namespace and name of the trait that the code is running in
477__NAMESPACE__
478
479The current namespace
480Note
481The value of these magic constants changes depending on where you use it.
482Operators
483Arithmetic
484You should recognize the arithmetic functions:
485Operation
486
487Example
488
489Description
490Addition
491
4921 + 2.3
493
494Subtraction
495
4964 – 5
497
498Division
499
5006 / 7
501
502Multiplication
503
5048 * 9
505
506Modulus
507
50810 % 11
509
510Gives the remainder of dividing 10 by 11
511Power
512
51312 ** 13
514
515Raises 12 to the power of 13
516These arithmetic operators take two arguments and so are called binary.
517The unary operators following take only one argument and their placement before or after the variable changes how they work. There are two unary operators in PHP, namely prefix and postfix. They are named for whether the operator appears before or after the variable that it affects.
518
519 If the operator appears before the variable (prefix), then the interpreter will first evaluate it and then return the changed variable.
520 If the operator appears after the variable (postfix), then the interpreter will return the variable as it was before the statement executed and then increment the variable.
521
522Let’s show their effects on a variable $a that we initialize to 1 and then operate on:
523Command
524
525Output
526
527Value of $a Afterwards
528
529Description
530$a = 1;
531
5321
533
534echo $a++;
535
5361
537
5382
539
540Postfix
541echo ++$a;
542
5433
544
5453
546
547Prefix
548echo $a--;
549
5503
551
5522
553
554Postfix
555echo --$a;
556
5571
558
5591
560
561Prefix
562Logic Operators
563PHP uses both symbol and word form logic operators. The symbol form operators are C-based.
564Operator
565
566Example
567
568True When
569and
570
571$a and $b
572
573Both $a and $b evaluate true
574and
575
576$a && $b
577
578or
579
580$a or $b
581
582Either $a or $b evaluate true
583or
584
585$a || $b
586
587xor
588
589$a xor $b
590
591One of (but not both) $a or $b is True
592xor
593
594$a ^ $b
595
596not
597
598!$a
599
600$a is not true (false)
601It is best practice not to mix the word form (e.g., and) and the symbol (e.g., &&) in the same comparison, as the operators have different precedence. It’s safest to stick to using the symbol form exclusively.
602In this example, we see that operator precedence14 results in the variables $truth and $pravda not being the same even though we’re performing the “same” logical operator to derive them.
603This happens because the logical operators and and or have lower priority than the equality operator =.
604<?php
605$a = true;
606$b = false;
607$truth = $a and $b; // true
608$pravda = $a && $b; // false
609assert($truth === $pravda);
610/*
611 Warning: assert(): assert($truth === $pravda) failed
612*/
613Ternary Operator
614PHP implements the ternary operator in the same format as other C-ancestor languages. The general format is as follows:
615condition ? expression1 : expression2;
616If condition is true, then expression1 will be evaluated; otherwise expression2 is evaluated.
617Here is an example that checks the condition of isset($a) and assigns the string value 'true' or 'false' to $b accordingly.
618<?php
619$a = 'foo';
620$b = (isset($a)) ? 'true' : 'false';
621echo $b; // true
622The syntax above is identical to the following if statement:
623<?php
624$a = 'foo';
625if (isset($a)) {
626 $b = 'true';
627} else {
628 $b = 'false';
629}
630echo $b; // true
631If the true value is omitted in the ternary operator, then the statement is evaluated as the expression, as follows:
632<?php
633$a = true;
634$b = $a ?: 'foo';
635echo $b; // 1
636This shortened version of the ternary operator is not suitable for testing if a variable exists, as the interpreter will throw a warning in this case.
637Null Coalescing Operator
638The null coalescing operator is just a special case of the ternary operator. It allows you to neaten up the syntax used when you’re using isset to assign a default value to a variable.
639<?php
640// Long form ternary syntax
641$sortDirection = (isset($_GET['sort_dir'])) ? $_GET['sort_dir'] : 'ASC';
642// Equivalent syntax using the null coalescing operator
643$sortDirection = $_GET['sort_dir'] ?? 'ASC';
644// The null-coalesce operator can be chained
645$sortDirection = $_GET['sort_dir'] ?? $defaultSortDir ?? 'ASC';
646// The Elvis operator raises E_NOTICE if the GET variable is not set
647$sortDirection = $_GET['sort_dir'] ?: 'ASC';
648It is preferable to use the null-coalescing operator over Elvis because the null-coalescing operator doesn’t raise a notice error if the variable is not set.
649Spaceship
650The spaceship operator is used to compare two different values and is particularly useful for writing callbacks for the sorting functions that we’ll be looking at later.
651It returns -1, 0, or 1 when the left operand is respectively less than, equal to, or greater than the right.
652Operation
653
654Value
6551 <=> 0
656
6571
6581 <=> 1
659
6600
6611 <=> 2
662
663-1
664'apples' <=> 'Bananas'
665
6661
667'Apples' <=> 'bananas'
668
669-1
670The spaceship operator uses the standard PHP comparison rules.
671We’ll see why there is this surprising difference in the string comparison in the section on “Strings” later.
672Bitwise
673Bitwise operators work on the bits of integers represented in binary form. Using them on a different variable type will cause PHP to cast the variable to integer before operating on it.
674There are three standard logical bitwise operators:
675Operator
676
677Operation
678
679Description
680&
681
682Bitwise AND
683
684The result will have a bit set if both of the operands bits were set
685|
686
687Bitwise OR
688
689If one or both of the operands have a bit set then the result will have that bit set
690^
691
692Bitwise XOR
693
694If one and only one of the operands (not both) has the bit set then the result will have the bit set.
695The result of a bitwise operator will be the value that has its bits set according to these rules. In other words, the bit in each position of the operands is evaluated against the corresponding bit in the same position of the other operand.
696It’s easier to consider the binary representations of numbers when using these operators. You can calculate the binary representation of the result by comparing bits (from right to left) and then converting to decimal when you’re done.
697Let’s look at 50 & 25 as an example. I’ve put the binary representations in comments in the three rows. You can see that I calculated the binary representation of $c by checking whether the bit in that position is set in $a and in $b. In this case, only one such bit is true in both positions.
698<?php
699$a = 50; // 0b110010
700$b = 25; // 0b011001
701$c = 50 & 25; // 0b010000
702echo $c; // 16
703Here is a tabular format that might make it easier to follow. I’m placing the bits from each number in columns. The row marked “operation” shows the comparison that happens—for every position the bits from the two values have the logical “and” operator applied to them.
704Value/Operator
705
706Bits in Each Position
70750
708
7091
710
7111
712
7130
714
7150
716
7171
718
7190
72025
721
7220
723
7241
725
7261
727
7280
729
7300
731
7321
733Operation
734
7351 and 0
736
7371 and 1
738
7390 and 1
740
7410 and 0
742
7431 and 0
744
7450 and 1
746Result
747
7480
749
7501
751
7520
753
7540
755
7560
757
7580
759When we echo out the result. PHP gives us the integer value and you can quickly confirm that the binary representation you evaluated matches it, because 2 raised to the power of 4 is 16.
760Bit Shifting
761PHP also has operators to shift bits left and right. The effect of these operators is to shift the bit pattern of the value either left or right while inserting bits set to 0 in the newly created empty spaces.
762To understand how these operators work, picture your number represented in binary form and then all the 1s and 0s being stepped to the left or right.
763The following table shows shifting bits, one to the right and one to the left.
764Operation
765
766Operation
767
768Result in Binary
769
770Result in Decimal
77150
772
77300110010
774
77550 >> 1
776
777Shift Right
778
77900011001
780
78125
78250 << 1
783
784Shift Left
785
78601100100
787
788100
789I’ve included enough leading zeroes in the binary forms to make it easier to see the pattern of what’s happening.
790You can see that when we shifted to the right, the right-hand bit was “lost”. When we shift left, we insert new bits that are set to 0 on the right.
791It’s important to be cautious when using bitwise operations to perform calculations, as the integer overflow size may vary between the different environments that PHP is deployed on.
792For example, although a 64-bit system will have the same result for both operations, on a 32-bit integer system they will not:
793<?php
794$x = 1;
795echo $x << 32;
796echo $x * pow(2, 32);
797The first line will echo 0 as shifting left 32 bits will fill the 32-bit integer with 0 bits. The second line will use the maths library and output the correct value of 2 raised to the power of 32.
798Tip
799If you want to experiment with binary operators, you’ll find the base_convert() function extremely useful. For example, to output the binary representation of the decimal number 50, you could echo base_convert(50, 10, 2) . PHP_EOL;.
800Bitwise NOT
801You won’t need to know the details of the mathematics behind this operator, so don’t spend too much time worrying about the details. If you understand the effect it has on the bits, you should be ready to answer questions about it.
802PHP uses the ∼ (tilde) symbol for bitwise NOT. The effect of this operator is to flip the bits in a value—if a bit is set it becomes unset, and if it were not set it becomes set.
803This is best understood by example:
804
805Bits
80650
807
8081
809
8101
811
8120
813
8140
815
8161
817
8180
819∼ (NOT)
820
8210
822
8230
824
8251
826
8271
828
8290
830
8311
832The value (in decimal) of the result is -51.
833Just for enrichment purposes, you could read up on Wikipedia about two’s complement.15 It is chiefly used to get to a binary representation of a negative number.
834Assignment Operators
835PHP uses the = symbol as an assignment operator. The following line sets the value of $a to 123.
836<?php
837$a = 123;
838The assignment operator can be combined with just about all the binary and arithmetic operators. This syntax serves as a shortcut that is best shown by providing an example of equivalent statements:
839<?php
840$a += 345; // equivalent to $a = $a + 345;
841$a .= 'foo'; // equivalent to $a = $a . 'foo';
842The result of any assignment expression is the value of the variable following the assignment.
843A fairly common typing error is to mistakenly forget the second = symbol in an equality check. Consider the following example where we’re using the assignment operator in the if statement where we intended to use the equality operator.
844<?php
845$foo = 'hello';
846if ($foo = 'world') {
847 echo 'matches';
848} else {
849 echo 'does not match';
850}
851Had this been an equality operator, the if statement would be false and the script would output “does not match”. However, because we’re assigning the string “world” to the variable $foo, the result is the value “world”, which when cast to Boolean is true (see “Casting Variables”).
852Some coding conventions use what is called the “Yoda Condition” to assist with this error. It uses the fact that PHP will not let you change the value of a constant. If you always place the constant on the left of an equality comparison, you’ll be warned if you mistype the operator. Whether the cost of code readability is worth it is a matter of personal style.
853Reference Operator
854By default, PHP assigns all scalar variables by value.
855PHP has optimizations to make assignment by value faster than assigning by reference (see the section on “Memory Management”), but if you want to assign by reference, you can use the & operator as follows:
856<?php
857$a = 1;
858$b = &$a; // assign by reference
859$b += 5;
860echo $a; // 6
861PHP always assigns objects by reference; if you try to explicitly create it by reference, PHP will generate a parse error.
862<?php
863class MyClass {}
864// Parse error: syntax error, unexpected 'new'
865$a = &new MyClass;
866Comparison Operators
867PHP uses the following comparison operators:
868Operator
869
870Description
871>
872
873Greater than
874>=
875
876Greater than or equal to
877<
878
879Less than
880<=
881
882Less than or equal to
883<>
884
885Not equal
886==
887
888Equivalence; values are equivalent if cast to the same variable type
889===
890
891Identity; values must be of the same data type and have the same value
892!=
893
894Not equivalent
895!==
896
897Not identical
898It is important to understand the difference between an equivalent comparison and an identity comparison:
899
900 Operands are equivalent if they can be cast to a common data type and have the same value.
901 Operands are identical if they share the same data type and have the same value.
902
903Arrays are equivalent if they have the same key and value pairs. They are identical if they have the same key and value pairs, in the same order, and the key-value are of the same type.
904When using comparison operators on arrays, the count of their keys is used to determine which is greater or lesser.
905When compared to a scalar variable, both an object and an array will be considered greater than the scalar.
906<?php
907$a = [1];
908$b = 100;
909echo $a <=> $b; // 1
910Be careful when using comparison operators on strings, or when using them on mismatching variable types. See the section on “Casting Variables” for more information.
911Two More Operators
912PHP provides an operator to suppress error messages . This will work only if the library that the function is based on uses PHP standard error reporting.
913<?php
914// Error messages will be suppressed
915$dbConnection = @mysqli_connect(...);
916It’s bad practice to suppress PHP errors with the @ operator. It is better to use PHP settings to suppress errors in your production environment and to allow your development environment to display errors. Having code that fails silently without producing an error makes debugging much more difficult than it needs to be.
917The last operator we will discuss is the backtick operator. It is not commonly used and is equivalent to calling the shell_exec() command. In the following example, the variable $a will contain the name of the user running the PHP interpreter.
918<?php
919// This is the equivalent of echo shell_exec('whoami');
920echo `whoami`;
921In a web environment this will probably be www-data. This is the default for Nginx and Apache, but from the command line will be the name of the user who is logged in.
922Control Structures
923Control structures allow you to analyze variables and then choose a direction for your program to flow in. In this section, we’re going to be looking at several different sorts of control structures and how they’re implemented in PHP.
924Conditional Structures
925PHP supports if, else, elseif, switch, and ternary conditional structures.
926If structures look like this:
927<?php
928if (condition) {
929 // statements to execute
930} elseif (second condition) {
931 // statements to execute
932} else {
933 // statements to execute
934}
935Note that the space between else and if in the elseif is optional.
936If statements may be nested.
937The switch statement looks like this:
938<?php
939switch ($value) {
940 case '10' :
941 // statements to execute
942 break;
943 case '20' :
944 // statements to execute
945 break;
946 case '30' :
947 // statements to execute
948 break;
949 default:
950 // statements to execute
951 break;
952}
953Once a case matches the value, the statements in the code block will be executed until it reaches a break command.
954If you omit the break command, then all the following statements in the switch will be executed until a break is hit even if the case does not match the value. This can be useful in some circumstances, but can also produce unintended outcomes if you forget to use the break statement.
955To illustrate, consider this example:
956<?php
957$value = 10;
958switch ($value) {
959 case '10' :
960 echo 'Value is 10';
961 // no break statement
962 case '20' :
963 echo 'Value is 20';
964 break;
965 case '30' :
966 echo 'Value is 30';
967 break;
968 default:
969 echo 'Value is not 10,20, or 30';
970 break;
971}
972// Value is 10Value is 20
973Note
974If you include case statements after the default case, they will not be checked.
975Loops
976PHP’s most basic loop is the while loop. It has two forms, as shown:
977<?php
978while (expression) {
979 // statements to execute
980}
981do {
982 // statements to execute
983} while (expression)
984The difference between them is that in the first form, the expression is evaluated at the beginning of the loop and in the second form, it’s evaluated at the end.
985This means that if the expression is false, the while loop will not run at all in the first case but it will run at least once in the second case.
986The for loop syntax shows the C roots of PHP and looks like this:
987<?php
988for ($i = 0; $i < 10; $i++) {
989 // do something
990}
991As with C, the first statement is executed to initialize the loop. The second condition is evaluated at the beginning of each loop, and the last statement is executed at the end of each loop. The loop will continue to run until the condition evaluates as false.
992To iterate over an array, you can use foreach , as follows:
993<?php
994$arr = [
995 'a' => 'one',
996 'b' => 'two',
997 'c' => 'three'
998];
999foreach ($arr as $value) {
1000 echo $value; // one, two, three
1001}
1002foreach ($arr as $key => $value) {
1003 echo $key; // a, b, c
1004 echo $value; // one, two, three
1005}
1006Breaking Out of Loops
1007There are two ways to stop an iteration of a loop in PHP— break and continue.
1008Using continue has the effect of stopping the current iteration and allowing the loop to process the next evaluation condition. This allows you to let any further iterations to occur.
1009Using break has the effect of stopping the entire loop and no further iterations will occur.
1010The break statement takes an optional integer value that can be used to break out of multiple levels of a nested loop. If no value is specified, it defaults to 1.
1011Namespaces
1012Namespaces help you avoid naming collisions between libraries or other shared code. A namespace will encapsulate the items inside it so that they don’t conflict with items declared elsewhere.
1013They can be used to avoid overly descriptive names for classes, to sub-divide a library into sections, or to limit the applicability of constants to one section of code.
1014Classes encapsulate code into instantiable units. Namespaces group functions, classes, and constants into spaces where their name is unique.
1015The namespace declaration must occur straight after the opening <?php tag and no other statements may precede it.
1016Namespaces affect constants, but you must declare them with the const keyword and not with define().
1017It is possible to have two namespaces in a file, but most coding standards will strongly discourage this. To accomplish this, you wrap the code for the namespace in braces, as in this example:
1018<?php
1019namespace A {
1020 // this is in namespace A
1021}
1022namespace B {
1023 // this is in namespace B
1024}
1025namespace {
1026 // this is in the global namespace
1027}
1028Note
1029This usage is not standard practice; in most cases a namespace declaration does not include the braces and all the statements in a file exist in only one namespace.
1030Fully Qualified Namespace Names
1031If you are working in a namespace, then the interpreter will assume that names are relative to the current namespace. Consider this class as a basis for the following examples:
1032<?php
1033namespace MyApp\Helpers;
1034class Formatters
1035{
1036 public static function asCurrency($val) {
1037 // statement
1038 }
1039}
1040If we want to use this class from another namespace, we need to provide a fully qualified namespace, as in this example:
1041<?php
1042// this file is in a different namespace
1043namespace MyApp\Lib;
1044// we must specify the full path to the namespace that the class is in
1045echo MyApp\Helpers\Formatters::asCurrency(10);
1046Alternatively, you may use the use statement to import a namespace so that you don’t have to use the long format all the time:
1047<?php
1048// this file is in a different namespace
1049namespace MyApp\Lib;
1050// the 'use' keyword imports the namespace
1051use MyApp\Helpers\Formatters;
1052// we no longer have to provide a full reference
1053echo Formatters::asCurrency(10);
1054You may precede a name with a backslash to indicate that you intend to use the global namespace, as in this example:
1055<?php
1056namespace MyApp;
1057throw new \Exception('Global namespace');
1058In this example, if we had not indicated the global scope with the backslash, the interpreter would look for a class called Exception within the MyApp namespace.
1059Configuration
1060I can highly recommend that you do some practical work to configure PHP. You can set up a virtual machine on your computer16 and install Linux17 on it, which will give you hands-on experience.
1061There are several Windows and Mac packages that offer an all-in-one configuration for PHP, but you should make sure that you find the config files and go through them.
1062Where Settings May Be Set or Changed
1063PHP offers a flexible configuration strategy whereby base configuration settings may be overridden by user configuration files and even at runtime by PHP itself.
1064It’s best to refer to the manual for this. Duplicating it here will only result in stale information. Refer to the following links:
1065
1066 https://secure.php.net/manual/en/configuration.changes.modes.php
1067 https://secure.php.net/manual/en/ini.list.php
1068
1069Php.ini
1070The PHP.ini file defines the configuration for each PHP environment. An environment here refers to how PHP is run—for example by command shell, as an FPM process, or within Apache2 as a module.
1071Each environment will have a directory off the main configuration directory, which is /etc/php/7.0/ by default on Ubuntu.
1072Windows machines use the registry to store the location of the php.ini. The actual key name varies between versions of PHP, but will follow a pattern similar to this: HKEY_LOCAL_MACHINE\SOFTWARE\PHP. If a Windows machine is unable to find it in the location specified by the Registry, it will fall back to looking for the file in a number of default locations, including the Windows system directory.
1073In addition to the php.ini file, it is possible to specify a directory that PHP will scan for additional configuration files. You can use the php_ini_scanned_files() function to obtain a list of the files that were included, as well as the order of inclusion.
1074The config file is read whenever the server (apache) or process (fpm/cli) starts. This means that if you make a change to the PHP configuration, you will need to reload your Apache2 server or restart the fpm service. In contrast, changes to the CLI configuration will take effect the next time you run PHP from the shell.
1075It is possible to use OS environment variables in your PHP.ini file, using syntax like this:
1076; PHP_MEMORY_LIMIT is taken from environment
1077memory_limit = ${PHP_MEMORY_LIMIT}
1078User INI Files
1079PHP checks these files when it is operating in FastCGI mode (PHP 5.3+). This is the case when you’re using the fpm module, but not in CLI or Apache2.
1080PHP will first check for these files in the directory that the script is running in and work backward up to the document root. The document root is configured in your host file and is reflected in the $_SERVER['DOCUMENT_ROOT'] variable.
1081These INI files will override the settings in php.ini, but will only affect settings that are flagged as PHP_INI_PERDIR or PHP_INI_USER. Refer to the previous link for a list of settings and where they may be changed.
1082The main configuration file has two directives that pertain to user INI files. The first, user_ini_filename, governs the name of the file that PHP looks for.
1083The second, user_cache_ttl, governs how often the user file is read from disk.
1084Apache Version of INI Files
1085If you are using Apache, then you can use .htaccess to manage user INI settings. They are searched for in the same method as the fastcgi files are.
1086You must set the AllowOverride setting in your vhost config to true in any directories that you want the .htaccess file to be read.
1087Performance
1088A great deal of PHP performance issues relate to the deployment environment, which is beyond the scope of this reference.
1089One potential deployment issue with performance worth mentioning in the context of the Zend examination is using the xdebug extension in production. As the name suggests, this extension is for debugging and should not be installed in production.
1090Another deployment concern is in keeping your PHP version up to date. PHP is constantly improving its performance and it’s a good idea to migrate your code to keep up with new PHP versions.
1091Tip
1092Using the latest version of PHP is a good way to improve performance. PHP 7 is about 30% (in my tests) faster than PHP 5 and some people claim it is even faster. PHP 7.2 is faster than PHP 7.1.
1093When considering performance for the Zend examination, we focus on memory management and the opcode cache.
1094Memory Management
1095Optimizing memory performance in PHP requires some understanding of how the language’s internal data type representation works.
1096PHP uses a container called a zval to store variables. The zval container contains four pieces of information:
1097Piece
1098
1099Description
1100Value
1101
1102The value the variable is set to.
1103Type
1104
1105The data type of the variable.
1106Is_ref
1107
1108A Boolean value indicating whether this variable is part of a reference set. Remember that variables can be assigned by reference. This Boolean value helps PHP decide if a particular variable is a normal variable or if it is a reference to another variable.
1109Refcount
1110
1111This is a counter that tracks how many variable names point to this particular zval container. This refcount is incremented when we declare a new variable to reference this one.
1112Variable names are referred to as symbols and are stored in a symbol table that is unique to the scope in which the variables occur.
1113Symbols Are Pointed to zval Containers
1114In the section on the reference operator, I mentioned that PHP has optimizations for assigning by value. PHP accomplishes this by only copying the value to a new zval when it changes, and initially pointing the new symbol to the same zval container. This mechanism is called “copy on write”.18
1115Here is an example to illustrate:
1116<?php
1117$a = 'new string';
1118$b =& $a;
1119// the variable b points to the variable a
1120xdebug_debug_zval( 'a' );
1121xdebug_debug_zval( 'b' );
1122// change the string and see that the refcount is reset
1123$b = 'changed string';
1124xdebug_debug_zval( 'a' );
1125xdebug_debug_zval( 'b' );
1126The output of this script is as follows:
1127a: (refcount=2, is_ref=0)='new string'
1128b: (refcount=2, is_ref=0)='new string'
1129a: (refcount=1, is_ref=0)='new string'
1130b: (refcount=1, is_ref=0)='changed string'
1131We can see that until we change the value of $b it is referring to the same zval container as $a.
1132Arrays and Objects
1133Arrays and objects use their own symbol table, separate from the scalar variables. They also use zval containers, but creating an array or object will result in several containers being created.
1134Consider this example:
1135<?php
1136$arr = ['name' => 'Bob', 'age' => 23 ];
1137xdebug_debug_zval( 'arr' );
1138The output from this script looks like this:
1139arr: (refcount=1, is_ref=0)=array (
1140 'name' => (refcount=1, is_ref=0)='Bob',
1141 'age' => (refcount=1, is_ref=0)=23)
1142We can see that three zval containers are created, one for the array variable itself and one for each of its two values.
1143Just as for scalar variables, if we had a third member of the array with the same value as another member then instead of creating a new zval container PHP will increase the refcount and point the duplicate symbol to the same zval.
1144Memory Leaks in Arrays and Objects
1145Memory leaks can occur when a composite object includes a reference to itself as a member. This is more likely to occur in use-cases with objects because PHP always assigns objects by reference. Possibly, for example, in parent-child relationships such as might be found in an ORM model.
1146The PHP Manual has a series of diagrams explaining this on the refcounting basics page.19 The problem occurs when you unset a composite object that has a reference to itself.
1147In this event, the symbol table is cleared of a reference to the zval structure that was used to contain the variable. PHP does not iterate through the composite object because this would result in recursion as it follows links to itself. This means that the member in the variable that is a reference to itself is not unset, and the zval container is not marked as free. There is no symbol pointing to this zval container and so the user cannot free the memory herself.
1148PHP will clear up these references at the end of the request. Remember that PHP is not intended to be a long-running language and is designed to be a text processor built for serving specific requests within the context of a web application.
1149Garbage Collection
1150The garbage collector clears circular references, which are those where a complex object contains a member that refers to itself.
1151PHP will initiate garbage collection when the root buffer is full or when the function gc_collect_cycles() is called.
1152The garbage collector will only cause a slowdown when it actually needs to do something. In smaller scripts where there is no leakage it won’t cause a performance drop.
1153Garbage collection is likely to be of benefit in long-running scripts or those where a memory leak is repeatedly created, such as processing a very large amount of database records using ORM models that leak.
1154The Opcode Cache
1155PHP is compiled into a sequence of intermediate instructions that are executed in order by the runtime engine. These instructions are called opcodes or bytecodes and this process occurs every time the script is run.
1156The bytecode is interpreted by the runtime engine; therefore, PHP is both precompiled and interpreted.
1157An opcode cache stores the converted instructions for a script. Subsequent calls to the script do not require the script to be interpreted prior to being run.
1158In 2013, Zend contributed their optimization engine to PHP. Known as opcache, it is baked into distributions of PHP as of version 5.5 and is probably the most commonly used PHP opcode cache.
1159Note
1160Opcache is built into PHP 7.1 and is enabled by default in your php.ini 20 settings.
1161Take note of the setting opcache.revalidate_freq. This determines the interval in seconds that PHP will scan for changes in the source file before recompiling it. You can set it to 0 to tell PHP to always scan for changes. PHP will not scan the file more than once per request.
1162In addition to the cache built into PHP, there are a number of third-party opcode caches available (see Wikipedia21 if you’re interested).
1163Tip
1164Using the opcode cache results in significant performance increases.
1165Extensions
1166PHP extensions extend on the functionality offered by the core language. A number of them are enabled by default into standard repository distributions of PHP. Other extensions need to be downloaded and installed manually.
1167PECL is a repository for PHP extensions. It provides an easy way to download and install extensions on Linux. Windows machines need to compile and install extensions manually, but usually they’re distributed in a compiled form and you just need to edit your INI file to enable them.
1168PHP includes several extensions that cannot be removed from PHP with compilation flags. These extensions include core functionality such as reflection, arrays, date and time, SPL, and math. You should be able to rely on them being installed.
1169Installing an Extension
1170Extensions are enabled through the php.ini file using the “extension” setting to specify the filename of the extension, like this for mcrypt:
1171extension=mcrypt.so;
1172You can set the extension directory with a setting in your php.ini file like so:
1173extension_dir = '/usr/lib/php5/20121212/mcrypt.so'
1174Different systems may provide convenient ways of installing and enabling extensions. PECL extensions can be installed using the pecl command-line utility.
1175Checking for Installed Extensions
1176The extensions installed will display if you call phpinfo() or if you use the more specific command get_loaded_extensions().
1177Running php –m from the shell will show a list of extensions installed.
1178You can check if an extension is loaded by calling extension_loaded(). This is recommended if you’re using a function in an extension that is not loaded by default. Here is an example from the PHP Manual:
1179<?php
1180if (!extension_loaded('gd')) {
1181 if (!dl('gd.so')) {
1182 exit;
1183 }
1184}
1185Chapter 1 Quiz
1186Q1: Which of the following tags should you avoid using to include PHP in HTML?
1187<?php
1188<?
1189<?=
1190None of the above; these are all fine
1191Q2: Which of the following are NOT case sensitive in PHP? Choose all that apply.
1192Variable names
1193Class names
1194Namespaces
1195Function names
1196Q3: What will this script output?
1197<?php
1198$a = 'Hello';
1199$B = ' world';
1200ECHO $a . $b;
1201Nothing; it won’t run
1202Hello world
1203Hello
1204An error message because the variable b is not defined
1205An error message and the word 'Hello'
1206Q4: What will this script output?
1207<?php
1208function A() {
1209 try {
1210 b();
1211 } catch (Exception $e) {
1212 echo 'Exception caught in ' . __CLASS__;
1213 }
1214}
1215function B() {
1216 C();
1217}
1218try {
1219 A();
1220} catch (Error $e) {
1221 echo 'Error caught in global scope: ' . $e->getMessage();
1222}
1223Exception caught in A
1224Error caught in global scope: Call to undefined function C()
1225Error caught in global scope: Call to undefined function b()
1226None of the above
1227Q5: What will this script output?
1228<?php
1229function A() {
1230 try {
1231 b();
1232 } catch (Exception $e) {
1233 echo 'Exception caught in ' . __CLASS__;
1234 }
1235}
1236function B() {
1237 echo 5 / 'five';
1238}
1239try {
1240 A();
1241} catch (Error $e) {
1242 echo 'Error caught in global scope: ' . $e->getMessage();
1243}
1244Exception caught in A
1245Error caught in global scope: Call to undefined function C()
12461
1247Error caught in global scope: Call to undefined function b()
1248None of the above
1249Q6: What will this script output?
1250<?php
1251class MyException extends Exception {}
1252class ChildException extends MyException {}
1253try {
1254 throw new ChildException;
1255} catch (Exception $e) {
1256 echo 'Caught Exception: ' . get_class($e);
1257} catch (MyException $e) {
1258 echo 'Caught MyException' . get_class($e);
1259}
1260Caught Exception: ChildException
1261Caught MyException: ChildException
1262Caught MyException: MyException
1263Nothing
1264An error message related to an uncaught exception
1265Q7: Which of the following settings can be configured at runtime using the ini_set() function?
1266output_buffering
1267memory_limit
1268max_execution_time
1269extension
1270Q8: What is the output of this script?
1271<?php
1272$a = 'apples' <=> 'bananas';
1273$b = $a ?? $c ?? 10;
1274echo $b;
1275-1
12760
12771
127810
1279apples
1280Q9: What is the output of this script?
1281<?php
1282echo 10 <=> 10 << 1;
1283-1
12840
12851
128610
1287Q10: What is the output of this script?
1288<?php
1289define('A', 1);
1290const B = 2;
1291define('C', [A * A, B * B]);
1292echo(C[1]);
1293This will generate an error because constants can only hold scalar values.
1294This will generate an error because you cannot use define() to declare an array constant.
1295This will generate an error because you cannot use expressions or functions when declaring a constant.
12961
12972
12984
1299Footnotes
13001
1301https://php.net/manual/en/reserved.php
1302
13032
1304https://www.phpdoc.org/
1305
13063
1307https://php.net/manual/en/language.types.type-juggling.php
1308
13094
1310https://secure.php.net/manual/en/language.types.string.php#language.types.string.conversion
1311
13125
1313https://secure.php.net/manual/en/language.types.integer.php
1314
13156
1316https://php.net/manual/en/reserved.constants.php
1317
13187
1319https://php.net/manual/en/language.constants.syntax.php
1320
13218
1322https://php.net/manual/en/function.define.php
1323
13249
1325https://php.net/manual/en/function.constant.php
1326
132710
1328https://php.net/manual/en/language.variables.superglobals.php
1329
133011
1331https://php.net/manual/en/reserved.variables.server.php
1332
133312
1334https://secure.php.net/manual/en/reserved.constants.php
1335
133613
1337https://secure.php.net/manual/en/language.constants.predefined.php
1338
133914
1340https://php.net/manual/en/language.operators.precedence.php
1341
134215
1343https://en.wikipedia.org/wiki/Two%27s_complement
1344
134516
1346http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html
1347
134817
1349https://www.ubuntu.com/download/server
1350
135118
1352https://en.wikipedia.org/wiki/Copy-on-write
1353
135419
1355https://php.net/manual/en/features.gc.refcounting-basics.php
1356
135720
1358https://github.com/php/php-src/blob/master/php.ini-production#L1763
1359
136021
1361https://en.wikipedia.org/wiki/List_of_PHP_accelerators
1362
1363