Ошибка uninitialized string offset

I have a form that users fill out, and on the form there are multiple identical fields, like «project name», «project date», «catagory», etc. Based on how many forms a user is submitting, my goal is to:

  1. loop over the number of forms
  2. create individual SQL insert statements

However, PHP throws me a NOTICE that I don’t seem to understand:

Notice:

Notice: Uninitialized string offset: 1 …dataPasser.php on line 90

PHP

$myQuery = array();

if ($varsCount != 0)
{
  for ($i=0; $i <= $varsCount; $i++)
  {
    $var = "insert into projectData values ('" . $catagory[$i] . "', '" .  $task[$i] . "', '" . $fullText[$i] . "', '" . $dueDate[$i] . "', null, '" . $empId[$i] ."')";
    array_push($myQuery, $var);     
  }
}

There are references to this issue I am having, but they are not exact and I am having trouble deducing where the actual problem stems from. I would greatly appreciate any help in understanding what is causing the array to not initialize properly.

Есть функция шифровки/расшифровки строки по ключу, при расшифровке пишет предупреждения:

Notice:  Uninitialized string offset: 63 in [...][...] on line 18
Notice:  Uninitialized string offset: 63 in [...][...] on line 19

Это строки:

$tmp = md5(md5($key.$strofsym[$x-1]).$key);
$encoded = str_replace($tmp[3].$tmp[6].$tmp[1].$tmp[2], $strofsym[$x-1], $encoded);

Сами функции:

function encode($unencoded,$key){ //Шифрование
$string=base64_encode($unencoded);
$newstr = '';
$arr=array();
$x=0;
while ($x++< strlen($string)) {
$arr[$x-1] = md5(md5($key.$string[$x-1]).$key);
$newstr = $newstr.$arr[$x-1][3].$arr[$x-1][6].$arr[$x-1][1].$arr[$x-1][2];
}
return $newstr;
}

function decode($encoded, $key){ //Расшифровка
$strofsym='qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM=';
$x=0;
while ($x++<= strlen($strofsym)) {
$tmp = md5(md5($key.$strofsym[$x-1]).$key);
$encoded = str_replace($tmp[3].$tmp[6].$tmp[1].$tmp[2], $strofsym[$x-1], $encoded);
}
return base64_decode($encoded);
}

echo decode('70072bbbd45b597a700751f437683768','z');

Не критично, но бесит

Vagrant

0 / 0 / 0

Регистрация: 11.01.2016

Сообщений: 5

1

12.01.2016, 13:17. Показов 4577. Ответов 7

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Доброго времени суток всем.

Кратко суть: при парсинге страницы с помощью simple_html_dom.php сталкиваюсь с предупреждением типа

Код

Notice: Uninitialized string offset: 0 in C:%путь%simple_html_dom.php on line 707

вот код, который использую я:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
require_once 'php/simple_html_dom.php';
$text = file_get_contents("url.com");
if ($text) {
    $text=iconv ("CP1251", "UTF-8",$text);
    $html_text=str_get_html($text);
    echo '<div class=""> <ul>';
    if($html_text->innertext!='' and count($html_text->find('a'))){
        foreach($html_text->find('a') as $links)
            if (strpos($links->href,"/")!=1) //если ссылка внешняя ( НЕ начинается с "/")
                echo '<li><a target= "_blank" href="'.$links->href.'">'.$links->plaintext.'</a></li></br>';
            else //если ссылка внутренняя - добавляем адрес хоста
                echo '<li><a target= "_blank" href="url.com'.$links->href.'">'.$links->plaintext.'</a></li></br>';
    }
    echo '</ul></div>';
}
else echo '<br>Сервер временно недоступен, попробуйте обновить страницу';
?>

при этом вышеуказанный notice появляется ровно столько раз, сколько в коде конструкций типа

PHP
1
$html_text->find('a')

После часов поисков в интернете и на форуме, пришел к выводу что наилучший способ решения проблемы в моем конкретном случае — на время работы «моего» парсера отключить ошибки типа E_NOTICE, а потом вернуть все как было.
Именно в этом и состоит суть задачи: сохранить текущее состояние->от ключить уровень E_NOTICE->собственно парсинг->вернуть изначальное состояние.

Заранее благодарю за помощь.
P.S. PHP изучаю всего «без года неделю», так что не судите строго, если вдруг код «кривой» или изложение задачи неправильное.



0



xpoince

182 / 182 / 83

Регистрация: 18.02.2014

Сообщений: 867

12.01.2016, 14:39

2

Vagrant, просто переменная пустая. Кидаете пустышку вот он и пугается. надо сделать проверку на

PHP
1
2
if (!empty($var))
   //code



0



Vagrant

0 / 0 / 0

Регистрация: 11.01.2016

Сообщений: 5

12.01.2016, 15:41

 [ТС]

3

xpoince, какая именно переменная у меня пустая?.
На сколько я понял, в переменную $html_text записывается обьект класса simlpe_html_dom(), и если это так, то эта переменная не пустая, поскольку цикл

PHP
1
foreach($html_text->find('a') as $links)

таки выводит нужные мне ссылки.



0



xpoince

182 / 182 / 83

Регистрация: 18.02.2014

Сообщений: 867

12.01.2016, 15:49

4

Vagrant, Вот наглядный пример.

PHP
1
2
3
4
[0] => 'www.www.www', // succes
[1] => array(0 => ''), // Notice: Uninitialized string offset: 0
[2] => 'www1.www.www', // succes
[3] => '', // Notice: Uninitialized string offset: 0



0



0 / 0 / 0

Регистрация: 11.01.2016

Сообщений: 5

12.01.2016, 18:24

 [ТС]

5

xpoince, повторюсь, я начал разбирать азы php совсем недавно, поэтому я (надеюсь, временно) не сильно разбираюсь во всех тонкостях. Но, исходя из вашего примера, у меня в каком-то из массивов (предполагаю, массив ссылок) есть элемент типа string с пустым содержанием, так? и если так, то обрабатывается он кодом библиотеки simple_html_dom.php, что опять таки приводит меня к варианту временного отключения обработки E_NOTICE.

Добавлено через 1 час 55 минут
Оказалось, что всё значительно проще… достаточно было использовать префикс «@».

Спасибо огромное, узнал для себя что-то новое ;-)



0



182 / 182 / 83

Регистрация: 18.02.2014

Сообщений: 867

12.01.2016, 18:47

6

Vagrant, к сожалению это не проще. Почитайте что вы скрыли. @ лучше избегать в использование, бывают случаи когда надо @ использовать, но это не есть хорошо. Вы в таком случае могли просто убрать notice и все. @ не покажет вам критическую ошибку и вы будете тратить кучу времени что бы вспомнить где вы прописали @ да и вообще если вспомните что писали @



0



25 / 25 / 15

Регистрация: 12.10.2013

Сообщений: 183

12.01.2016, 18:54

7

Цитата
Сообщение от xpoince
Посмотреть сообщение

да и вообще если вспомните что писали @

Правильно ли понимаю, что @ — сокрытие критической ошибки в месте установки @?



0



0 / 0 / 0

Регистрация: 11.01.2016

Сообщений: 5

12.01.2016, 19:28

 [ТС]

8

xpoince, я изначально и формулировал суть задачи:

Цитата
Сообщение от Vagrant
Посмотреть сообщение

сохранить текущее состояние->от ключить уровень E_NOTICE->собственно парсинг->вернуть изначальное состояние

а «@» делает какраз то что нужно.

n0n4m3r, да, «@» заставляет php игнорировать любые ошибки в выражениях. Выражение, как я понял, является единственно-правильным местом его использования.



0



* xdebug isn't built into the nightly PHP, so we'll get an error if we try to remove it; nightly should also be allow failures untilany identified issues are resolved

* <>/!=

* Update to versions of complex and matrix libraries

* Set formula attribute in the Xlsx reader

