The pitfall in foreach($items as &$item). Description of the com_content template structure Example of template editing

No matter how much we use PHP, some functions still pop up that we have never even heard of. Some of them would be very useful to us. I have created a small list of useful functions that should be in the arsenal of every PHP programmer.

1. Creating functions with a variable number of arguments

Most likely, you already know that PHP allows us to create functions with optional arguments. Now I will show a function in which the number of arguments can vary from case to case.

But first, let's remember how we create functions in the usual way:

// function with two optional parameters function foo($arg1 = "", $arg2 = "") ( echo "arg1: $arg1\n"; echo "arg2: $arg2\n"; ) foo("hello", "world"); /* will output: arg1: hello arg2: world */ foo(); /* will output: arg1: arg2: */

Now let's look at how you can write a function with an unlimited number of arguments. To do this, the func_get_args() method will be used:

// do not specify arguments function foo() ( // returns an array of passed arguments $args = func_get_args(); foreach ($args as $k => $v) ( echo "arg".($k+1)." : $v\n"; ) ) foo(); /* will not output anything */ foo("hello"); /* will print arg1: hello */ foo("hello", "world", "again"); /* will print arg1: hello arg2: world arg3: again */

2. Use Glob() to search for files

Often the names of functions speak for themselves. The same cannot be said for the glob() function.

Without going into too much detail, its functionality is similar to the scandir() method. It allows you to find the required file using a template:

// find all php files $files = glob("*.php"); print_r($files); /* will output: Array ( => phptest.php => pi.php => post_output.php => test.php) */

To find files of several types you need to write like this:

// find all php and txt files $files = glob("*.(php,txt)", GLOB_BRACE); print_r($files); /* output: Array ( => phptest.php => pi.php => post_output.php => test.php => log.txt => test.txt) */

You can also specify the path in the template:

$files = glob("../images/a*.jpg"); print_r($files); /* output: Array ( => ../images/apple.jpg => ../images/art.jpg) */

To get the full path to a document, use the realpath() method:

$files = glob("../images/a*.jpg"); // Apply the "realpath" function to each array element $files = array_map("realpath",$files); print_r($files); /* will output: Array ( => C:\wamp\www\images\apple.jpg => C:\wamp\www\images\art.jpg) */

3. Information about memory used

If you keep track of the amount of memory consumed by your scripts, you will probably optimize them more often.

PHP has a powerful memory tracking tool. The loads may be different in different parts of the script. To get the currently used memory value, we should use the memory_get_usage() method. To fix the maximum amount of memory used, use memory_get_peak_usage()

Echo "Initial: ".memory_get_usage()." bytes \n"; /* Initial: 361400 bytes */ // give a small load for ($i = 0; $i< 100000; $i++) { $array = md5($i); } // и ещё for ($i = 0; $i < 100000; $i++) { unset($array[$i]); } echo "Final: ".memory_get_usage()." bytes \n"; /* Final: 885912 bytes */ echo "Peak: ".memory_get_peak_usage()." bytes \n"; /* Peak: 13687072 bytes */

4. Processor information

To do this, you need to use the getrusage() method. But keep in mind that this feature will not work on Windows.

Print_r(getrusage()); /* prints Array ( => 0 => 0 => 2 => 3 => 12692 => 764 => 3864 => 94 => 0 => 1 => 67 => 4 => 0 => 0 => 0 => 6269 => 0) */

The picture outlined above will be clear to those who have experience in system administration. For everyone else, we offer a transcript:

  • ru_oublock: number of block write operations
  • ru_inblock: number of block read operations
  • ru_msgsnd: number of messages sent
  • ru_msgrcv: number of received messages
  • ru_maxrss: maximum size of a non-paged set
  • ru_ixrss: total amount of shared memory
  • ru_idrss: total volume of unshared data
  • ru_minflt: number of memory pages used
  • ru_majflt: number of page missing errors
  • ru_nsignals: number of received signals
  • ru_nvcsw: number of context switches by the process
  • ru_nivcsw: number of forced context switches
  • ru_nswap: number of disk accesses when paging
  • ru_utime.tv_usec: operating time in user mode (microseconds)
  • ru_utime.tv_sec: operating time in user mode (seconds)
  • ru_stime.tv_usec: operating time in privileged mode (microseconds)
  • ru_stime.tv_sec: operating time in privileged mode (seconds)

In order to find out what resources of your processor are used by the script, you need the value of 'user time' (user time) and 'system time' (privileged mode time). You can get the result in both seconds and microseconds. To convert the total number of seconds to a decimal number, you need to divide the microseconds value by 1 million and add the seconds value to the value.

