1

I'm currently building my first PHP application. I want to read in bus times from a csv file and give back ti users the next bus from their residence to our university. It is my first try with PHP, so be gentle:

<?php

    // configuration
    require("../includes/config.php"); 


    if (!empty($_SESSION["id"]))
    {
        //lookup database entries for house
        $users = query("SELECT * FROM users WHERE id = ?", $_SESSION["id"]);
        if ($users === false)
        {
            apologize("Sorry, there was an error");
        }
        //lookup database entries for house
        $residences = query("SELECT * FROM residences WHERE id = ?", $users[0]["residence"]);
        if ($residences === false)
        {
            apologize("Sorry, there was an error");
        }
        //if user specified a residence in his profile
        if($residences[0]["id"] != 0)
        {   
            $times = array();           
            //if there is no bus today, in this case sat and sun
            if(date( "w", $timestamp) == 0 || date( "w", $timestamp) == 6)
            {
                $times[0] = "There is no bus today";
            }
            //load the busplan for his residence
            else
            {
                //open file and load in array if time is higher than date("His");
                $timesList = file_get_contents($users[0]["residence"] . ".csv");
                $nextbuses = explode(',', $timesList);
                $hoursMins = date("Gi");

                $num = 0;

                for($i = 0; $i < count($nextbuses); $i++)
                {
                    if($hoursMins < $nextbuses[$i])
                    {
                        $times[$num] = $nextbuses[$i];
                        $num++;
                    }

                }
            }
            render("shuttle_show.php", ["title" => "Next Shuttle from your residence.", "times" => $times]);
        }
    }

This uses the function query:

function query(/* $sql [, ... ] */)
{
    // SQL statement
    $sql = func_get_arg(0);

    // parameters, if any
    $parameters = array_slice(func_get_args(), 1);

    // try to connect to database
    static $handle;
    if (!isset($handle))
    {
        try
        {
            // connect to database
            $handle = new PDO("mysql:dbname=" . DATABASE . ";host=" . SERVER, USERNAME, PASSWORD);

            // ensure that PDO::prepare returns false when passed invalid SQL
            $handle->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 
        }
        catch (Exception $e)
        {
            // trigger (big, orange) error
            trigger_error($e->getMessage(), E_USER_ERROR);
            exit;
        }
    }

    // prepare SQL statement
    $statement = $handle->prepare($sql);
    if ($statement === false)
    {
        // trigger (big, orange) error
        trigger_error($handle->errorInfo()[2], E_USER_ERROR);
        exit;
    }

    // execute SQL statement
    $results = $statement->execute($parameters);

    // return result set's rows, if any
    if ($results !== false)
    {
        return $statement->fetchAll(PDO::FETCH_ASSOC);
    }
    else
    {
        return false;
    }
}

the other functions it uses are not relevant I guess. Now I cant seem to find why this keeps producing:

Notice: Undefined offset: 0 in /Applications/MAMP/htdocs/html/shuttle.php on line 16

Notice: Undefined offset: 0 in /Applications/MAMP/htdocs/html/shuttle.php on line 22

The relevant lines are

    $residences = query("SELECT * FROM residences WHERE id = ?", $users[0]["residence"]);

and

    if($residences[0]["id"] != 0)

Would appreciate some help! :)

Edit:

I transferred the same file to my linux system and without any changes I get a vardump. If I use the same vardump on MAMP on my Mac the array is empty. Now I get for:

var_dump($users);

array (size=1)
  0 => 
    array (size=5)
  'id' => int 12
  'username' => string 'frechdaxx' (length=9)
  'mail' => string '*************@gmail.com' (length=23)
  'hash' => string '$1$qr5axj4C$BET5zZGJza2DcHI8eD8fV0' (length=34)
  'residence' => int 9573
  1. Why is this a problem at all? the function query worked with the exact same syntax before when I accessed the user table and as we can see it gives back all other values correctly.

  2. Why the difference between my environments? The array is empty on my MAMP server, but works on Linux. However, other code examples with the query function work perfectly on both environments

  3. Why the big int of 9573? The value in the table is 2.
