PHP works in browser but not in cron :/

So basically…

viewed.php → includes checklogin.inc.php
checklogin.inc.php → includes functions.inc.php

As you might have guessed, within functions.inc.php there are various functions :stuck_out_tongue:

One of which is this…

// Function to strip down to links
function striplinks($document) {
    preg_match_all("'<\s*a\s.*?href\s*=\s*			# find <a href=
        ([\"\'])?					# find single or double quote
        (?(1) (.*?)\\1 | ([^\s\>]+))		# if quote found, match up to next matching
        # quote, otherwise match up to next space
        'isx", $document, $links);

    while (list($key, $val) = each($links[2])) {
        if (!empty($val))
            $match[] = $val;
    }

    while (list($key, $val) = each($links[3])) {
        if (!empty($val))
            $match[] = $val;
    }

    return $match;
}

When I run viewed.php from the browser, the scripts executed fine without error and does what it is supposed to do. However, when I run the script from cron, as it will be, then I get this:

PHP Notice: Undefined variable: match in /bla/bla/functions.inc.php on line 79

Can’t work it out at all :confused:

The variable $match is only in scope within each of those while loops.
If you define $match before the first while it will exist for the return.


I have not coded in PHP for many, many years. But I recall (with bruises to testify) that scope in this language was ALWAYS counter to the norm [found in most other languages].

That solution did not work.

I don’t understand why it runs fine from the browser but not cli :frowning:

I even have other pages using the same function from cron and it works fine.

There’s a couple things going on here that might be leading to your confusion.

First off, what you’re seeing is just a php notice indicating that the script will continue as expected but there is an opportunity to make the code better. The reason for this in your situation is that you haven’t defined the $match variable prior to attempting to use it. When PHP encounters an uninitialized variable, it will trigger the notice you are seeing, then instantiate the variable setting it’s datatype to an appropriate one based on the context in which it was found (in this case, as an array). If you want to get rid of the notice, you could simply modify your function to instantiate the $match variable prior to it being used:

function striplinks($document) {
    $match = array();
    preg_match_all(...);
    [...]
}

Secondly, the reason you are seeing it when executing the script from a terminal and not in the browser likely has to do with a php.ini setting (display_errors) having a different value. I know many linux distributions provide 2 different php.ini files, one intended for the web server and another for terminal execution. For instance, on an Ubuntu server, the php.ini file for the web server is found at /etc/php5/apache2/php.ini while the php.ini file for the terminal is found at /etc/php5/cli/php.ini. In addition, if there is a file named php.ini in the directory where php is executing, those values will overwrite the settings for the environmental php.ini. The setting for the web server php is probably configured to not display errors, while the cli php might be so.

You can easily override these settings in the appropriate php.ini file, or in your execution you can make a run time change to them using the ini_set function, though you should use caution when changing settings in this manner in a live environment to help prevent security holes.

You are correctly and I have since added $match = array(); which fixed the error notice but didn’t fix the underlying issue.

I traced the whole thing back to curl. When I was executing my scripts through the browser, curl was logging into a site and extracting links. However when executing via cron, curl wasn’t logging in which gave no data, therefore the function’s results were blank.

This was all down to the cookie path, which is now apparent needs to be the FULL path if executing through cli/cron.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.