It's kind of confusing. Here's an example:

// rest for 3 seconds sleep(3); $data = getrusage(); echo "User time: ". ($data["ru_utime.tv_sec"] + $data["ru_utime.tv_usec"] / 1000000); echo "System time: ". ($data["ru_stime.tv_sec"] + $data["ru_stime.tv_usec"] / 1000000); /* prints User time: 0.011552 System time: 0 */

Although the script took about 3 seconds to execute, the processor was not heavily loaded. The fact is that when called (sleep), the script consumes virtually no processor resources. In general, there are many tasks that take a significant amount of time, but do not use the processor. For example, waiting for disk-related operations. So you don't always use CPU time in your scripts.

Here's another example:

// walk 10 million times for($i=0;$i hello => 42 => Array ( => 1 => two) => apple) */

This is how these functions work. However, due to the rapid growth in popularity of JSON, 2 methods json_encode() and json_decode() were added to PHP 5.2. Their work is similar to serialize():

// complex array $myvar = array("hello", 42, array(1,"two"), "apple"); // convert to string $string = json_encode($myvar); echo $string; /* will print ["hello",42,,"apple"] */ // restore the original value $newvar = json_decode($string); print_r($newvar); /* prints Array ( => hello => 42 => Array ( => 1 => two) => apple) */

This option is more compact and compatible with other languages ​​such as JavaScript. However, when working with very complex objects, data loss may occur.

8. String compression

When we talk about compression, archive files in ZIP format immediately come to mind. PHP provides the ability to compress long strings without any files.

The following example demonstrates how the gzcompress() and gzuncompress() functions work:

$string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut elit id mi ultricies adipiscing. Nulla facilisi. Praesent pulvinar, sapien vel feugiat vestibulum, nulla dui pretium orci, non ultricies elit lacus quis ante. Lorem ipsum dolor sit amet , consectetur adipiscing elit. Aliquam pretium ullamcorper urna quis iaculis. Etiam ac massa sed turpis tempor luctus. Curabitur sed nibh eu elit mollis congue. Praesent ipsum diam, consectetur vitae ornare a, aliquam a nunc. In id magna pellentesque tellus posuere ad ipiscing.Sed non mi metus, at lacinia augue. Sed magna nisi, ornare in mollis in, mollis sed nunc. Etiam at justo in leo congue mollis. Nullam in neque eget metus hendrerit scelerisque eu non enim. Ut malesuada lacus eu nulla bibendum id euismod urna sodales . "; $compressed = gzcompress($string); echo "Original size: ". strlen($string)."\n"; /* will output Original size: 800 */ echo "Compressed size: ". strlen($compressed)."\n"; /* will output Compressed size: 418 */ // return $original = gzuncompress($compressed);

We can reduce the volume of text by 50%. For the same purposes, you can use the gzencode() and gzdecode() methods, which use a different compression algorithm.

9. Execute before exiting

PHP has a register_shutdown_function() function that will allow you to execute some code before shutting down the script.

Let's say you want to find out some information... Script running time:

// get the start time $start_time = microtime(true); // some operations // ... // display the running time echo "execution took: ". (microtime(true) - $start_time). "seconds.";

At first glance, this may seem like a trivial task. For these purposes, you can place the code at the end of the file. However, if the exit() function fires somewhere before this, this code will never work. Also, it will not work if there is an error on the page or the user interrupts the page loading (by clicking on the corresponding button in his browser);

When using the register_shutdown_function() method, the code will be executed in any case:

$start_time = microtime(true); register_shutdown_function("my_shutdown"); function my_shutdown() ( global $start_time; echo "execution took: ". (microtime(true) - $start_time). " seconds."; )

Conclusion

PHP is a whole planet that never ceases to amaze us with its content. What do you think about these functions?

Are you creating and promoting a website running CMS Joomla and suddenly you have a need to remake the design of the material to your taste and in your own way by editing the standard templates of the com_content component? The component is responsible for generating content. Let's understand the structure of the component itself.

Standard Material Template Location

The original com_content component files are located in the components\com_content\views\View\tmpl folder. If the component files are copied to the \templates\template you are using\html\com_content\ directory, then the materials template will be taken from the files in this folder.

Directories and template files

The template location directory contains five folders for creating views.

archive folder

  • Archive output template folder. This article is not discussed; rarely does anyone use it. The structure is similar to the folders described below;

article folder - Material

frontpage folder - Home page

  • default.php Same principle as category\blog.php;
  • default_item.php Same principle as category\blog_item.php;
  • default_links.php Same principle as category\blog_links.php;