rStorms
  • 1,036
  • 2
  • 11
  • 23
  • In situations like this, *debug* your results, for example using this: `echo '
    '; var_dump($some_variable); echo '
    ';`
    – thaJeztah Apr 06 '13 at 19:59
  • Does your query() returns results or only creates query to DB ??? query and get results are different actions !!! – Svetoslav Apr 06 '13 at 20:03
  • possible duplicate of [PHP: "Notice: Undefined variable" and "Notice: Undefined index"](http://stackoverflow.com/questions/4261133/php-notice-undefined-variable-and-notice-undefined-index) – Madara's Ghost Apr 06 '13 at 20:19
  • I transferred the same file to my linux system and without any changes I get a vardump. Before the array seemed empty. Now I get for: echo var_dump($users);array (size=1) 0 => array (size=5) 'id' => int 12 'username' => string 'name' (length=9) 'mail' => string 'mail@gmail.com' (length=23) 'hash' => string 'passwordhash' (length=34) 'residence' => int 9573 and a big int, which doesn't make any sense. In the database the value is 2 – rStorms Apr 06 '13 at 20:23
  • @user2252633 That last comment isn't very readable... update at the end of your question please. And it's `var_dump($users);`, not `echo var_dump($users);`. – Francisco Presencia Apr 06 '13 at 20:38
  • Because Linux rocks (; . Seriously, It works on linux, right? Besides, I think this has become a completely different question. I'd suggest you setting up a new question if you cannot solve it yourself, with more information, in the appropriate [stack exchange site](http://stackexchange.com/). Maybe [apple.stackexchange.com](http://apple.stackexchange.com/) or [dba.stackexchange.com](http://dba.stackexchange.com/)? Because I have no idea about mac. I'd suggest working on a similar environment to the production machine's one. PS, you can accept my answer if it answered your original question. – Francisco Presencia Apr 06 '13 at 21:13

2 Answers2

2

This is simply that $users[0]["residence"] doesn't exists (is not set). You should check it before attempting to use it. As you can see, it's only a notice, not a error. This means that in some case scenarios, the variable can be unset and PHP won't complain THAT much, but this is definitely not good as a general rule.

I would change it to:

  $users = query("SELECT * FROM users WHERE id = ?", $_SESSION["id"]);
  if (empty($users[0]["residence"]))
    {
    apologize("Sorry, there was an error");
    }

Furthermore, that only "fixes" it. If you want to go to the root of the problem, it's in the query() function that is called in $users = query("SELECT * FROM users WHERE id = ?", $_SESSION["id"]);:

  // execute SQL statement
  $results = $statement->execute($parameters);

  // return result set's rows, if any
  if ($results !== false)
  {
    $fetched = $statement->fetchAll(PDO::FETCH_ASSOC);
    // Check that ther was actually something fetched
    if(!empty($fetched))
    {
      return $fetched;
    }
  }
/* You don't need to return false, null is the default returned value.
 * If you *want* it, then delete the else. */
}

From the documentation, fetchall returns an empty array if there's nothing, so the function might return an empty array.

Francisco Presencia
  • 8,732
  • 6
  • 46
  • 90
1
$users = query("SELECT * FROM users WHERE id = ?", $_SESSION["id"]);
if ($users === false) {   }

You are strictly checking if query returned false, that only occurs when something was wrong with query or parameters. That does not check if any result was returned, and you are referring to the first returned record ($users[0]["residence"]) that is not present ($users is an empty array).

Since user id comes from $_SESSION["id"] it should be present and available in database, but there is possibility that somewhere in your code you are overwriting it with other id.

dev-null-dweller
  • 29,274
  • 3
  • 65
  • 85
  • Yeah, but it worked before with the exact same query. If I use the same code on my linux system the array gets filled. I updated above, so please have a look :) – rStorms Apr 06 '13 at 20:58
  • Check what ID is passed to your query and your db connection if it connects to desired host/database. Also enable error reporting and watch logs for any warnings / notices. – dev-null-dweller Apr 07 '13 at 06:47