Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PHP Warning: extract() expects parameter 1 to be array

998 views
Skip to first unread message

Alla

unread,
Aug 20, 2016, 12:15:16 PM8/20/16
to
Hello!

I have written a small file that extracts information from a txt file passed in as a command line
argument, and inserts all information, line by line, into sql table. When I run the program, I get
a warning:

PHP Warning: extract() expects parameter 1 to be array, boolean given in /home/ubuntu/workspace/pset8/bin/import on line 30
PHP Stack trace:
PHP 1. {main}() /path/to/file:0
PHP 2. extract() /path/to/file:30

Warning: extract() expects parameter 1 to be array, boolean given in /path/to/file on line 30

Call Stack:
0.0015 241368 1. {main}() /path/to/file:0
20.7551 334832 2. extract() /path/to/file:30

Line 30 is this one extract($new_entry);

I have checked the extract() function, and had some issues with it, which are now resolved
thanks to great help I received here. I have checked mysql connection, and it's fine.
Now, even though I get this warning, which I don't understand,
sql table is filled in with the data from txt file, and I don't get an error message at any of the passes
of the while loop.

Here is my code. I will be grateful for your help.

<?php
require(__DIR__ . "/../includes/config.php");

if($argc < 2)
echo "Please, provide a path to a file\n";
else
{
$file = $argv[1];

if(!file_exists($file))
echo "Sorry, there is no such file $file\n";
else if(!($open_file = fopen($file, "r")))
echo "Sorry, couldn't open $file\n";
else if(!is_readable($file))
echo "$file is not readable\n";
else if(filesize($file)==0)
echo "Seems there is not content in the file $file\n";

else
{
while(!feof($open_file))
{
$new_entry = fgetcsv($open_file, 0, "\t");
// var_dump($new_entry);

extract($new_entry);

$entry0 = $new_entry[0];
$entry1 = $new_entry[1];
$entry2 = $new_entry[2];
$entry3 = $new_entry[3];
$entry4 = $new_entry[4];
$entry5 = $new_entry[5];
$entry6 = $new_entry[6];
$entry7 = $new_entry[7];
$entry8 = $new_entry[8];
$entry9 = $new_entry[9];
$entry10 = $new_entry[10];
$entry11 = $new_entry[11];

//below is a customized query function from a library that is included by config.php

$row = query("INSERT INTO `places`(`country_code`, `postal_code`, `place_name`,
`admin_name1`,
`admin_code1`, `admin_name2`, `admin_code2`, `admin_name3`, `admin_code3`, `latitude`,
`longitude`,
`accuracy`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $entry0, $entry1, $entry2, $entry3, $entry4,
$entry5, $entry6, $entry7, $entry8, $entry9, $entry10, $entry11);

if($row < 1)
exit("Unable to extract data");
}
fclose($open_file);
}
}
?>
Thank you very much!

R.Wieser

unread,
Aug 20, 2016, 12:45:38 PM8/20/16
to
Alla,

> When I run the program, I get a warning:
>
> PHP Warning: extract() expects parameter 1 to be array, boolean
> given in /home/ubuntu/workspace/pset8/bin/import on line 30
...
> Line 30 is this one extract($new_entry);

And that "$new_entry" is the result of fgetcsv(), a few lines above it.

Looking at the docs to fgetcsv() I see that it indeed is capable of
returning a boolean, and does that in cases of an error or when encountering
an EOF.

In other words: its possible that fgetcsv() either has got a problem with
converting a read line OR the "while(!feof($open_file))" doesn't detect an
eof, but fgetcsv() does (could happen when the file "ends" with whitespace
before the real end is encountered).

What you need to do is to take that boolean seriously, and deal with it.
For example by first checking if the result value is actually False, and if
so check the file if an EOF is encountered.

If not you might have encountered a non-covertable line, and (possibly) need
to abort.

Hope that helps.

Regards,
Rudy Wieser


-- Origional message:
Alla <modelli...@gmail.com> schreef in berichtnieuws
2d416b5e-e923-4d44...@googlegroups.com...
> file://below is a customized query function from a library that

Alla

unread,
Aug 20, 2016, 1:16:36 PM8/20/16
to
Ruby, thank you very much. I have added the lines below to check what's causing
the issue:

else
{
$row_number = 0;
while(!feof($open_file))
{
$new_entry = fgetcsv($open_file, 0, "\t");
// var_dump($new_entry);
$row_number++;

if($new_entry == FALSE)
exit ("A problem reading data from the file; row number $row_number\n");
if($new_entry == NULL)
{
echo "The line $row_number doesn't contain any data\n";
continue;
}

extract($new_entry);
......
and I have found the problem - the last line in txt, i.e. 40796 line, is an empty one, it
contains no data, hence $new_entry is an empty string at that last while loop iteration -
nothing to extract().
Thank you very much for your help!

Christoph M. Becker

unread,
Aug 20, 2016, 1:28:01 PM8/20/16
to
On 20.08.2016 at 19:16, Alla wrote:

> Ruby, thank you very much. I have added the lines below to check what's causing
> the issue:
>
> else
> {
> $row_number = 0;
> while(!feof($open_file))
> {
> $new_entry = fgetcsv($open_file, 0, "\t");
> // var_dump($new_entry);
> $row_number++;
>
> if($new_entry == FALSE)

This tests doesn't work as you expect. Actually, it will be true for
$new_entry === NULL and all other values that convert to boolean false.

I suggest to read the "Comparison Operators" section in the PHP manual
(<http://php.net/manual/en/language.operators.comparison.php>) and also
the section on "Type Juggling"
(<http://php.net/manual/en/language.types.type-juggling.php>).

> exit ("A problem reading data from the file; row number $row_number\n");
> if($new_entry == NULL)
> {
> echo "The line $row_number doesn't contain any data\n";
> continue;
> }
>
> extract($new_entry);
> ......
> and I have found the problem - the last line in txt, i.e. 40796 line, is an empty one, it
> contains no data, hence $new_entry is an empty string at that last while loop iteration -
> nothing to extract().

Generally, I suggest to use a while loop as shown in the example #1 in
the PHP manual:
<http://php.net/manual/en/function.fgetcsv.php#refsect1-function.fgetcsv-examples>.

--
Christoph M. Becker

Alla

unread,
Aug 20, 2016, 1:59:04 PM8/20/16
to
Rudy! Please, please, forgive me for making typos in your name - I have done that two times
already; this is extremely shameful. Please, believe me that it was not due to lack of respect;
these are pure typos. I am truly sorry!

Alla

unread,
Aug 20, 2016, 2:00:13 PM8/20/16
to
Christoph,
Thank you very much! I will follow your advice.

Christoph M. Becker

unread,
Aug 20, 2016, 2:15:44 PM8/20/16
to
On 20.08.2016 at 19:21, Tim Streater wrote:

> In article <2d416b5e-e923-4d44...@googlegroups.com>,
> Alla <modelli...@gmail.com> wrote:
>
>> $new_entry = fgetcsv($open_file, 0, "\t");
>
> Why are you not checking that fgetcsv didn't return a boolean?
>
> I could also ask why your program is such a convoluted if/then/else
> mess but I can't be bothered.

Alla is learning. No one is born a master. :-)

--
Christoph M. Becker

R.Wieser

unread,
Aug 20, 2016, 3:02:56 PM8/20/16
to
Alla,

> Ruby, thank you very much. I have added the lines below
> to check what's causing the issue:
...
> and I have found the problem - the last line in txt, i.e. 40796 line,
> is an empty one, it contains no data, hence $new_entry is an empty
> string at that last while loop iteration - nothing to extract().

I already expected as much (have run into the same problem myself), but
couldn't be sure. Glad you found it.

A remark at the code snippets Christoph posted a link to though: none of the
examples seem to check what caused the fgetcsv() function to return a False.
It could be an EOL, but it could be as well be a parsing or other error ...

You really should check, otherwise you could accept a partially processed
input file (with a problem on the last-read line) as fully done. Not good.
:-|
Don't worry about it, I already was assuming you just made a mistake. I'm
just glad you noticed it. :-)

Regards,
Rudy Wieser


-- Origional message:
Alla <modelli...@gmail.com> schreef in berichtnieuws
6ee0e256-b008-4d76...@googlegroups.com...

R.Wieser

unread,
Aug 20, 2016, 3:24:04 PM8/20/16
to
Christoph,

> Alla is learning. No one is born a master. :-)

True that. And if we're lucky we will be novices many times again before
we EOL.

I have to say that Tim made a good first remark. Its always good to check
the result of whatever you call if it doen't work as expected.

A shame that he followed that up with a put-down though. It seems he has
forgotten his own novice days.

But he just kills any positive vibe by that "can't be bothered" there. :-(

Regards,
Rudy Wieser


Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
npa6ob$q4u$1...@solani.org...

Alla

unread,
Aug 21, 2016, 1:39:15 AM8/21/16
to
Christoph and Rudy, Thank you very much!
As to Tim's message, which I can see only as a quotation here, I am fine with
all criticism, even harsh one, but if it contains correct remarks, as Tim's message
does, - it is also very helpful in learning. And I do agree
about the "convoluted mess"; I am struggling with this issue,
including in my C coding experience. I am in the processes, hopefully a successful
one eventually :)

Jerry Stuckle

unread,
Aug 21, 2016, 10:10:38 AM8/21/16
to
On 8/21/2016 5:26 AM, Tim Streater wrote:
> In article <18d88f90-6b3b-4e2f...@googlegroups.com>,
> Alla <modelli...@gmail.com> wrote:
>
>> On Saturday, August 20, 2016 at 9:15:44 PM UTC+3, Christoph M. Becker
>> wrote:
>>> On 20.08.2016 at 19:21, Tim Streater wrote:
>>>
>>> > In article <2d416b5e-e923-4d44...@googlegroups.com>,
>>> > Alla <modelli...@gmail.com> wrote:
>>> > >> $new_entry = fgetcsv($open_file, 0, "\t");
>>> > > Why are you not checking that fgetcsv didn't return a boolean?
>>> > > I could also ask why your program is such a convoluted if/then/else
>>> > mess but I can't be bothered.
>>>
>>> Alla is learning. No one is born a master. :-)
>
>> Christoph and Rudy, Thank you very much!
>> As to Tim's message, which I can see only as a quotation here, I am
>> fine with all criticism, even harsh one, but if it contains correct
>> remarks, as Tim's
>> message does, - it is also very helpful in learning. And I do agree
>> about the "convoluted mess"; I am struggling with this issue,
>> including in my C coding experience. I am in the processes, hopefully
>> a successful
>> one eventually :)
>
> There was a time around 1980 when computer science students were
> apparently being told that single-entry-single-exit was the way to
> write functions and procedures. This approach was assisted by the fact
> that Pascal didn't even have a return statement.
>
> I've always found this approach to be foolish as it increases
> complexity for no benefit, and on the one occasion when I was forced to
> write a substantial piece of code in Pascal, I used to systematically
> put a 999: label at the end of the function, to which I could GOTO when
> needed.
>

Tim,

It's still be espounded by some C programmers, but none I have seen that
I would consider competent (from other things they also say).

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

Ben Bacarisse

unread,
Aug 21, 2016, 11:55:36 AM8/21/16
to
Tim Streater <timst...@greenbee.net> writes:

> In article <18d88f90-6b3b-4e2f...@googlegroups.com>,
> Alla <modelli...@gmail.com> wrote:
>
>>On Saturday, August 20, 2016 at 9:15:44 PM UTC+3, Christoph M. Becker wrote:
>>> On 20.08.2016 at 19:21, Tim Streater wrote:
>>>
>>> > In article <2d416b5e-e923-4d44...@googlegroups.com>,
>>> > Alla <modelli...@gmail.com> wrote:
>>> > >> $new_entry = fgetcsv($open_file, 0, "\t");
>>> > > Why are you not checking that fgetcsv didn't return a boolean?
>>> > > I could also ask why your program is such a convoluted
>>> if/then/else
>>> > mess but I can't be bothered.
>>>
>>> Alla is learning. No one is born a master. :-)
>
>>Christoph and Rudy, Thank you very much!
>> As to Tim's message, which I can see only as a quotation here, I am
>> fine with all criticism, even harsh one, but if it contains correct
>> remarks, as Tim's
>> message does, - it is also very helpful in learning. And I do agree
>>about the "convoluted mess"; I am struggling with this issue,
>>including in my C coding experience. I am in the processes, hopefully
>> a successful
>>one eventually :)
>
> There was a time around 1980 when computer science students were
> apparently being told that single-entry-single-exit was the way to
> write functions and procedures. This approach was assisted by the fact
> that Pascal didn't even have a return statement.
>
> I've always found this approach to be foolish as it increases
> complexity for no benefit,