folder section - Section

  • blog.php Section blog template. Same principle as category\blog.php;
  • blog_item.php Template for separate material from the section blog. Same principle as category\blog_item.php;
  • blog_links.php Template for presenting links under the section blog. Same principle as category\blog_links.php;
  • default.php Standard section template. Displays the category title, its description, and the number of elements. After clicking on the category title, the page is processed by category\default.php;
An example of template editing. Displays the number of views of the material.

Let's say we want to display the number of hits of an individual article from a category blog. To do this, edit the category\blog_item.php template. The code for inserting information about hits will be like this:

Now you need to find a place in the category\blog_item.php template file where to insert this code. For example, before displaying the date the material was last edited. We are looking for the line:

And before it we insert a line with the code.

Example displaying a list of categories in several columns .

Many fatal and recoverable fatal errors have been converted to exceptions in PHP 7. These error exceptions inherit from the Error class, which itself implements the Throwable interface (the new base interface all exceptions inherit).

This means that custom error handlers may no longer be triggered because exceptions may be thrown instead (causing new fatal errors for uncaught Error exceptions).

A fuller description of how errors operate in PHP 7 can be found on the PHP 7 errors page. This migration guide will merely enumerate the changes that affect backward compatibility.

Internal constructors always throw exceptions on failure

Previously, some internal classes would return NULL or an unusable object when the constructor failed. All internal classes will now throw an Exception in this case in the same way that user classes already had to.

E_STRICT notices severity changes

All of the E_STRICT notices have been reclassified to other levels. E_STRICT constant is retained, so calls like error_reporting(E_ALL|E_STRICT) will not cause an error.

E_STRICT notices severity changes Situation New level/behaviour
Indexing by a resource E_NOTICE
Abstract static methods
"Redefining" a constructor Notice removed, triggers no error
Signature mismatch during inheritance E_WARNING
Same (compatible) property in two used traits Notice removed, triggers no error
Accessing static property non-statically E_NOTICE
Only variables should be assigned by reference E_NOTICE
Only variables should be passed by reference E_NOTICE
Calling non-static methods statically E_DEPRECATED
Changes to variable handling

PHP 7 now uses an abstract syntax tree when parsing source files. This has permitted many improvements to the language which were previously impossible due to limitations in the parser used in earlier versions of PHP, but has resulted in the removal of a few special cases for consistency reasons, which has resulted in backward compatibility breaks. These cases are detailed in this section.

Changes to the handling of indirect variables, properties, and methods

Indirect access to variables, properties, and methods will now be evaluated strictly in left-to-right order, as opposed to the previous mix of special cases. The table below shows how the order of evaluation has changed.

Old and new evaluation of indirect expressions Expression PHP 5 interpretation PHP 7 interpretation
$$foo["bar"]["baz"] $($foo["bar"]["baz"]) ($$foo)["bar"]["baz"]
$foo->$bar["baz"] $foo->($bar["baz"]) ($foo->$bar)["baz"]
$foo->$bar["baz"]() $foo->($bar["baz"])() ($foo->$bar)["baz"]()
Foo::$bar["baz"]() Foo::($bar["baz"])() (Foo::$bar)["baz"]()

Code that used the old right-to-left evaluation order must be rewritten to explicitly use that evaluation order with curly braces (see the above middle column). This will make the code both forwards compatible with PHP 7.x and backwards compatible with PHP 5.x.

Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2 Stack trace: #0 (main) thrown in /tmp/test.php on line 2

Out of range bitshifts

Bitwise shifts (in either direction) beyond the bit width of an integer will always result in 0. Previously, the behavior of such shifts was architecture dependent.

Changes to Division By Zero

Previously, when 0 was used as the divisor for either the divide (/) or modulus (%) operators, an E_WARNING would be emitted and false would be returned. Now, the divide operator returns a float as either +INF, -INF, or NAN, as specified by IEEE 754. The modulus operator E_WARNING has been removed and will throw a DivisionByZeroError exception.

Output of the above example in PHP 5:

Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false)

Output of the above example in PHP 7:

Warning: Division by zero in %s on line %d float(INF) Warning: Division by zero in %s on line %d float(NAN) PHP Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %s line %d