* Calculation/DateTime Failure With PHP8 (#1661)

The following code generates an error with PHP8:
  if ($t1[1] > 29) {
    $t1[1] += 1900;

Under the "right" conditions, PHP8 evaluates the condition as true
when PHP8 is a non-numeric string and then generates an error trying
to perform += on that non-numeric string. Adding a numeric test
eliminates the problem. All unit tests involving this code now
succeed with both PHP7 and PHP8.

* Update to versions of complex and matrix libraries

* Reader/Gnumeric Failure with PHP8 (#1662)

* Reader/Gnumeric Failure with PHP8

An explicit cast from SimpleXML to int is now needed with PHP8,
where it was performed implicitly with PHP7.
Unit tests run correctly for both PHP7 and PHP8 on corrected code.

* ReverseSort bug, exposed but not caused by PHP8 (#1660)

Some tests of ReferenceHelper functions columnReverseSort and
cellReverseSort which passed with PHP7 fail with PHP8.
Both functions use the following construction:
  return 1 - strcasecmp(whatever);
The "1" seems very mysterious. I believe that the correct code should be:
  return -strcasecmp(whatever);
It appears in particular that PHP7 strcasecmp was never returning a
value of 1 for the tests in question, but PHP8 strcasecmp does so.
With the corrected code, the tests pass in both PHP7 and PHP8.

* Drop $this->spreadSheet null check from Xlsx Writer (#1646)

$this->spreadSheet cannot be null

* Update index.md (#1620)

* Bug setting Superscript/Subscript to false (#1567)

If font style Superscript is set to true, Subscript is set to false.
Likewise, setting Subscript to true sets Superscript to false.
Both of these are working as they should. However,
setting Superscript to false causes Subscript to be set to true,
and setting Subscript to false causes Superscript to be set to true.
I believe that is an error in both cases. This change fixes it.

There seem to be no existing tests for Font styles.
I added the tests necessary to validate this change.
I will put adding more on my to-do list.

* Update CHANGELOG

* Sync README

* Separate compoer.json for PHP8 to enforce phpunit ^9.3

* We don't want the composer lock file for PHP8

* Work with existing composer file; but force a fresh install to require new dependency versions

* Allow failures on nightly

* Allow failures on nightly fails if we remove it from the grid

* fixed php8 deprecation warning for libxml_disable_entity_loader() (#1625)

* fixed php8 deprecation warning for libxml_disable_entity_loader()

* Use ZipArchive methods as zip_* functions are deprecated in PHP8

* Remove tests that include tcPDF and DomPDF libraries when running against PHP8, because neither library is yet PHP8-ready

* Let's try to figure out why we're having an issue with a temp csv file

* Need to add `application/csv` to the list of valid CSV mime types

* Locale-specific float to string is changed in PHP as per https://wiki.php.net/rfc/locale_independent_float_to_string

* Codestyle clean-ups

* Switch from using poser badges to shields.io because poser wasn't picking up the correct license

* Update composer suggestions

* Introduce GitHub Actions

The plan is to keep Travis for a short while, until we are confident that
GitHub Actions work well enough for us. And after that we can remove Travis
entirely.

There is a bunch of duplicated things but it allows us to maximize
parallelismt to have results as soon as possible.

API documentation generation is still missing.

* Annotate problems in code

* Publish API docs via GitHub Actions

* Update composer suggestions

* Test PHP 8 on GitHub Actions

* Improving Coverage for Excel2003 XML Reader (#1557)

* Improving Coverage for Excel2003 XML Reader

Reader/Xml is now 100% covered.

File templates/Excel2003XMLTest.xml, used in some tests, is *not*
readable by a current version of Excel. I have substituted a new file
excel2003.xml to be used in its place. I have not deleted the original
in case someone in future (possibly me) wants to see what it needs to
make it usable.

There are minimal code changes.
- Unused protected functions pixel2WidthUnits and widthUnits2Pixel
  are deleted.
- One regex looking to convert hex characters is changed from a-z to a-f,
  and made case insensitive.
- No calculation performed for "error" cell (previously calculation
  was attempted and threw exception).
- Empty relative row/cell is now handled correctly.
- Style applied to empty cell when appropriate.
- Support added for textRotation.
- Support added for border styles.
- Support added for diagonal borders.
- Support added for superscript and subscript.
- Support added for fill patterns.

In theory, encodings other than UTF-8 were supported.
In fact, I was unable to get SecurityScanner to pass *any* xml which is
not UTF-8. Eliminating the assumption that strings might not be UTF-8
allowed much of the code to be greatly simplified.
After that, I added some code that would permit the use of
some ASCII-compatible encodings (there is a test of ISO-8859-1).
It would be more difficult to handle other encodings (such as UTF-16).
I am not convinced that even the ISO-8859 effort is worth it,
but am willing to investigate either expanding or eliminating
non-UTF8 support.

I added a number of tests, creating an Xml directory, and moving
XmlTest to that directory.

Pull Request had problems reading old invalid sample in the code
coverage phase, not in any of the other test phases, and not in
the code coverage phase on my local machine.
As it turns out, aside from being invalid, the sample
is much larger than any of the other samples. Tests have been
adjusted accordingly.

* Smaller Test File

Should eliminate need to avoid test during xml coverage.

* Break Up Style Test into Multiple Tests

Per suggestion from Mark Baker.

* Integrate AddressHelper Change

The introduction of AddressHelper introduced a conflict which needed to
be resolved. I wanted to test it locally before resolving. This required
me to add (unchanged) AddressHelper to my local copy. I hope this is
an okay manner of resolving the conflict.

* Weird Travis Error

XmlOddTest works just fine on my local machine, but Travis failed it.
Even worse, the lines which Travis flags don't even make any sense
(one was the empty line between two methods!).
This test is not essential to the rest of the change. I am removing
it from the package, and will attempt to re-add it when I have a chance
to sync up my fork with the main project.

* Update CHANGELOG

* 1.15.0

* Remove coverage from Travis

Coverage data were not correctly uploaded for a long time now, and it
now is uploaded via GitHub Actions

* Prepare for next version

* Ensure that the list of shared formulae is maintained while chunk-reading Xlsx Files (#1680)

* Ensure that the list of shared formulae is maintained while chunk-reading Xlsx files

* Prevent notice during accessing "cached magnification factor" offset

Sheet View Settings Block should be 8-14 bytes long in BIFF8 Excel 97 according
to the open office file format documentation. However access to byte 10 and 12 is
not possible when record data is malformed, so getUInt2d throws notice.

* Refresh lock files

* Add exportArray Method for Styles (#1580)

Issue #580 has gone stale since I started work on this.
Nevertheless, this implements an exportArray function as an
exact counterpart of applyFromArry.
I chose the name exportArray to avoid confusion with the existing
method getStyleArray, which does something completely different.

This change also increases coverage for all the Style classes to 100%,
with the exception of Style.php itself. There were several (unchanged)
places in Style.php where I did not have sufficient understanding of
what was supposed to be happening, so could not create tests.

All properties used by applyFromArray are exported by this method.
Note that conditional styles are not covered; this is consistent
with the fact that they are not covered by applyFromArray.

The method is implemented as a final public function in Style/Supervisor,
which calls abstract protected function exportArray1, which is implemented
in each of the subclasses, and which calls final protected
function exportArray2 in Style/Supervisor.
So exportArray is usable for any of the subclasses as well.

The new method is added to the documentation.
The existing documentation for applyFromArray was alphabetized to make
it easier to follow.
One property (Style quotePrefix) was added to the documentation.
Some Borders pseudo-properties (vertical, horizontal, and outline) were
documented as usable by applyFromArray,
but aren't actually supported - they were removed.
The documentation of the properties seemed to use setProperty and
getProperty fairly randomly - it now uses setProperty exclusively.

New constants were added for the textRotation "angles" used to create a
"stacked" cell. I felt that changing the readers and writers to use
these constants was beyond the scope of this change, but it is
on my to-do list.

* Updating a misspelling of a function name. (#1695)

This will update the function name DCOUNTA from the misspelling of DCOUNT.

* Make DefinedNames Samples Consistent With Other Samples (#1707)

All other Samples write to temporary directory. DefinedNames samples
write to main directory, which (a) means they aren't stored with others,
and (b) they aren't ignored by git so look like changed files.
The tests are also simplified by requiring Header rather than Bootstrap,
making use of Helper.

* Resolve XSS Vulnerability in the HTML Writer (#1719)

Resolve XSS Vulnerability in the HTML Writer

* Drop Travis

* Automatic GitHub releases from git tags

* Improve Coverage in src/PhpSpreadsheet

There are no changes to code. Additional tests are added,
so that the following 6 items now have 100% test coverage:
- Comment
- DefinedName
- DocumentGenerator
- IOFactory
- NamedFormula
- NamedRange

* Changes for Scrutinizer

Two changes to fix minor problems reported by Scrutinizer.

* Spelling: Tou -> You

* Fix for 1735 (Incorrect activeSheetIndex after RemoveSheetByIndex) (#1743)

This is a fix for issue #1735.
It adds tests for this situation, and similar situations involving
adding new sheets and accessing existing ones.
Coverage for Spreadsheet.php increases from 69% to 75% as a result.

* Update change log

* Fix for 3 Issues Involving ReadXlsx and NamedRange (#1742)

* Fix for 3 Issues Involving ReadXlsx and NamedRange

Issues #1686 and #1723, which provide sample spreadsheets, are probably
solved by this ticket. Issue #1730 is also probably solved, but I have
no way to verify.

There are two problems with how PhpSpreadsheet is handling things now.
Although the first problem is much less severe, and isn't really a factor
in the issues named above, it is helpful to get it out of the way first.
If you define a named range in Excel, and then delete the sheet where
the range exists, Excel saves the range as #REF!. If there is a cell which
references the range, it will similarly have the value #REF! when you open
the Excel file.
Currently, PhpSpreadsheet discards the #REF! definition, so a cell which
references the range will appear as #NAME? rather than #REF!.
This PR changes the behavior so that PhpSpreadsheet retains the #REF!
definition, and cells which reference it will appear as #REF!.

The second problem is the more severe, and is, I believe, responsible
for the 3 issues identified above.
If you define a named range and the sheet on which the range is defined
does not exist at the time, Excel will save the range as something like:

'[1]Unknown Sheet'!$A$1

If a cell references such a range, Excel will again display #REF!.
PhpSpreadsheet currently throws an Exception when it encounters
such a definition while reading the file. This PR changes
the behavior so that PhpSpreadsheet saves the definition as #REF!,
and cells which reference it will behave similarly.

For the record, I will note that Excel does not magically recalculate when a
missing sheet is subsequently added, despite the fact that the reference
might now become resolvable. PhpSpreadsheet behaves likewise.

* Remove Dead Code in Test

Identified it after push but before merge.

* Update change log

* Apply Column and Row Styles to Existing Cells (#1721)

* Apply Column and Row Styles to Existing Cells

This is a fix for issue #1712.
When a style is applied to an entire row or column, it is currently
only effective for cells which don't already contain a value.
The code needs to iterate through existing cells in the row/column
in order to apply the style to them.
This could be considered a breaking change, however, I believe that
the change makes things operate as users would expect, and that the
existing implementation is incomplete.

The change also removes protected element conditionalStyles from
the Style class. That element is an unused remnant, and can no longer be
set or retrieved - methods getConditionalStyles and setConditionalStyles
actually act on an element in the Worksheet class.

Finally, additional tests are added so that Style, and in fact the
entire Style directory, now has 100% test coverage.

* Scrutinizer Changes

Scrutinizer flagged 6 statements. 5 can be easily corrected.
One is absolutely wrong (it thinks iterating through cells in column
can return null). Let's see if we can satisfy it.

* Remove Exception For CellIterator on Empty Row/Column

For my first attempt at this change, which corrects a bug by updating styles
for non-empty cells when a style is set on a row or column, I wished to make things
more efficient by using setIterateOnlyExistingCells, something which the
existing documentation recommends. This caused an exception to be generated
when the row or column is empty. So I removed that part of the change while I
researched what was going on.

I have completed that research. The existing code does throw an exception
when the row/column is empty and iterateOnlyExistingCells is true. However,
that does not seem like a reasonable action. This situation is analagous to
iterating over an empty array, and that action is legal and does not throw.
The same should apply here. There were no tests for this situation,
and now there are.

I have added additional tests, and coverage for all of RowCellIterator,
ColumnCellIterator, and CellIterator are all now 100%. Some of my new tests
were added in new members, because the existing tests all relied on mocking,
which was not the best choice for the new tests. One of the existing tests
for RowCellIteratorTest (testSeekOutOfRange) was wrong; it issued the expected
exception, but for the wrong reason. I have added an additional test to
ensure that it fails "correctly".

The existing documentation says that the default value for
IterateOnlyExistingCells is true. In fact, the default value is false.
I have corrected the documentation.

* More Scrutinizer

I believe its analysis is incorrect, but this should silence it.

* DocBlock Correction

ColumnCellIterator DocBlock for current indicated it could return null
or Cell, but it can really return only Cell. This had caused Scrutinizer
to complain earlier.

* PHP8 Environment Appears to be Fixed

Cosmetic change to Doc member. I suspect there is a way to rerun all
the tests without another push, but I have been unable to figure out how.

* Update change log

* TextData Coverage and Minor Bug Fixes (#1744)

This had been intended to get 100% coverage for TextData functions, and it does that.
However, some minor bugs requiring source changes arose during testing.
- the Excel CHAR function restricts its argument to 1-255. PhpSpreadsheet CHARACTER
  had been allowing 0+. Also, there is no need to test if iconv exists,
  since it is part of Composer requirements.
- The DOLLAR function had been returning NUM for invalid arguments. Excel returns VALUE.
  Also, negative amounts were not being handled correctly.
- The FIXEDFORMAT function had been returning NUM for invalid arguments. Excel FIXED returns VALUE.

* Replace anti-xss with html purifier (#1751)

* Replace voku/anti-xss with ezyang/htmlpurifier. Despite anti-xss being a smaller footprint dependency, an a better license fit with our MIT license, there are issues with it's automatic it sanitisation of global variables causing side effects
* Additional unit tests for xss in html writer cell comments

* Fix bug #1626 where values of 0 were "rounded" up/down as if they were not 0 (#1627)

* Fix bug where values of 0 were "rounded" up/down as if they were not 0

* Update change log

* Fix for #1612 - SLK Long File Name (#1706)

Issue has been marked stale, but ...
Sylk read sets worksheet title to filename (minus .slk).
If that is >31 characters, PhpSpreadsheet throws Exception.
This change truncates sheet title, as Excel does, to 31 characters.

* Update change log

* worksheet: fix if cellValue does not exist (#1727)

The condition is FALSE if the cell does not exist in the flipped table,
but anyway, it is sent in to a method requiring 'string' type, causing
it to fail.

* fixes #1655 issue (#1656)

Resolve problem with incorrectly defined hyperlinks

* Add 'ps' suffix to printer settings resources IDs (#1690)

* Add 'ps' suffix to printer settings resources IDs

* Update change log

* Fix pixelsToPoints conversion (for HTML col width) (#1733)

* DocBlock Change in Styles/Conditional (#1697)

Scrutinizer reported a minor error in a test involving a module
which I was not changing.
Styles/Conditional function setConditions can take a scalar or an
array as a parameter, but DocBlock says it only expects array.
I did not wish to add the extra module to my PR, but made a note to
self to fix that after PR was installed.
That has now happened, and it makes for a good case for me
to see all the PHP8/Composer2/etc. changes that have happened recently.

* Merge pull request #1698

* Merge pull request #4 from PHPOffice/master

* Restore Omitted Read XML Test

* Fix for bug #1592 (UPDATED) (#1623)

* Fix for Xls when BIFF8 SST (FCh) has bad Shared string length

* Update change log

* Add nightly PHP 8.1 dev to github actions (#1763)

* Fix compatibility with ext-gd on php 8 (#1762)

* CSV - Guess Encoding, Handle Null-string Escape (#1717)

* CSV - Guess Encoding, Handle Null-string Escape

This is in response to issue #1647 (detect CSV character encoding).
First, my tests with mb_detect_encoding indicate that it doesn't work
well enough; regardless, users can always do that on their own
if they deem it useful.
Rolling my own is also troublesome, but I can at least:
a. Check for BOM (UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE).
b. Do some heuristic tests for each of the above encodings.
c. Fallback to a user-specified encoding (default CP1252)
  if a and b don't yield result.
I think this is probably useful enough to include, and relatively
easy to expand if other potential encodings should be considered.

Starting with PHP7.4, fgetcsv allows specification of null string as
escape character in fgetcsv. This is a much better choice than the PHP
(and PhpSpreadsheet) default of backslash in that it handles the file
in the same manner as Excel does. There is one statement in Reader/CSV
which would be adversely affected if the caller so specified (building
a regular expression under the assumption that escape character is
a single character). Fix that statement appropriately and add tests.

* Update changelog

* Update Units of Measure supported by the CONVERT() function (#1768)

Now supports all current UoM in all categories, with both 1- and 2-character multiplier prefixes, and binary multiplier prefixes, including the new Temperature scales

* Changelog for 1.16.0 release

* Fix date tests withut specified year for current year 2021 (#1774)

* Mrand of zero to any multiple should return 0 (#1773)

* Problems Using Builtin PHP Functions Directly As Excel Functions (#1799)

* Problems Using Builtin PHP Functions Directly As Excel Functions

This fixes issue #1789.
As originally reported, stricter typing was causing PHP8 to throw
an exception when a non-numeric value was passed to the Round function.
Previous releases of PHP did not see this problem, however, on further
analysis, they were also incorrect in returning 0 as the result in the
erroneous situation, when they should have been returning a VALUE error.
Yet more analysis showed that other functions would also have problems,
and, in addition, might not handle invalid input (e.g. a negative length
passed to REPT) or output (e.g. NAN in the case of ACOS(2)) correctly.

The following MathTrig functions are affected:
ABS, ACOS, ACOSH, ASIN, ASINH, ATAN, ATANH,
COS, COSH, DEGREES (rad2deg), EXP, LN (log), LOG10,
RADIANS (deg2rad), REPT (str_repeat), SIN, SINH, SQRT, TAN, TANH.
One TextData function (REPT) is also affected.

This change lets PhpSpreadsheet validate the input for each of these
functions before passing control to the builtin, and handle the output
afterwards.

There were no explicit tests for any of these functions, a fact made
easy to ignore by the fact that PhpSpreadsheet delegated the heavy
lifting to PHP itself for these cases. A full suite of tests is
now added for each of the affected functions.

* Scrutinizer Recommendations

Only in 3 modules which are part of this PR.

* Improved Handling of Tan(PI/2)

Return DIV0 error for TAN when COS is very small.

* Additional Trig Tests

Results which should be infinity, i.e. DIV/0 error.

* Delete Temporary Files In XssVulnerabilityTest (#1800)

* Delete Temporary Files In XssVulnerabilityTest

They need not exist after the test. Some of them are placed in
current directory, which means Git thinks they are needed.

* Update Changelog for switch from built-in PHP functions to Excel class methods (to handle typechecking for stricter PHP8 typing)

* Fix For #1772 Null Exception on ODS Read (#1776)

Fix for #1772.
Header and Footer Properties may be omitted in Page Setting Style Set.
Code changed to allow for this possibility, and tests added.

* Additional method call/return typing

* Update Changelog

* PHPCS Resolutions

* Fix Xlsx reader overriding manually set number format with builtin number format (#1805)

* Update Changelog

* Named formula fix for empty formula value

* Do not swallow previous exception (#1778)

The previous exception will be included when loading the content as DOM Document fails. This makes debugging the reason behind the failure much easier.

* Support DataBar of conditional formatting rule (#1754)

Implemented the databar of Conditional Type for XLSX Files.
- DataBar can be read, written, and added for basic use.
- Supports reading, writing and adding using "extLst".

About "extLst"
- https://docs.microsoft.com/en-us/openspecs/office_standards/ms-xlsx/07d607af-5618-4ca2-b683-6a78dc0d9627

The following setting items on the Excel setting screen can be read, written, and added.
- (minimum, maximum)type: Automatic, LowestValue, Number, Percent, Formula, Percentile
- Direction: context, leftToRight, rightToLeft (show data bar only)
- Fills Solid, Gradient
- FillColor: PositiveValues, NegativeValues
- Borders: Solid, None
- BorderColor: PositiveValues, NegativeValues
- Axis position: Automatic, Midpoint, None
- Axis color

* formatAsDate strip language metadata (#1618)

* Revert "Fix cant get right format chinese date format error"

This reverts commit 8c58385d6c103d23f6a5b3d1899a5e7cc8f66e92.

* formatAsDate strip language metadata (fixes #1616)

Co-authored-by: Mark Baker <mark@lange.demon.co.uk>

* Additional method call/return typing

* Composer fixes

* PHPCS Fixes

* Additional unit tests for statistical functions, with a fix to ordering for RANK() (#1813)

* Additional unit tests for statistical functions, with a fix to ordering for RANK()

* Unhappy path unit tests (#1814)

* Unhappy path unit tests

* Fix unhappy error for BETADIST and BETAINV min/max range

* Additional unit tests for previously untested financial functions (#1815)

* Additional unit tests for previously untested financial functions, and some additions to follow untested paths
* Start splitting Financial function tests out from the large FinancialTests class into individual test classes for each function

* Extract remaining Excel function unit tests into separate test classes for each function (#1817)

* Extract remaining Financial function unit tests into separate test classes for each function

This makes it easier to manage unit tests if they are individual files rather than all in a single file

It also provides a stepping stone toward making it easier to test Excel functions when Excel errors no longer return a string, but an actual Excel exception that can be handled more cleanly

* Additional statistical unit tests (#1818)

* Inherited Scrutinizer Recommendations - 1 of 3 (#1806)

* Make DefinedNames Samples Consistent With Other Samples (#1707)

All other Samples write to temporary directory. DefinedNames samples
write to main directory, which (a) means they aren't stored with others,
and (b) they aren't ignored by git so look like changed files.
The tests are also simplified by requiring Header rather than Bootstrap,
making use of Helper.

* Resolve XSS Vulnerability in the HTML Writer (#1719)

Resolve XSS Vulnerability in the HTML Writer

* Drop Travis

* Automatic GitHub releases from git tags

* Improve Coverage in src/PhpSpreadsheet

There are no changes to code. Additional tests are added,
so that the following 6 items now have 100% test coverage:
- Comment
- DefinedName
- DocumentGenerator
- IOFactory
- NamedFormula
- NamedRange

* Changes for Scrutinizer

Two changes to fix minor problems reported by Scrutinizer.

* Spelling: Tou -> You

* Fix for 1735 (Incorrect activeSheetIndex after RemoveSheetByIndex) (#1743)

This is a fix for issue #1735.
It adds tests for this situation, and similar situations involving
adding new sheets and accessing existing ones.
Coverage for Spreadsheet.php increases from 69% to 75% as a result.

* Update change log

* Fix for 3 Issues Involving ReadXlsx and NamedRange (#1742)

* Fix for 3 Issues Involving ReadXlsx and NamedRange

Issues #1686 and #1723, which provide sample spreadsheets, are probably
solved by this ticket. Issue #1730 is also probably solved, but I have
no way to verify.

There are two problems with how PhpSpreadsheet is handling things now.
Although the first problem is much less severe, and isn't really a factor
in the issues named above, it is helpful to get it out of the way first.
If you define a named range in Excel, and then delete the sheet where
the range exists, Excel saves the range as #REF!. If there is a cell which
references the range, it will similarly have the value #REF! when you open
the Excel file.
Currently, PhpSpreadsheet discards the #REF! definition, so a cell which
references the range will appear as #NAME? rather than #REF!.
This PR changes the behavior so that PhpSpreadsheet retains the #REF!
definition, and cells which reference it will appear as #REF!.

The second problem is the more severe, and is, I believe, responsible
for the 3 issues identified above.
If you define a named range and the sheet on which the range is defined
does not exist at the time, Excel will save the range as something like:

'[1]Unknown Sheet'!$A$1

If a cell references such a range, Excel will again display #REF!.
PhpSpreadsheet currently throws an Exception when it encounters
such a definition while reading the file. This PR changes
the behavior so that PhpSpreadsheet saves the definition as #REF!,
and cells which reference it will behave similarly.

For the record, I will note that Excel does not magically recalculate when a
missing sheet is subsequently added, despite the fact that the reference
might now become resolvable. PhpSpreadsheet behaves likewise.

* Remove Dead Code in Test

Identified it after push but before merge.

* Update change log

* Apply Column and Row Styles to Existing Cells (#1721)

* Apply Column and Row Styles to Existing Cells

This is a fix for issue #1712.
When a style is applied to an entire row or column, it is currently
only effective for cells which don't already contain a value.
The code needs to iterate through existing cells in the row/column
in order to apply the style to them.
This could be considered a breaking change, however, I believe that
the change makes things operate as users would expect, and that the
existing implementation is incomplete.

The change also removes protected element conditionalStyles from
the Style class. That element is an unused remnant, and can no longer be
set or retrieved - methods getConditionalStyles and setConditionalStyles
actually act on an element in the Worksheet class.

Finally, additional tests are added so that Style, and in fact the
entire Style directory, now has 100% test coverage.

* Scrutinizer Changes

Scrutinizer flagged 6 statements. 5 can be easily corrected.
One is absolutely wrong (it thinks iterating through cells in column
can return null). Let's see if we can satisfy it.

* Remove Exception For CellIterator on Empty Row/Column

For my first attempt at this change, which corrects a bug by updating styles
for non-empty cells when a style is set on a row or column, I wished to make things
more efficient by using setIterateOnlyExistingCells, something which the
existing documentation recommends. This caused an exception to be generated
when the row or column is empty. So I removed that part of the change while I
researched what was going on.

I have completed that research. The existing code does throw an exception
when the row/column is empty and iterateOnlyExistingCells is true. However,
that does not seem like a reasonable action. This situation is analagous to
iterating over an empty array, and that action is legal and does not throw.
The same should apply here. There were no tests for this situation,
and now there are.

I have added additional tests, and coverage for all of RowCellIterator,
ColumnCellIterator, and CellIterator are all now 100%. Some of my new tests
were added in new members, because the existing tests all relied on mocking,
which was not the best choice for the new tests. One of the existing tests
for RowCellIteratorTest (testSeekOutOfRange) was wrong; it issued the expected
exception, but for the wrong reason. I have added an additional test to
ensure that it fails "correctly".

The existing documentation says that the default value for
IterateOnlyExistingCells is true. In fact, the default value is false.
I have corrected the documentation.

* More Scrutinizer

I believe its analysis is incorrect, but this should silence it.

* DocBlock Correction

ColumnCellIterator DocBlock for current indicated it could return null
or Cell, but it can really return only Cell. This had caused Scrutinizer
to complain earlier.

* PHP8 Environment Appears to be Fixed

Cosmetic change to Doc member. I suspect there is a way to rerun all
the tests without another push, but I have been unable to figure out how.

* Update change log

* TextData Coverage and Minor Bug Fixes (#1744)

This had been intended to get 100% coverage for TextData functions, and it does that.
However, some minor bugs requiring source changes arose during testing.
- the Excel CHAR function restricts its argument to 1-255. PhpSpreadsheet CHARACTER
  had been allowing 0+. Also, there is no need to test if iconv exists,
  since it is part of Composer requirements.
- The DOLLAR function had been returning NUM for invalid arguments. Excel returns VALUE.
  Also, negative amounts were not being handled correctly.
- The FIXEDFORMAT function had been returning NUM for invalid arguments. Excel FIXED returns VALUE.

* Replace anti-xss with html purifier (#1751)

* Replace voku/anti-xss with ezyang/htmlpurifier. Despite anti-xss being a smaller footprint dependency, an a better license fit with our MIT license, there are issues with it's automatic it sanitisation of global variables causing side effects
* Additional unit tests for xss in html writer cell comments

* Fix bug #1626 where values of 0 were "rounded" up/down as if they were not 0 (#1627)

* Fix bug where values of 0 were "rounded" up/down as if they were not 0

* Update change log

* Fix for #1612 - SLK Long File Name (#1706)

Issue has been marked stale, but ...
Sylk read sets worksheet title to filename (minus .slk).
If that is >31 characters, PhpSpreadsheet throws Exception.
This change truncates sheet title, as Excel does, to 31 characters.

* Update change log

* worksheet: fix if cellValue does not exist (#1727)

The condition is FALSE if the cell does not exist in the flipped table,
but anyway, it is sent in to a method requiring 'string' type, causing
it to fail.

* fixes #1655 issue (#1656)

Resolve problem with incorrectly defined hyperlinks

* Add 'ps' suffix to printer settings resources IDs (#1690)

* Add 'ps' suffix to printer settings resources IDs

* Update change log

* Fix pixelsToPoints conversion (for HTML col width) (#1733)

* DocBlock Change in Styles/Conditional (#1697)

Scrutinizer reported a minor error in a test involving a module
which I was not changing.
Styles/Conditional function setConditions can take a scalar or an
array as a parameter, but DocBlock says it only expects array.
I did not wish to add the extra module to my PR, but made a note to
self to fix that after PR was installed.
That has now happened, and it makes for a good case for me
to see all the PHP8/Composer2/etc. changes that have happened recently.

* Merge pull request #1698

* Merge pull request #4 from PHPOffice/master

* Restore Omitted Read XML Test

* Fix for bug #1592 (UPDATED) (#1623)

* Fix for Xls when BIFF8 SST (FCh) has bad Shared string length

* Update change log

* Add nightly PHP 8.1 dev to github actions (#1763)

* Fix compatibility with ext-gd on php 8 (#1762)

* CSV - Guess Encoding, Handle Null-string Escape (#1717)

* CSV - Guess Encoding, Handle Null-string Escape

This is in response to issue #1647 (detect CSV character encoding).
First, my tests with mb_detect_encoding indicate that it doesn't work
well enough; regardless, users can always do that on their own
if they deem it useful.
Rolling my own is also troublesome, but I can at least:
a. Check for BOM (UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE).
b. Do some heuristic tests for each of the above encodings.
c. Fallback to a user-specified encoding (default CP1252)
  if a and b don't yield result.
I think this is probably useful enough to include, and relatively
easy to expand if other potential encodings should be considered.

Starting with PHP7.4, fgetcsv allows specification of null string as
escape character in fgetcsv. This is a much better choice than the PHP
(and PhpSpreadsheet) default of backslash in that it handles the file
in the same manner as Excel does. There is one statement in Reader/CSV
which would be adversely affected if the caller so specified (building
a regular expression under the assumption that escape character is
a single character). Fix that statement appropriately and add tests.

* Update changelog

* Update Units of Measure supported by the CONVERT() function (#1768)

Now supports all current UoM in all categories, with both 1- and 2-character multiplier prefixes, and binary multiplier prefixes, including the new Temperature scales

* Changelog for 1.16.0 release

* Fix date tests withut specified year for current year 2021 (#1774)

* Mrand of zero to any multiple should return 0 (#1773)

* WIP Inherited Scrutinizer Recommendations - 1 of 3

I tried to sync my fork with the main project, as I have done several times before.
However, the GitHub interface to do this had changed, and it appears that I
did not make the optimal selection when I had a choice. Consequently, all
the merges that happened to base between the last time I synchronized and this time
appear to be part of any PR that I push. "Files changed" remains correct for
my new PRs, but there appear to be many more commits involved than is actually the
case. I will, at some point, delete and re-create my fork, and pay much closer
attention in future when I want to sync my fork with the main project.

Because of this set-up, Scrutinizer reports flaws in code that I haven't
actually changed in my PRs #1799 and #1800.
It still passes them, but, as long as I'm aware of the problems,
I may as well attempt to correct them. The following are not part of those PRs:
- 5 problems spread over 4 different members
- 12 problems in Calculation/Engineering
- 15 problems in Reader/XML

I shall attempt to resolve these via 3 separate PRs,
of which this is the first.

* Try Hyperlink Again

Scrutinizer still didn't like it as fixed.

* Another Crack at Hyperlink

This should work.

Co-authored-by: Mark Baker <mark@lange.demon.co.uk>
Co-authored-by: Adrien Crivelli <adrien.crivelli@gmail.com>
Co-authored-by: Ryan McAllen <rhyno@rhynodesigns.com>
Co-authored-by: Flinsch <220455+Flinsch@users.noreply.github.com>
Co-authored-by: Jan Sverre Riksfjord <jasverix@gmail.com>
Co-authored-by: Max Kalyabin <maksim@kalyabin.ru>
Co-authored-by: Sébastien Despont <sebastien.despont@gmail.com>
Co-authored-by: Guilliam Xavier <guilliamxavier@users.noreply.github.com>
Co-authored-by: Gianluca Giovinazzo <g.giovinazzo@gmail.com>
Co-authored-by: Alexander M. Turek <me@derrabus.de>
Co-authored-by: Martins Sipenko <martins.sipenko@gmail.com>

* Inherited Scrutinizer Recommendations - 2 of 3 (#1807)

* Make DefinedNames Samples Consistent With Other Samples (#1707)

All other Samples write to temporary directory. DefinedNames samples
write to main directory, which (a) means they aren't stored with others,
and (b) they aren't ignored by git so look like changed files.
The tests are also simplified by requiring Header rather than Bootstrap,
making use of Helper.

* Resolve XSS Vulnerability in the HTML Writer (#1719)

Resolve XSS Vulnerability in the HTML Writer

* Drop Travis

* Automatic GitHub releases from git tags

* Improve Coverage in src/PhpSpreadsheet

There are no changes to code. Additional tests are added,
so that the following 6 items now have 100% test coverage:
- Comment
- DefinedName
- DocumentGenerator
- IOFactory
- NamedFormula
- NamedRange

* Changes for Scrutinizer

Two changes to fix minor problems reported by Scrutinizer.

* Spelling: Tou -> You

* Fix for 1735 (Incorrect activeSheetIndex after RemoveSheetByIndex) (#1743)

This is a fix for issue #1735.
It adds tests for this situation, and similar situations involving
adding new sheets and accessing existing ones.
Coverage for Spreadsheet.php increases from 69% to 75% as a result.

* Update change log

* Fix for 3 Issues Involving ReadXlsx and NamedRange (#1742)

* Fix for 3 Issues Involving ReadXlsx and NamedRange

Issues #1686 and #1723, which provide sample spreadsheets, are probably
solved by this ticket. Issue #1730 is also probably solved, but I have
no way to verify.

There are two problems with how PhpSpreadsheet is handling things now.
Although the first problem is much less severe, and isn't really a factor
in the issues named above, it is helpful to get it out of the way first.
If you define a named range in Excel, and then delete the sheet where
the range exists, Excel saves the range as #REF!. If there is a cell which
references the range, it will similarly have the value #REF! when you open
the Excel file.
Currently, PhpSpreadsheet discards the #REF! definition, so a cell which
references the range will appear as #NAME? rather than #REF!.
This PR changes the behavior so that PhpSpreadsheet retains the #REF!
definition, and cells which reference it will appear as #REF!.

The second problem is the more severe, and is, I believe, responsible
for the 3 issues identified above.
If you define a named range and the sheet on which the range is defined
does not exist at the time, Excel will save the range as something like:

'[1]Unknown Sheet'!$A$1

If a cell references such a range, Excel will again display #REF!.
PhpSpreadsheet currently throws an Exception when it encounters
such a definition while reading the file. This PR changes
the behavior so that PhpSpreadsheet saves the definition as #REF!,
and cells which reference it will behave similarly.

For the record, I will note that Excel does not magically recalculate when a
missing sheet is subsequently added, despite the fact that the reference
might now become resolvable. PhpSpreadsheet behaves likewise.

* Remove Dead Code in Test

Identified it after push but before merge.

* Update change log

* Apply Column and Row Styles to Existing Cells (#1721)

* Apply Column and Row Styles to Existing Cells

This is a fix for issue #1712.
When a style is applied to an entire row or column, it is currently
only effective for cells which don't already contain a value.
The code needs to iterate through existing cells in the row/column
in order to apply the style to them.
This could be considered a breaking change, however, I believe that
the change makes things operate as users would expect, and that the
existing implementation is incomplete.

The change also removes protected element conditionalStyles from
the Style class. That element is an unused remnant, and can no longer be
set or retrieved - methods getConditionalStyles and setConditionalStyles
actually act on an element in the Worksheet class.

Finally, additional tests are added so that Style, and in fact the
entire Style directory, now has 100% test coverage.

* Scrutinizer Changes

Scrutinizer flagged 6 statements. 5 can be easily corrected.
One is absolutely wrong (it thinks iterating through cells in column
can return null). Let's see if we can satisfy it.

* Remove Exception For CellIterator on Empty Row/Column

For my first attempt at this change, which corrects a bug by updating styles
for non-empty cells when a style is set on a row or column, I wished to make things
more efficient by using setIterateOnlyExistingCells, something which the
existing documentation recommends. This caused an exception to be generated
when the row or column is empty. So I removed that part of the change while I
researched what was going on.

I have completed that research. The existing code does throw an exception
when the row/column is empty and iterateOnlyExistingCells is true. However,
that does not seem like a reasonable action. This situation is analagous to
iterating over an empty array, and that action is legal and does not throw.
The same should apply here. There were no tests for this situation,
and now there are.

I have added additional tests, and coverage for all of RowCellIterator,
ColumnCellIterator, and CellIterator are all now 100%. Some of my new tests
were added in new members, because the existing tests all relied on mocking,
which was not the best choice for the new tests. One of the existing tests
for RowCellIteratorTest (testSeekOutOfRange) was wrong; it issued the expected
exception, but for the wrong reason. I have added an additional test to
ensure that it fails "correctly".

The existing documentation says that the default value for
IterateOnlyExistingCells is true. In fact, the default value is false.
I have corrected the documentation.

* More Scrutinizer

I believe its analysis is incorrect, but this should silence it.

* DocBlock Correction

ColumnCellIterator DocBlock for current indicated it could return null
or Cell, but it can really return only Cell. This had caused Scrutinizer
to complain earlier.

* PHP8 Environment Appears to be Fixed

Cosmetic change to Doc member. I suspect there is a way to rerun all
the tests without another push, but I have been unable to figure out how.

* Update change log

* TextData Coverage and Minor Bug Fixes (#1744)

This had been intended to get 100% coverage for TextData functions, and it does that.
However, some minor bugs requiring source changes arose during testing.
- the Excel CHAR function restricts its argument to 1-255. PhpSpreadsheet CHARACTER
  had been allowing 0+. Also, there is no need to test if iconv exists,
  since it is part of Composer requirements.
- The DOLLAR function had been returning NUM for invalid arguments. Excel returns VALUE.
  Also, negative amounts were not being handled correctly.
- The FIXEDFORMAT function had been returning NUM for invalid arguments. Excel FIXED returns VALUE.

* Replace anti-xss with html purifier (#1751)

* Replace voku/anti-xss with ezyang/htmlpurifier. Despite anti-xss being a smaller footprint dependency, an a better license fit with our MIT license, there are issues with it's automatic it sanitisation of global variables causing side effects
* Additional unit tests for xss in html writer cell comments

* Fix bug #1626 where values of 0 were "rounded" up/down as if they were not 0 (#1627)

* Fix bug where values of 0 were "rounded" up/down as if they were not 0

* Update change log

* Fix for #1612 - SLK Long File Name (#1706)

Issue has been marked stale, but ...
Sylk read sets worksheet title to filename (minus .slk).
If that is >31 characters, PhpSpreadsheet throws Exception.
This change truncates sheet title, as Excel does, to 31 characters.

* Update change log

* worksheet: fix if cellValue does not exist (#1727)

The condition is FALSE if the cell does not exist in the flipped table,
but anyway, it is sent in to a method requiring 'string' type, causing
it to fail.

* fixes #1655 issue (#1656)

Resolve problem with incorrectly defined hyperlinks

* Add 'ps' suffix to printer settings resources IDs (#1690)

* Add 'ps' suffix to printer settings resources IDs

* Update change log

* Fix pixelsToPoints conversion (for HTML col width) (#1733)

* DocBlock Change in Styles/Conditional (#1697)

Scrutinizer reported a minor error in a test involving a module
which I was not changing.
Styles/Conditional function setConditions can take a scalar or an
array as a parameter, but DocBlock says it only expects array.
I did not wish to add the extra module to my PR, but made a note to
self to fix that after PR was installed.
That has now happened, and it makes for a good case for me
to see all the PHP8/Composer2/etc. changes that have happened recently.

* Merge pull request #1698

* Merge pull request #4 from PHPOffice/master

* Restore Omitted Read XML Test

* Fix for bug #1592 (UPDATED) (#1623)

* Fix for Xls when BIFF8 SST (FCh) has bad Shared string length

* Update change log

* Add nightly PHP 8.1 dev to github actions (#1763)

* Fix compatibility with ext-gd on php 8 (#1762)

* CSV - Guess Encoding, Handle Null-string Escape (#1717)

* CSV - Guess Encoding, Handle Null-string Escape

This is in response to issue #1647 (detect CSV character encoding).
First, my tests with mb_detect_encoding indicate that it doesn't work
well enough; regardless, users can always do that on their own
if they deem it useful.
Rolling my own is also troublesome, but I can at least:
a. Check for BOM (UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE).
b. Do some heuristic tests for each of the above encodings.
c. Fallback to a user-specified encoding (default CP1252)
  if a and b don't yield result.
I think this is probably useful enough to include, and relatively
easy to expand if other potential encodings should be considered.

Starting with PHP7.4, fgetcsv allows specification of null string as
escape character in fgetcsv. This is a much better choice than the PHP
(and PhpSpreadsheet) default of backslash in that it handles the file
in the same manner as Excel does. There is one statement in Reader/CSV
which would be adversely affected if the caller so specified (building
a regular expression under the assumption that escape character is
a single character). Fix that statement appropriately and add tests.

* Update changelog

* Update Units of Measure supported by the CONVERT() function (#1768)

Now supports all current UoM in all categories, with both 1- and 2-character multiplier prefixes, and binary multiplier prefixes, including the new Temperature scales

* Changelog for 1.16.0 release

* Fix date tests withut specified year for current year 2021 (#1774)

* Mrand of zero to any multiple should return 0 (#1773)

* Inherited Scrutinizer Recommendations - 2 of 3

I tried to sync my fork with the main project, as I have done several times before.
However, the GitHub interface to do this had changed, and it appears that I
did not make the optimal selection when I had a choice. Consequently, all
the merges that happened to base between the last time I synchronized and this time
appear to be part of any PR that I push. "Files changed" remains correct for
my new PRs, but there appear to be many more commits involved than is actually the
case. I will, at some point, delete and re-create my fork, and pay much closer
attention in future when I want to sync my fork with the main project.

Because of this set-up, Scrutinizer reports flaws in code that I haven't
actually changed in my PRs #1799 and #1800.
It still passes them, but, as long as I'm aware of the problems,
I may as well attempt to correct them. The following are not part of those PRs:
- 5 problems spread over 4 different members
- 12 problems in Calculation/Engineering
- 15 problems in Reader/XML

I shall attempt to resolve these via 3 separate PRs,
of which this is the second.

* Fixed Most of the Problems, But Some New Ones Cropped Up

Trying once more to satisfy Scrutinizer.

Co-authored-by: Mark Baker <mark@lange.demon.co.uk>
Co-authored-by: Adrien Crivelli <adrien.crivelli@gmail.com>
Co-authored-by: Ryan McAllen <rhyno@rhynodesigns.com>
Co-authored-by: Flinsch <220455+Flinsch@users.noreply.github.com>
Co-authored-by: Jan Sverre Riksfjord <jasverix@gmail.com>
Co-authored-by: Max Kalyabin <maksim@kalyabin.ru>
Co-authored-by: Sébastien Despont <sebastien.despont@gmail.com>
Co-authored-by: Guilliam Xavier <guilliamxavier@users.noreply.github.com>
Co-authored-by: Gianluca Giovinazzo <g.giovinazzo@gmail.com>
Co-authored-by: Alexander M. Turek <me@derrabus.de>
Co-authored-by: Martins Sipenko <martins.sipenko@gmail.com>

* Inherited Scrutinizer Recommendations - 3 of 3 (#1808)

* Make DefinedNames Samples Consistent With Other Samples (#1707)

All other Samples write to temporary directory. DefinedNames samples
write to main directory, which (a) means they aren't stored with others,
and (b) they aren't ignored by git so look like changed files.
The tests are also simplified by requiring Header rather than Bootstrap,
making use of Helper.

* Resolve XSS Vulnerability in the HTML Writer (#1719)

Resolve XSS Vulnerability in the HTML Writer

* Drop Travis

* Automatic GitHub releases from git tags

* Improve Coverage in src/PhpSpreadsheet

There are no changes to code. Additional tests are added,
so that the following 6 items now have 100% test coverage:
- Comment
- DefinedName
- DocumentGenerator
- IOFactory
- NamedFormula
- NamedRange

* Changes for Scrutinizer

Two changes to fix minor problems reported by Scrutinizer.

* Spelling: Tou -> You

* Fix for 1735 (Incorrect activeSheetIndex after RemoveSheetByIndex) (#1743)

This is a fix for issue #1735.
It adds tests for this situation, and similar situations involving
adding new sheets and accessing existing ones.
Coverage for Spreadsheet.php increases from 69% to 75% as a result.

* Update change log

* Fix for 3 Issues Involving ReadXlsx and NamedRange (#1742)

* Fix for 3 Issues Involving ReadXlsx and NamedRange

Issues #1686 and #1723, which provide sample spreadsheets, are probably
solved by this ticket. Issue #1730 is also probably solved, but I have
no way to verify.

There are two problems with how PhpSpreadsheet is handling things now.
Although the first problem is much less severe, and isn't really a factor
in the issues named above, it is helpful to get it out of the way first.
If you define a named range in Excel, and then delete the sheet where
the range exists, Excel saves the range as #REF!. If there is a cell which
references the range, it will similarly have the value #REF! when you open
the Excel file.
Currently, PhpSpreadsheet discards the #REF! definition, so a cell which
references the range will appear as #NAME? rather than #REF!.
This PR changes the behavior so that PhpSpreadsheet retains the #REF!
definition, and cells which reference it will appear as #REF!.

The second problem is the more severe, and is, I believe, responsible
for the 3 issues identified above.
If you define a named range and the sheet on which the range is defined
does not exist at the time, Excel will save the range as something like:

'[1]Unknown Sheet'!$A$1

If a cell references such a range, Excel will again display #REF!.
PhpSpreadsheet currently throws an Exception when it encounters
such a definition while reading the file. This PR changes
the behavior so that PhpSpreadsheet saves the definition as #REF!,
and cells which reference it will behave similarly.

For the record, I will note that Excel does not magically recalculate when a
missing sheet is subsequently added, despite the fact that the reference
might now become resolvable. PhpSpreadsheet behaves likewise.

* Remove Dead Code in Test

Identified it after push but before merge.

* Update change log

* Apply Column and Row Styles to Existing Cells (#1721)

* Apply Column and Row Styles to Existing Cells

This is a fix for issue #1712.
When a style is applied to an entire row or column, it is currently
only effective for cells which don't already contain a value.
The code needs to iterate through existing cells in the row/column
in order to apply the style to them.
This could be considered a breaking change, however, I believe that
the change makes things operate as users would expect, and that the
existing implementation is incomplete.

The change also removes protected element conditionalStyles from
the Style class. That element is an unused remnant, and can no longer be
set or retrieved - methods getConditionalStyles and setConditionalStyles
actually act on an element in the Worksheet class.

Finally, additional tests are added so that Style, and in fact the
entire Style directory, now has 100% test coverage.

* Scrutinizer Changes

Scrutinizer flagged 6 statements. 5 can be easily corrected.
One is absolutely wrong (it thinks iterating through cells in column
can return null). Let's see if we can satisfy it.

* Remove Exception For CellIterator on Empty Row/Column

For my first attempt at this change, which corrects a bug by updating styles
for non-empty cells when a style is set on a row or column, I wished to make things
more efficient by using setIterateOnlyExistingCells, something which the
existing documentation recommends. This caused an exception to be generated
when the row or column is empty. So I removed that part of the change while I
researched what was going on.

I have completed that research. The existing code does throw an exception
when the row/column is empty and iterateOnlyExistingCells is true. However,
that does not seem like a reasonable action. This situation is analagous to
iterating over an empty array, and that action is legal and does not throw.
The same should apply here. There were no tests for this situation,
and now there are.

I have added additional tests, and coverage for all of RowCellIterator,
ColumnCellIterator, and CellIterator are all now 100%. Some of my new tests
were added in new members, because the existing tests all relied on mocking,
which was not the best choice for the new tests. One of the existing tests
for RowCellIteratorTest (testSeekOutOfRange) was wrong; it issued the expected
exception, but for the wrong reason. I have added an additional test to
ensure that it fails "correctly".

The existing documentation says that the default value for
IterateOnlyExistingCells is true. In fact, the default value is false.
I have corrected the documentation.

* More Scrutinizer

I believe its analysis is incorrect, but this should silence it.

* DocBlock Correction

ColumnCellIterator DocBlock for current indicated it could return null
or Cell, but it can really return only Cell. This had caused Scrutinizer
to complain earlier.

* PHP8 Environment Appears to be Fixed

Cosmetic change to Doc member. I suspect there is a way to rerun all
the tests without another push, but I have been unable to figure out how.

* Update change log

* TextData Coverage and Minor Bug Fixes (#1744)

This had been intended to get 100% coverage for TextData functions, and it does that.
However, some minor bugs requiring source changes arose during testing.
- the Excel CHAR function restricts its argument to 1-255. PhpSpreadsheet CHARACTER
  had been allowing 0+. Also, there is no need to test if iconv exists,
  since it is part of Composer requirements.
- The DOLLAR function had been returning NUM for invalid arguments. Excel returns VALUE.
  Also, negative amounts were not being handled correctly.
- The FIXEDFORMAT function had been returning NUM for invalid arguments. Excel FIXED returns VALUE.

* Replace anti-xss with html purifier (#1751)

* Replace voku/anti-xss with ezyang/htmlpurifier. Despite anti-xss being a smaller footprint dependency, an a better license fit with our MIT license, there are issues with it's automatic it sanitisation of global variables causing side effects
* Additional unit tests for xss in html writer cell comments

* Fix bug #1626 where values of 0 were "rounded" up/down as if they were not 0 (#1627)

* Fix bug where values of 0 were "rounded" up/down as if they were not 0

* Update change log

* Fix for #1612 - SLK Long File Name (#1706)

Issue has been marked stale, but ...
Sylk read sets worksheet title to filename (minus .slk).
If that is >31 characters, PhpSpreadsheet throws Exception.
This change truncates sheet title, as Excel does, to 31 characters.

* Update change log

* worksheet: fix if cellValue does not exist (#1727)

The condition is FALSE if the cell does not exist in the flipped table,
but anyway, it is sent in to a method requiring 'string' type, causing
it to fail.

* fixes #1655 issue (#1656)

Resolve problem with incorrectly defined hyperlinks

* Add 'ps' suffix to printer settings resources IDs (#1690)

* Add 'ps' suffix to printer settings resources IDs

* Update change log

* Fix pixelsToPoints conversion (for HTML col width) (#1733)

* DocBlock Change in Styles/Conditional (#1697)

Scrutinizer reported a minor error in a test involving a module
which I was not changing.
Styles/Conditional function setConditions can take a scalar or an
array as a parameter, but DocBlock says it only expects array.
I did not wish to add the extra module to my PR, but made a note to
self to fix that after PR was installed.
That has now happened, and it makes for a good case for me
to see all the PHP8/Composer2/etc. changes that have happened recently.

* Merge pull request #1698

* Merge pull request #4 from PHPOffice/master

* Restore Omitted Read XML Test

* Fix for bug #1592 (UPDATED) (#1623)

* Fix for Xls when BIFF8 SST (FCh) has bad Shared string length

* Update change log

* Add nightly PHP 8.1 dev to github actions (#1763)

* Fix compatibility with ext-gd on php 8 (#1762)

* CSV - Guess Encoding, Handle Null-string Escape (#1717)

* CSV - Guess Encoding, Handle Null-string Escape

This is in response to issue #1647 (detect CSV character encoding).
First, my tests with mb_detect_encoding indicate that it doesn't work
well enough; regardless, users can always do that on their own
if they deem it useful.
Rolling my own is also troublesome, but I can at least:
a. Check for BOM (UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE).
b. Do some heuristic tests for each of the above encodings.
c. Fallback to a user-specified encoding (default CP1252)
  if a and b don't yield result.
I think this is probably useful enough to include, and relatively
easy to expand if other potential encodings should be considered.

Starting with PHP7.4, fgetcsv allows specification of null string as
escape character in fgetcsv. This is a much better choice than the PHP
(and PhpSpreadsheet) default of backslash in that it handles the file
in the same manner as Excel does. There is one statement in Reader/CSV
which would be adversely affected if the caller so specified (building
a regular expression under the assumption that escape character is
a single character). Fix that statement appropriately and add tests.

* Update changelog

* Update Units of Measure supported by the CONVERT() function (#1768)

Now supports all current UoM in all categories, with both 1- and 2-character multiplier prefixes, and binary multiplier prefixes, including the new Temperature scales

* Changelog for 1.16.0 release

* Fix date tests withut specified year for current year 2021 (#1774)

* Mrand of zero to any multiple should return 0 (#1773)

* Inherited Scrutinizer Recommendations - 3 of 3

I tried to sync my fork with the main project, as I have done several times before.
However, the GitHub interface to do this had changed, and it appears that I
did not make the optimal selection when I had a choice. Consequently, all
the merges that happened to base between the last time I synchronized and this time
appear to be part of any PR that I push. "Files changed" remains correct for
my new PRs, but there appear to be many more commits involved than is actually the
case. I will, at some point, delete and re-create my fork, and pay much closer
attention in future when I want to sync my fork with the main project.

Because of this set-up, Scrutinizer reports flaws in code that I haven't
actually changed in my PRs #1799 and #1800.
It still passes them, but, as long as I'm aware of the problems,
I may as well attempt to correct them. The following are not part of those PRs:
- 5 problems spread over 4 different members
- 12 problems in Calculation/Engineering
- 15 problems in Reader/XML

I shall attempt to resolve these via 3 separate PRs,
of which this is the third.

* The Usual

Fixed some Scrutinizer problems, some new ones popped up.

* More Scrutinizer

I think it's wrong in a lot of these cases. Although I am working
around all of them, I intend to file a bug report with them.

Co-authored-by: Mark Baker <mark@lange.demon.co.uk>
Co-authored-by: Adrien Crivelli <adrien.crivelli@gmail.com>
Co-authored-by: Ryan McAllen <rhyno@rhynodesigns.com>
Co-authored-by: Flinsch <220455+Flinsch@users.noreply.github.com>
Co-authored-by: Jan Sverre Riksfjord <jasverix@gmail.com>
Co-authored-by: Max Kalyabin <maksim@kalyabin.ru>
Co-authored-by: Sébastien Despont <sebastien.despont@gmail.com>
Co-authored-by: Guilliam Xavier <guilliamxavier@users.noreply.github.com>
Co-authored-by: Gianluca Giovinazzo <g.giovinazzo@gmail.com>
Co-authored-by: Alexander M. Turek <me@derrabus.de>
Co-authored-by: Martins Sipenko <martins.sipenko@gmail.com>

* Fix/1674 (#1688)

* Treat inline strings like strings in Open Document because it has no specific inline-string format

* implement data-type error

Co-authored-by: Mark Baker <mark@lange.demon.co.uk>

* Fixed reading XSLS style alignments from XML (#1710)

The attribute `$alignmentXml` given to the private method `readAlignmentStyle` is the alignment XML tag that contains the alignment data itself. But inside that method all data are read from another `alignment` XML tag within that given tag. This redundant child-node access resulted in the following error- / notice-message: `PHP Notice:  Trying to access array offset on value of type null in /foo/bar/baz/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php on line 146`

These changes remove the redundant child-node access in …

Общие предварительные проверки.


### Ничего не видно. Страница пустая и белая.

Это происходит, когда отчеты об ошибках отключены и произошла фатальная ошибка (часто синтаксическая ошибка). Если это происходит не на продакшн версии, а при разработке, то достаточно включить отображение ошибок. Как это сделать, написано тут:
Как и какими средствами находить ошибки в PHP коде — Сообщения об ошибках PHP. Если это продакшн версия, то ошибки обычно логируются в специальный файл. Как правило на Линукс системах лежит в папке /var/log/apache2
с названием «error.log» либо «название-сайта-error.log». Там можно найти конкретное сообщение об ошибке.


Просто напоминание: для проверки на корреткность логики кода, когда работает, но не так, как ожидалось, используйте отладку

### Код не запускается / Выводится код как он есть в PHP

Если не видно результата от PHP-кода и/или видно части PHP кода прямо на странице как они есть, значит PHP не выполняется. Если посмотреть в исходный код страницы в своем браузере (View Source),
то поскольку код PHP пишется в тегах <?php ?>, браузер попытается интерпретировать их как теги HTML и результат может выглядеть несколько запутанным.

Надо знать, чтобы запустить PHP-скрипты, необходимо:

  • веб-сервер, который выполняет скрипт

  • установить расширение файла на .php, иначе веб-сервер не будет интерпретировать его как таковой (Если вы его не перенастроите (всё можно перенастроить))

  • обращаться к файлу .php через веб-сервер! Если просто дважды кликнуть файл, он, скорее всего, откроется в браузере с таким адресом:

    file://C:/path/to/my/file.php
    

    Это полностью игнорирует любой запущенный веб-сервер, и файл не интерпретируется. Нужно «посетить» URL-адрес файла именно на веб-сервере. Примерно так:

    http://localhost/my/file.php
    

Напоминание: Если используете короткие открытые теги <? вместо <?php, надо проверить, что в конфигурации PHP (php.ini) включена опция short_open_tag = On

→ Ссылка

Автор решения: Алексей Шиманский

### Notice: Undefined variable

Происходит при попытке использовать переменную, которая ранее не была определена. То есть обращаетесь, например, к переменной $test, пишите if($test){ echo $actionMessage; },
а в коде выше её нет, либо она в другой области видимости (например за пределами анонимной функции)

$prefix = "Blueberry";
$food = ["cake", "cheese", "pie"];
$prefixedFood = array_map(function ($food) { // должно быть array_map(function ($food) use ($prefix) {
 // $prefix не определён, т.к. в другой области видимости                              ^^^^^^^^^^^^ надо передать в функцию
  return "${prefix} ${food}";
}, $food);

или определяется только в одной из веток if, а код попадает в другую

$a = 10;
if($a == 5) {
    $user_location = 'Paris';
} else {
}

echo $user_location;

и т.д. Смотрите наличие этой переменной выше по коду и в правильной области видимости!

### Notice: Undefined property

Эта ошибка означает то же, что выше, но относится к свойству объекта. Т.е. например обращение if($obj->test){ echo $actionMessage; }, при отсутствии свойства test в объекте вызовет ошибку.


### Warning: [function] expects parameter 1 to be resource, boolean given

Самая распространённая проблема mysql_fetch_array() expects parameter 1 to be resource (or mysqli_result), boolean given. См. ссылку для подробного описания.

Сама ошибка говорит о том, что в какую-либо из функций подали на вход переменную с типом boolean, а она ждала тип «ресурс».
Ресурс — это тип, такой же как строки, целые числа и пр.
Некоторые функции в PHP возвращают данный тип, например mysql_query, curl_init, fopen и многие другие (смотрите в документации, что возвращает функция).
Однако если функция отработала некорректно, то в качестве результата она может вернуть false (всё тот же fopen, например, или mysql_query). Поэтому надо проверять что вернула функция: boolean (по-сути, неудачу операции) или корректный дескриптор.

$fp = fopen(...);

if (!$fp) {
    trigger_error('Failed to allocate resource');
    exit;
}

$data = fread($fp, 1024);

### Warning: [function]: failed to open stream

Происходит, когда вызывается файл (обычно с помощью include, require или fopen). Частые варианты проблемы:

  • Файл не существует в принципе
  • Отсутствует даже сама папка
  • Путь до файла неверный
  • Путь до файла относительный (а указали абсолютный или неправильно рассчитан путь, не учтена вложенность и пр.)
  • Путь подключаемого файла (через include, require) неверный
  • Путь вроде похожий, но на самом деле там опечатки
  • Неправильные права на папку или файл (например 000 вместо 755)
  • Файлы в ПО компилируются и кэшируются. Путь поменялся, а кэш забыли сбросить

Одна из распространенных ошибок — не использовать абсолютный путь. Это можно легко решить, используя полный путь или магические константы, такие как __DIR__ или dirname (__ FILE__):

include __DIR__ . '/inc/globals.inc.php';

или

require dirname(__FILE__) . '/inc/globals.inc.php';

### Warning: Division by zero

Происходит деление на ноль. Это может быть не только потому, что в переменной-делителе 0, но и если в ней NULL. Самое простое это воспользоваться отладкой. и посмотреть почему в переменной не то значение, что ожидалось. Нужно переписать свое выражение так, чтобы проверить, что значение не равно 0. Также можно воспользоваться try/catch для отлова исключения и уведомления об этом пользователя, например.

$var1 = 0;
$var2 = 5;

try {
    $var3 = $var2 / $var1;
} catch (DivisionByZeroError $e) {
    echo 'Произошло деление на ноль!';
}

### Warning: Illegal string offset ‘XXX’ | Uncaught TypeError: Cannot access offset of type string on string (PHP 8.0)

Происходит при попытке получить доступ к элементу массива с синтаксисом квадратных скобок, но делаете это в строке, а не в массиве, поэтому операция явно не имеет смысла. Пример

$myString = "string";

// Ту всё ок
echo $myString[0]; // s
echo $myString[1]; // t
echo $myString[2]; // r
// ...

// !! Ошибка:
echo $myString['port'];
// !! Warning: Illegal string offset 'port' in ...

Если известно, что в переменной должен (обязан) быть массив — можно воспользоваться отладкой, чтобы отследить, почему в какой момент в переменной вместо массива значение меняется на строковое. Если не известно, прилетит ли массив или строка, но нужен массив, то можно воспользоваться проверками типа is_array (определяет, является ли переменная массивом), in_array (проверяет, присутствует ли в массиве значение), isset (определяет, была ли установлена переменная значением, отличным от null)

$string = "string";
$array = array('port' => 'the_port');

if (is_array($string) && isset($string['port'])) {
    // Всё отлично, мы никогда не попадём сюда
    echo $string['port'];
}

if (is_array($array) && isset($array['port'])) {
    // Ok!
    echo $array['port']; // the_port
}

if (is_array($array) && isset($array['unset_key'])) {
    // Всё отлично, мы никогда не попадём сюда
    echo $array['unset_key'];
}

// Аналогично вышенаписанному, но с применением array_key_exists
if (is_array($array) && array_key_exists('port', $array)) {
    // Ok!
    echo $array['port']; // the_port
}

### Warning: count(): Parameter must be an array or an object that implements Countable

Параметр, передаваемый в функцию count(), должен быть исчисляемым/то что можно посчитать. Обычно это массив.

Вероятная проблема заключается в том, что было передано скалярное значение, такое как строка или целое число, или объект, который не реализует интерфейс Countable. Использование var_dump() для рассматриваемой переменной может показать, так ли это.

→ Ссылка

Автор решения: Алексей Шиманский

### Fatal error: Call to a member function … on a non-object

Происходит обычно в случае xyz->method(), где xyz по какой-то причине не является объектом, как ожидалось, и, следовательно, этот method не может быть вызван.
Нужно убедиться, что объект на самом деле является объектом, прежде чем вызывать его методы. Т.е. в примере выше нужно быть уверенным,
что xyz — это объект, а не, например, null (наиболее часто встречается именно это) или false.

Как пример:

$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

В приведенном примере запрос не может быть подготовлен, и prepare() вернёт false. Как следствие будет происходить попутка вызвать метод execute() у булевого типа, а не у объекта.

Выясните, почему функция вернула логическое значение вместо объекта. Например, проверьте объект $pdo на предмет последней произошедшей ошибки. Подробности того, как отлаживать это, будут зависеть от того, как обрабатываются ошибки для конкретной рассматриваемой функции/объекта/класса. Чаще всего ошибка возникает потому, что в коде отсутствуют проверки на наличие ошибок.


Другая проблема может заключаться в условном создании объекта и последующей попытке вызвать метод вне этого условного блока. Например

if ($someCondition) {
    $myObj = new MyObj();
}
// ...
$myObj->someMethod();

Смотрите наличие этой переменной выше по коду и в правильной области видимости!


### Fatal error: Call to undefined function XXX

Происходит, когда происходит вызов функции, которая еще не определена. Распространенные причины: отсутствие расширений, неподключенный файл с функциями (через include/require), условное объявление функции (см. пример ниже), объявлении функции в функциях или просто из-за опечаток.

Условное объявление функции:

$someCondition = false;
if ($someCondition === true) {
    function fn() {
        return 1;
    }
}
echo fn(); // Ошибка, т.к. условие никогда не выполнится

Объявление функции в функции

function createFn() {
    function fn() {
        return 1;
    }
}
echo fn(); // Ошибка, т.к. другая область видимости

Примечание: последующие вызовы createFn() вызовут ошибку о повторном объявлении существующей функции.


Также можно увидеть эту ошибку для встроенной функции PHP. Можно попробовать найти функцию в официальном руководстве и проверить, к какому «расширению» (модулю PHP) оно принадлежит и какие версии PHP его поддерживают. В случае отсутствия расширения — нужно установить его и включить его в php.ini.

В случае, если функция находится в другом файле — не забудьте его подключить перед использованием функции

В случае опечатки — исправьте опечатку %)


### Fatal error: Cannot redeclare class [class name]

а также

### Fatal error: Cannot redeclare [function name]

Это означает, что вы либо дважды используете одно и то же имя функции/класса и нужно переименовать одну/один из них, либо это потому, что использовали require или include, где должны использовать require_once или include_once.

Когда класс или функция объявляются в PHP, они неизменяемы и не могут быть позже объявлены с новым значением.

Пример:

class.php

<?php

class MyClass {
    public function doSomething() { // что-то тут }
}

index.php

<?php

function doStuff() {
   require 'class.php';
   $obj = new MyClass;
   $obj->doSomething();
}

doStuff();
doStuff();

Второй вызов doStuff() вызовет указанную выше ошибку. Изменив require на require_once, мы можем быть уверены, что файл, содержащий определение MyClass, будет загружен только один раз, и ошибки можно будет избежать.


Не лишним будет использовать автозагрузку, и такие стандарты, как PSR-4 (стандарт по автозагрузке). или даже устаревший PSR-0, в значительной степени избавляют от необходимости использовать require/include самостоятельно (за исключением нескольких странных крайних случаев).

См. также Автозагрузка классов с помощью Composer., Автозагрузка классов с помощью Composer2, Автозагрузка классов с помощью Composer3


### Fatal error: Can’t use function return value in write context

Обычно это происходит при использовании функции напрямую с empty

if (empty(is_null(null))) {
    echo 'empty';
}

Это связано с тем, что empty — это языковая конструкция, а не функция. Её нельзя вызвать с выражением в качестве аргумента в версиях PHP до 5.5. До PHP 5.5 аргумент для empty() должен быть variable (то есть переменной), но в PHP 5.5+ допускается произвольное выражение (например, возвращаемое значение функции).

Не смотря на своё название, empty на самом деле не проверяет, является ли переменная «пустой». Она проверяет существует ли переменная или её значение равно false.
Выражения (такие как is_null (null) в примере) всегда будут считаться существующими, поэтому здесь empty только проверяет, равно ли оно false. Можно заменить здесь empty() на !, например

if (! is_null (null)) 

или явно сравнить с false, например

if (is_null (null) == false) 

→ Ссылка

Автор решения: Алексей Шиманский

### Fatal error: Declaration of AAA::BBB() must be compatible with that of CCC::BBB()

Происходит при наследовании (или использовании трейтов), когда в методе в классе наследнике сигнатура метода отличается от класса родителя.
Пример в базовом классе есть метод:

function test($arg1, $arg2 = null)

а в наследнике

function test($arg1, $arg2, $arg3 = null)

То есть уже три аргумента, вместо двух. Или типы аргументов поменялись (хотя бы у одного). Например у arg2 в первом случае был тип int, а во втором — string;


### Fatal error: Using $this when not in object context

$this — это специальная переменная в PHP, которой нельзя ничего присваивать.
Если к ней обращаются в контексте, где её не существует, выдается эта фатальная ошибка.

Возможные моменты возникновения:

  1. Если не статический метод вызывается из статического контекста. Пример:

     class Foo {
        protected $var;
        public function __construct($var) {
            $this->var = $var;
        }
    
        public static function bar () {
            // ^^^^^^
            echo $this->var;
            //   ^^^^^
        }
     }
    
     Foo::bar();
    

Как исправить: еще раз просмотрите свой код, $this может использоваться только в контексте объекта и никогда не должен использоваться в статическом методе. Кроме того, статический метод не должен обращаться к не статическому свойству. Используйте self::$static_property для доступа к статическому свойству.

  1. Если код из метода класса был скопирован в обычную функцию или куда-либо ещё вне метода и при этом забыли убрать слово $this.

Как исправить: Просмотрите код и замените $this другой переменной подстановки.


### Fatal error: Object of class Closure could not be converted to a string

Это означает, что вы не исполняете/не вызываете свою анонимную функцию (или замыкание), а пытаетесь отправить в поток вывода через echo/print/var_dump/и т.д. саму функцию, а не результат выполнения.

Примеры:

Стрелочная функция

$fn = fn($x = 42) => $x;
echo $fn; // <--- Должно было быть echo $fn()  т.е. необходимы круглые скобки

или анонимная функция:

echo function($x = 42) { return $x; }; // должно быть echo (function($x = 42) { return $x; })(2);

Чтобы устранить эту ошибку, необходимо выполнить функцию (как в примере выше echo $fn() вместо echo $fn или echo (function($x = 42) { return $x; })(30); вместо echo function($x = 42) { return $x; };.
Последний синтаксис называется IIFE (Immediately Invoked Function Expression — функция, которая выполняется сразу же после того, как она была определена.). Она была добавлена в PHP7


### Fatal error: Undefined class constant

Эта ошибка означает, что вы пытались использовать несуществующую константу класса. В отличие от других «неопределенных» уведомлений и предупреждений — это фатальная ошибка и скрипт немедленно останавливается.

В первую очередь следует проверить типографские ошибки. Опечатки, регистр. Нужно убедиться, что константа определена в классе и вызывается с использованием соответствующего пространства имен. Убедиться также, что все соответствующие файлы были подключены.


### Fatal error: Uncaught TypeError: some_function(): Argument #1 must be of type XXX, YYY given

В данном случае ошибка говорит о том, что код попытался вызвать some_function() и передал неправильный тип данных в качестве одного из аргументов. Например:

declare(strict_types=1);

function multiply(int $x, int $y) { 
    return $x * $y; 
}

echo multiply("3", 4);

Поскольку первый аргумент вызываемой функции имеет скалярный тип int, а вызов находится в файле, в котором включены строгие типы (stict_types = 1), при передаче ему тип «строка» возникает ошибка:

Fatal error: Uncaught TypeError: multiply(): Argument #1 ($x) must be of type integer, string given in…

Понятно, что нужно чинить, чтобы в функцию приходил верный тип.

→ Ссылка

Автор решения: Алексей Шиманский

### Notice: Array to string conversion

Происходит при попытки вывести массив как строку. Обычно это происходит, когда применяется функция echo к массиву или конкатенируется массив в строке.

$arr = array('foo', 'bar');    
echo $arr;  // Notice: Array to string conversion
$str = 'Something, ' . $arr;  // Notice: Array to string conversion

Массив не может быть просто выведен через echo или объединен со строкой, потому что результат не определен должным образом.
Вероятно, вы хотели сделать что-то вроде этого:

echo $arr[0];  // Выведет: foo
$str = 'Something ' . join(', ', $arr); // Выведет: Something, foo, bar

Или сделать цикл по массиву:

foreach($arr as $key => $value) {
    echo "array $key = $value";        
}

// Выведет: 
// array 0 = foo
// array 1 = bar

Если это уведомление появляется там, где не ожидаете, это означает, что переменная, которую вы считали строкой, на самом деле является массивом. Это означает, что в вашем коде есть ошибка, которая превращает эту переменную в массив вместо ожидаемой строки.


### Notice: Trying to get property of non-object error

Происходит при попытке обращения к свойству объекта, когда объекта нет.

Типичный пример:

$users = json_decode('[{"name": "hakre"}]');
echo $users->name; # Notice: Trying to get property of non-object

В примере выше $users является массивом (а не объектом) и не имеет никаких свойств. А вот элементы массива — объекты. И обращение $users[0]->name возымело бы эффект.

Это похоже на доступ к несуществующему индексу или ключу массива (см. Notice: Undefined Index).

Этот пример сильно упрощен. Чаще всего такое уведомление сигнализирует о непроверенном возвращаемом значении, например когда библиотека возвращает NULL, если объект не существует или просто неожиданное значение, которое не является объектом (например, в результате Xpath, структуры JSON с неожиданным форматом, XML с неожиданным форматом и т. д.), но код (точнее разработчик) не проверяет наличие такого состояния (что json,xml и пр. могут быть некорректными).

Поскольку эти не-объекты часто обрабатываются дальше, часто происходит фатальная ошибка при вызове метода этого объекта и возникает Fatal error: Call to a member function … on a non-object, которая останавливает работу скрипта в том числе.

Этого можно легко предотвратить, проверив условия ошибки и/или соответствие переменной ожидаемому. Пример DOMXPath:

$result  = $xpath->query("//*[@id='detail-sections']/div[1]");
$divText = $result->item(0)->nodeValue; # Notice: Trying to get property of non-object

Тут происходит попытка обратиться к свойству (полю) nodeValue первого элемента, хотя проверки на то, существует ли он в коллекции $result не было.
Вместо этого стоит сделать код более явным, назначив переменные объектам, с которыми работает код:

$result  = $xpath->query("//*[@id='detail-sections']/div[1]");
$div     = $result->item(0);
$divText = "-/-";

if (is_object($div)) {
    $divText = $div->nodeValue;
}

echo $divText;

→ Ссылка

Автор решения: Алексей Шиманский

### Notice: Undefined Index ( Undefined array key >= PHP8.0 )

а также

### Undefined offset

Происходит при попытке обратиться по ключу массива, которого нет в массиве.

Типичный пример:

$data = array('foo' => '42', 'bar');
echo $data['spinach']; // Undefined index: spinach
echo $data[1]; // Undefined offset: 1

И spinach и 1 не существуют и вызовут уведомление. Но немного разные. Undefined offset означает, что есть пустой ключ массива, происходит обращение по числовому индексу в массиве, которого нет.
Самый типичный пример:

$arr = array('Felix','Jon','Java');

// Будет "Undefined offset" т.к. нумерация начинается с 0, 
// и будут индексы 0,1,2, а обращение идёт к индексу 3    
echo $arr[3];

Нужно убедиться, что индекс или ключ существует как таковой или до доступа по нему.

Нужно исправить ошибку в программе, чтобы эти индексы действительно существовали, когда это ожидается.
Или нужно проверить, что существуют нужные индексы используя array_key_exists или empty.
Как пример

$data = array('foo' => '42', 'bar');

if (array_key_exists('spinach', $data)) {
    echo $data['spinach'];
} else {
    echo 'Нет ключа "spinach" в массиве';
}

Как пример ещё: preg_match если совпадений не найдено — $match вернёт пустой массив. Но если не проверить и думать, что там всегда будет значение, то можно увидеть эту ошибку

preg_match($regex,$content,$matches)
echo $matches[0]; Undefined offset: 0   так как совпадений не нашлось

### Notice: Uninitialized string offset: XXX

Ошибка возникает когда, скорее всего, идёт попытка перебрать в цикле строку по символам или найти значение в массиве с несуществующим ключом.

Пример, цикл по строке

$string = 'ABCD'; 
for ($i=0, $len = strlen($string); $i <= $len; $i++){
    echo "$string[$i] n"; 
}

// На выходе будет
A
B
C
D
Notice: Uninitialized string offset: 4 in XXX on line X

Будет показана ошибка потому, что длина строки — 4 символа, а цикл написан от 0 до 4 включительно, то есть 5 итераций.


### Notice: Use of undefined constant XXX — assumed ‘XXX’

или в >=PHP7.2:

### Warning: Use of undefined constant XXX — assumed ‘XXX’ (this will throw an Error in a future version of PHP)

Это уведомление появляется, когда в коде используется токен, который кажется константой, но константа с таким именем не определена.

Одна из наиболее частых причин появления этого уведомления — отсутствие кавычек в строке, используемой в качестве ключа ассоциативного массива:

// Неверно
echo $array[key];

// Верно
echo $array['key'];

Другой распространенной причиной является отсутствие перед именем переменной знака $ (доллар):

// Неверно
echo varName;

// Верно
echo $varName;

Или, возможно, неправильно написали какую-то другую константу или ключевое слово:

// Неверно
$foo = fasle;

// Верно
$foo = false;

Это также может быть признаком того, что необходимое расширение или библиотека PHP отсутствует, когда происходит попытка получить доступ к константе, определенной этой библиотекой.

→ Ссылка

Автор решения: Алексей Шиманский

### Strict Standards: Non-static method [<class>::<method>] should not be called statically

Происходит при попытке вызвать не статический метод в классе в таком форме, как если бы он был статическим. (А также при включенном флаге E_STRICT в настройках error_reporting())

Поясняющий пример:

class HTML {
   public function br() { // метод br НЕ статический!
      echo '<br>';
   }
}

HTML::br(); // <--- два двоеточия должны быть только для вызова статики!     
// или     
$html = new HTML();
$html::br(); // <--- два двоеточия должны быть только для вызова статики!

Конечно, можно избежать этой ошибки, не добавляя E_STRICT в `error_reporting(), например

 error_reporting (E_ALL & ~ E_STRICT);
 

Но лучше программировать правильно, чем не правильно!))

Решение состоит в том, чтобы определить вашу предполагаемую статическую функцию как фактическую статическую или или вызвать из контекста:

// решение 1
public static function br() {
    echo '<br>';
}

// решение 2
$html = new HTML();
$html->br();

Конечно нужно смотреть на свой контекст и, возможно, переписать класс под правильную логику и вызовы методов.


### Warning: function() expects parameter XXX to be boolean (or integer, string, etc) , YYY given

Если в функцию передается параметр неправильного типа, а PHP не может преобразовать его автоматически, выдается это предупреждение.
Это предупреждение указывает, какой параметр является проблемой и какой тип данных ожидается.

  • expects — ожидается
  • given — то, что подаётся на вход
  • parameter X — это какой по счёту параметр

Решение: измените указанный параметр на правильный тип данных. Пример:

echo substr(["foo"], 23);

Отобразится ошибка::

PHP Warning: substr() expects parameter 1 to be string, array given

Ожидается что в первый параметр дадут тип «строка», но в реале дан на вход — тип «массив».


### Deprecated: Array and string offset access syntax with curly braces is deprecated

До версии PHP 7.4.0 доступ к смещениям (offset) строк и элементам массива можно было получить с помощью фигурных скобок {}:

$string = 'abc';
echo $string{0};  // a

$array = [1, 2, 3];
echo $array{0};  // 1

С PHP 7.4.0 это устарело и отображает ошибку выше

Необходимо использовать квадратные скобки [] для доступа к строковым смещениям и элементам массива:

$string = 'abc';
echo $string[0];  // a

$array = [1, 2, 3];
echo $array[0];  // 1

→ Ссылка

  • Ошибка uniform 01 the division 2
  • Ошибка unexpected end of archive
  • Ошибка unicodeutf8 is not a member of qapplication
  • Ошибка unexpected character encountered while parsing value path line 0 position 0
  • Ошибка unhandled exception occurred see log for details dead air