No benefit (in all cases) is a little strong. In some situation it can
be useful. For example when you have very limited debug facilities
being able to add print or logging call in one place can be helpful.
The problem comes from it being made a rule, with no thought put into
what the costs might be compared to any benefits.

<snip>
> In my view, you should be doing thus:
>
> // Start with all tests for conditions that prevent the program being
> run
>
> if ($argc<2)
> {
> echo "Please, provide a path to a file\n";
> exit ()
> }
>
> if (!file_exists($file))
> {
> echo "Sorry, there is no such file $file\n";
> exit ()
> }
>
> if (!is_readable($file))
> {
> echo "$file is not readable\n";
> exit ()
> }
>
> // other tests etc, then finally:
>
> $open_file = fopen($file, "r");
> if ($open_file===false)
> {
> echo "Sorry, couldn't open $file\n";
> exit ();
> }
>
> // Now comes the real meat of the program
>
> while (...)
> {
>
> // Main work is here
>
> }

Generally a good plan, but in this case I prefer the "more structured"
version:

if ($argc < 2)
echo "Please, provide a path to a file\n";
else if (!file_exists($file))
echo "Sorry, there is no such file $file\n";
else if (!is_readable($file))
echo "$file is not readable\n";
...
else if (($open_file = fopen($file, "r")) === false)
echo "Sorry, couldn't open $file\n";
else {
// All ok. Let's get on with it...

while (...)
{
// Main work is here
}
}