\u( may cause errors

Due to the addition of the new Unicode codepoint escape syntax , strings containing a literal \u( followed by an invalid sequence will cause a fatal error. To avoid this, the leading backslash should be escaped.

Removed functions Removed INI directives xsl.security_prefs

The xsl.security_prefs directive has been removed. Instead, the XsltProcessor::setSecurityPrefs() method should be called to control the security preferences on a per-processor basis.

Other backward incompatible changes New objects cannot be assigned by reference

The result of the new statement can no longer be assigned to a variable by reference:

Output of the above example in PHP 5:

Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3

Output of the above example in PHP 7:

Parse error: syntax error, unexpected "new" (T_NEW) in /tmp/test.php on line 3

Invalid class, interface and trait names

The following names cannot be used to name classes, interfaces or traits:

  • bool
  • int
  • float
  • string
  • NULL
  • TRUE
  • FALSE

Furthermore, the following names should not be used. Although they will not generate an error in PHP 7.0, they are reserved for future use and should be considered deprecated.

  • object
  • mixed
  • numeric
ASP and script PHP tags removed

Support for using ASP and script tags to delimit PHP code has been removed. The affected tags are:

Removed ASP and script tags Opening tag Closing tag
Calls from incompatible context removed

Previously deprecated in PHP 5.6, static calls made to a non-static method with an incompatible context will now result in the called method having an undefined $this variable and a deprecation warning being issued.

Output of the above example in PHP 5.6:

Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8 object(B)#1 (0) ( )

Output of the above example in PHP 7:

Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8 Notice: Undefined variable: this in /tmp/test.php on line 3 NULL

yield is now a right associative operator

The yield construct no longer requires parentheses, and has been changed to a right associative operator with precedence between print and => . This can result in changed behavior:

Parentheses can be used to disambiguate those cases.

Functions cannot have multiple parameters with the same name

It is no longer possible to define two or more function parameters with the same name. For example, the following function will trigger an E_COMPILE_ERROR :

Functions inspecting arguments report the current parameter value

func_get_arg() , func_get_args() , debug_backtrace() and exception backtraces will no longer report the original value that was passed to a parameter, but will instead provide the current value (which might have been modified).

Output of the above example in PHP 5:

Output of the above example in PHP 7:

Switch statements cannot have multiple default blocks

It is no longer possible to define two or more default blocks in a switch statement. For example, the following switch statement will trigger an E_COMPILE_ERROR :

JSON replaced extension with JSOND

The JSON extension has been replaced with JSOND, causing three minor BC breaks. Firstly, a number must not end in a decimal point (i.e. 34. must be changed to either 34.0 or 34 ). Secondly, when using scientific notation, the e exponent must not immediately follow a decimal point (i.e. 3.e3 must be changed to either 3.0e3 or 3e3). Finally, an empty string is no longer considered valid JSON.

Internal function failure on overflow

Previously, internal functions would silently truncate numbers produced from float-to-integer coercions when the float was too large to represent as an integer. Now, an E_WARNING will be emitted and NULL will be returned.

Fixes to custom session handler return values

Any predicate functions implemented by custom session handlers that return either FALSE or -1 will be fatal errors. If any value from these functions other than a boolean, -1 , or 0 is returned, then it will fail and an E_WARNING will be emitted.

Sort order of equal elements

The internal sorting algorithm has been improved, what may result in different sort order of elements, which compare as equal, than before.

Don"t rely on the order of elements which compare as equal; it might change anytime.

Misplaced break and switch statements

break and continue statements outside of a loop or switch control structure are now detected at compile-time instead of run-time as before, and trigger an E_COMPILE_ERROR .

See involuntarily... Dictionary of Russian synonyms and expressions similar in meaning. under. ed. N. Abramova, M.: Russian Dictionaries, 1999. unconsciously instinctively, without realizing it, spontaneously, panic, instinctively, without realizing it, without realizing it,... ... Dictionary of synonyms

Unaccountably, instinctively, mechanically, spontaneously, blindly. See... Dictionary of synonyms

Involuntarily, unconsciously, unconsciously, instinctively, mechanically, mechanically, blindly, spontaneously; accidentally, unintentionally; willy-nilly, like it or not (volens nolens), out of necessity He had to do this due to things beyond his control... ... Dictionary of synonyms

Blindly, subconsciously, gut, without realizing it, without knowing it, spontaneously, unconsciously, without realizing it, unconsciously, mechanically, unconsciously, unconsciously, intuitively, unconsciously, sixth sense, instinctively Dictionary of Russian... ... Dictionary of synonyms

See involuntarily... Dictionary of Russian synonyms and expressions similar in meaning. under. ed. N. Abramova, M.: Russian Dictionaries, 1999. blindly unconsciously, involuntarily; indistinctly, recklessly, unaccountably, spontaneously, instinctively, slavishly, unconsciously, unclearly,... ... Dictionary of synonyms

adv. to unaccountable. [Mother] wanted to turn back, but unconsciously went forward again. M. Gorky, Mother. [Judas] begged his good friend Mama to manage his estate unaccountably. Saltykov Shchedrin, Messrs. Golovlevs ... Small Academic Dictionary

UNACCOUNTABLE, unaccountable, unaccountable; (short masculine not used) unaccountable, unaccountable. 1. Not subject to any control, not obliged to report. He was unaccountably (adv.) in charge of the shop. 2. Not dependent on reasonable considerations,... ... Ushakov's Explanatory Dictionary

- (Greek). A person who is entrusted to trade unaccountably for the account of another person. Dictionary of foreign words included in the Russian language. Chudinov A.N., 1910. ANAGALIST A person who is entrusted to trade at the expense of another person without accountability. Explanation... ... Dictionary of foreign words of the Russian language

Unaccountably, unconsciously, mechanically, involuntarily, automatically, mechanically, automatically, mechanically, autopilot Dictionary of Russian synonyms. automatically see automatically Dictionary of synonyms of the Russian language. Practical guide. M.: Russian... Dictionary of synonyms

See involuntarily... Dictionary of Russian synonyms and expressions similar in meaning. under. ed. N. Abramova, M.: Russian Dictionaries, 1999. instinctively, unconsciously, involuntarily; involuntarily, unconsciously, gut, spontaneously, spontaneously, unconsciously, blindly,... ... Dictionary of synonyms

Books
  • Travel through Czechoslovakia, J. Marko, M. Peterka, Prague, 1959. Artia. With many photo illustrations. Publisher's binding. The condition is good. An enchanted wanderer from any country in the world, delving into this wonderful book, will be able... Category: Notes of travelers, memoirs, research Publisher: Artia,
  • Board, or Meetings on Sennaya, Gennady Grigoriev, Sergey Nosov, There are simply phantasmogenic places in St. Petersburg. These include Sennaya Square. "Sennaya - the cradle of phantasmagoria". The authors themselves seem to be surprised by what happened to them on Sennaya. And... Category: Classical and modern prose Series: St. Petersburg faces of our time Publisher:

Many people like to write such constructions in one form or another, everyone has come across:
foreach ($items as &$item) ( $item += 2; )
But not many people suspect the danger that lurks here.
Let's look at an example.

Vasya Pupkin took the array, walked through it, increasing all elements by two:
$items = array("a" => 10, "b" => 20, "c" => 30,); foreach ($items as &$item) ( $item += 2; ) print_r($items);
I looked at the dump, saw that the problem was solved, and left satisfied:
Array ([a] => 12 [b] => 22 [c] => 32)
After some time, Petrovich decided to supplement this section of code with another search, adding below:
$newitems = array("a" => 10, "b" => 20, "c" => 30,); foreach ($newitems as $key=>$item) ( $newitems[$key] += 5; ) print_r($newitems);
He saw that his task was also solved, and with a feeling of accomplishment, he closed the file:
Array ([a] => 15 [b] => 25 [c] => 35)
After some time, unexplained bugs began to appear. Why?
Let's do var_dump($items) at the end of the code:
array(3) ( ["a"]=> int(12) ["b"]=> int(22) ["c"]=> &int(30) )
thirty! Vasya Pupkin swears that he checked. Why was it 32, and after Petrovich’s code 30?

The reason lies in the ampersand. He reports that someone else is referencing the flagged data. When leaving, Vasya did not wipe behind him the temporary variable that he used to brute force ($item). The variable was used with change-of-source permission ("&"), also called "assignment by reference". He was sure that the variable would only be used inside the loop. Petrovich, using a variable with the same name, during his search, changed its value, and each time the place where this variable was stored changed. And it was stored in the same place as the last element of the Pupkin array.

Of course, the case in the article is exaggerated. In practice, such connections can be very complex, especially if the project is low-cost and involves insufficiently experienced and dispersed web developers.

How can you deal with this?

  • Destroy temporary variables after use, especially if they have some connection with the data being used:
    foreach ($items as &$item) $item += 2; unset($item);
  • Be careful with variables that have already been used by someone.
  • Encapsulate your actions into separate functions, methods or namespaces.
  • Use var_dump instead of print_r, and pay attention to the ampersand. To dump to a file rather than to the browser, an alternative to print_r($var,true) would be this construct:
    function dump() ( ob_start(); foreach(func_get_args() as $var) var_dump($var); return ob_get_clean(); )
In conclusion, I will say that bugs related to links can occur not only in foreach. And they were all discussed at some point. However, judging by my experience, this case is so common in practice that it deserves special attention.
mob_info