0

I am trying to read a file ($txtFile) line-by-line. Then store the different items in the line ($line) separated by comma in an array ($pieces). The code is given below.

 <?php
    include_once __DIR__.'/connect.php';

    function createURL($ticker)
    {
        $currentPeriod = time(); 
        return "https://query1.finance.yahoo.com/v7/finance/download/$ticker?period1=1538917807&period2=1541596207&interval=1d&events=history&crumb=6DH0b71wPwr";
    }

    function getCSVFile($url, $outputFile)
    {
        $content = file_get_contents($url);
        $content = str_replace("Date,Open,High,Low,Close,Adj Close,Volume", "", $content);
        $content = trim($content);
        file_put_contents($outputFile, $content);
    }

    function fileToDatabase($txtFile, $tableName)
    {
        $file = fopen($txtFile, "r");
        while (!feof($file)) {
            $line = fgets($file);
            $pieces = explode(",", $line);
            print_r($pieces);
            $date = $pieces[0];
            $open = $pieces[1];
            $high = $pieces[2];
            $low = $pieces[3];
            $close = $pieces[4];
            $adj_close = $pieces[5];
            $volume = $pieces[6];
            $amount_change = $adj_close-$open;
            $percent_change = ($amount_change/$open)*100;
            $sql = "SELECT * FROM $tableName";
            $result = $conn->query($sql);

            if (!$result) {
                $createQuery = "CREATE TABLE $tableName (
                    date TIMESTAMP PRIMARY KEY,
                    open FLOAT,
                    high FLOAT,
                    low FLOAT,
                    close FLOAT,
                    adj_close FLOAT,
                    volume INT,
                    amount_change FLOAT,
                    percent_change FLOAT
                )";
                $conn->query($createQuery);
            }

            $insertQuery = "INSERT INTO $tableName VALUES (
                '$date', '$open', '$high', '$low', '$close', '$adj_close', '$volume', '$amount_change', '$percent_change'
            )";
            $conn->query($insertQuery);
        }
        fclose($file);
    }

function main()
{
    $pathToTickerFile = __DIR__."/tickerMaster.txt";
    $mainTickerFile = fopen($pathToTickerFile, "r");
    while (!feof($mainTickerFile)) {
        $companyTicker = fgets($mainTickerFile);
        $companyTicker = trim($companyTicker);

        $fileURL = createURL($companyTicker);
        $companyTxtFile = __DIR__."/txtFiles/".$companyTicker.".txt";
        getCSVFile($fileURL, $companyTxtFile);
        fileToDatabase($companyTxtFile, $companyTicker);
    }
    fclose($mainTickerFile);
    echo "The stocks have been downloaded!";
}

main();

?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Stock Downloader</title>
</head>
<body>
</body>
</html>

But I am getting the following error:

PHP Notice:  Undefined offset: 1
PHP Notice:  Undefined offset: 2
PHP Notice:  Undefined offset: 3
PHP Notice:  Undefined offset: 4
PHP Notice:  Undefined offset: 5
PHP Notice:  Undefined offset: 6

I am using PHP-7.0 & I am unable to understand what's wrong with this code. How do I get rid of this error?

Gautam Vashisht
  • 337
  • 2
  • 3
  • 17

3 Answers3

1

Your file contains a blank line (or possibly multiple). You'll usually see this at the very end of the file.

Because of this, explode() returns an array with a single empty value, while you expect 7 (keys 0 through 6).

Before exploding the line to an array, check if it is indeed empty. Or count the array after creating it, and validate the expected number of keys are present.

Duroth
  • 6,315
  • 2
  • 19
  • 23
1

Before indexing into the array, you might check if the number of items in $pieces by for example counting the number if items that explode returns:

$file = fopen($txtFile, "r");
while (!feof($file)) {
    $line = fgets($file);
    $pieces = explode(",", $line);
    if (count($pieces) > 6) {
        $date = $pieces[0];
        $open = $pieces[1];
        $high = $pieces[2];
        $low = $pieces[3];
        $close = $pieces[4];
        $adj_close = $pieces[5];
        $volume = $pieces[6];
    }
}
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
1

A quick fix, would be to check that you have a line with 7 elements, so after your explode, just check how many elements the array has and skip the rest of the processing if there aren't enough values...

$pieces = explode(",", $line);
if ( count($pieces) != 7)   {
    continue;
}
$date = $pieces[0];
// ....

You should also look into using prepared statements as the offer more security, although you will still have to do a substitution for the table name as you do now (you can't have a table name as a bind variable).

Also as a recommendation, when doing an INSERT,always list the column names ...

INSERT INTO $tableName (date, open, ... )
   VALUES ('$date', '$open', ...)

as this ensures that it's clear which column is where and if any table changes are made that the INSERT is explicit about which values it is using for which columns.

Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
  • The files are indeed empty because `file_get_contents($url)` isn't getting data. `$url` is working fine but `$content` is empty. Can you please tell me why is this happening? – Gautam Vashisht Nov 08 '18 at 10:29
  • Can you give me 1 line from the tickerMaster.txt file so I can test it. – Nigel Ren Nov 08 '18 at 10:39
  • Try adding `ini_set('display_errors', 'On');` and `error_reporting(E_ALL);` to the start of your script, I get `failed to open stream: HTTP request failed! HTTP/1.0 401 Unauthorized`. – Nigel Ren Nov 08 '18 at 10:46
  • `Warning: file_get_contents(https://query1.finance.yahoo.com/v7/finance/download/TSLA?period1=1538917807&period2=1541596207&interval=1d&events=history&crumb=6DH0b71wPwr): failed to open stream: HTTP request failed! HTTP/1.0 401 Unauthorized` – Gautam Vashisht Nov 08 '18 at 10:49
  • This is the warning I am getting every time for each link – Gautam Vashisht Nov 08 '18 at 10:49
  • But typing that URL in the browser downloads the CSV file – Gautam Vashisht Nov 08 '18 at 10:50
  • You must have logged in on the browser. Is there any documentation which tells you how to use the API and how to login? – Nigel Ren Nov 08 '18 at 10:51
  • Also getting `Warning: file_put_contents(/projects/stock-analyzer/txtFiles/TSLA.txt): failed to open stream: Permission denied` – Gautam Vashisht Nov 08 '18 at 10:51
  • No. There isn't any documentation or login requirement. – Gautam Vashisht Nov 08 '18 at 10:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/183291/discussion-between-gautam-vashisht-and-nigel-ren). – Gautam Vashisht Nov 08 '18 at 10:54
  • There are a couple of references - https://stackoverflow.com/questions/44030983/yahoo-finance-url-not-working/44050039#44050039 and https://stackoverflow.com/questions/44249819/php-code-for-yahoo-api-for-downloading-csv-file – Nigel Ren Nov 08 '18 at 10:55
  • Thanks. I will take a look into it. – Gautam Vashisht Nov 08 '18 at 10:58