Obviously put the {} back if your style rules require them.

(You probably did this only for the purposes example, but since many
people might see this, I'd point out that it's usually better just to
try to open a file. Testing for specific problem before hand is going
to work 99.9999% of the time, but it introduces a race condition that
is, to my mind, inelegant.)

<snip>
--
Ben.

Thomas 'PointedEars' Lahn

unread,
Aug 22, 2016, 3:34:23 PM8/22/16
to
Ben Bacarisse wrote:

> […] I prefer the "more structured" version:
>
> if ($argc < 2)
> echo "Please, provide a path to a file\n";
> else if (!file_exists($file))
> echo "Sorry, there is no such file $file\n";
> else if (!is_readable($file))
> echo "$file is not readable\n";
> ...
> else if (($open_file = fopen($file, "r")) === false)
> echo "Sorry, couldn't open $file\n";
> else {
> // All ok. Let's get on with it...
>
> while (...)
> {
> // Main work is here
> }
> }

This code style is a maintenance nightmare (the missing blocks and the
assignment in the “if” statement doubly so). Do you know what the condition
on line 50 was because of which you wrote “else” on line 100?

Also, PHP is influenced by C, but it is _not_ C. The function should throw
(PHP Standard Library) exceptions like \InvalidArgumentException instead of
echo-ing error conditions without regard to the user’s locale. This will
also get them a stack trace (even better if the Xdebug extension is
installed and enabled) if they do not catch the exception. As a result, the
then-unnecessary “else” statements would vanish in a puff of program logic.

<http://php.net/manual/en/language.exceptions.php>

--
PointedEars
Zend Certified PHP Engineer
<http://www.zend.com/en/yellow-pages/ZEND024953> | Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

Jerry Stuckle

unread,
Aug 22, 2016, 7:13:53 PM8/22/16
to
On 8/22/2016 3:34 PM, the troll Thomas 'Pointed Head' Lahn wrote:
> Ben Bacarisse wrote:
>
>> […] I prefer the "more structured" version:
>>
>> if ($argc < 2)
>> echo "Please, provide a path to a file\n";
>> else if (!file_exists($file))
>> echo "Sorry, there is no such file $file\n";
>> else if (!is_readable($file))
>> echo "$file is not readable\n";
>> ...
>> else if (($open_file = fopen($file, "r")) === false)
>> echo "Sorry, couldn't open $file\n";
>> else {
>> // All ok. Let's get on with it...
>>
>> while (...)
>> {
>> // Main work is here
>> }
>> }
>
> This code style is a maintenance nightmare (the missing blocks and the
> assignment in the “if” statement doubly so). Do you know what the condition
> on line 50 was because of which you wrote “else” on line 100?
>

Yes - if the code is properly indented and commented (something you
wouldn't understand).

> Also, PHP is influenced by C, but it is _not_ C. The function should throw
> (PHP Standard Library) exceptions like \InvalidArgumentException instead of
> echo-ing error conditions without regard to the user’s locale. This will
> also get them a stack trace (even better if the Xdebug extension is
> installed and enabled) if they do not catch the exception. As a result, the
> then-unnecessary “else” statements would vanish in a puff of program logic.
>

Which would display to a user internal details of your code - a huge
security exposure. But you don't understand security, either, do you?

In addition, it will immediately stop processing of the page - resulting
in invalid HTML being sent to the browser. Something else you don't
care about, either.

> <http://php.net/manual/en/language.exceptions.php>
>

Glad you can cut/paste a URL. Too bad you don't understand how write
good PHP code.

Matthew Carter

unread,
Aug 23, 2016, 1:26:39 AM8/23/16
to
Details of stack traces are only exposed if the environment
(production?) is configured to match that of a developer environment
(such as showing errors vs logging them).

It is also quite easy to wrap your outer-most layer of code input/output
in a try/catch block and handle:

- Rendering a generic or descriptive error message for the user in the
catch block

- Manually logging the stack trace (part of the \Exception object) to a
file or sending as part of an email to the webmaster (if this is not
configurable in the php.ini of the server for some reason)

- Ensuring the HTML the user receives is still valid

This also allows for easier to extend code in the future, as you end up
with a single exit point.

--
Matthew Carter (m...@ahungry.com)
http://ahungry.com

Jerry Stuckle

unread,
Aug 23, 2016, 8:08:47 AM8/23/16
to
You obviously didn't read Pointed Head's post, did you?
0 new messages