Jump to content
Sign in to follow this  
sdgsdghshhg

newbie getting unexpected $end

Recommended Posts

Hi.
I'm playing around with MySQL and PHP, using the O'Reilly book.  I know that some of the stuff in here is out of date, most notably the mysql_connect and other stuff.  But I had this book lying around and decided to go with that, and then update my knowledge once I have the basics.

So I'm building a 'pets' database.  The MySQL side is good, I can do that relatively easily and relatively fault-free.  I can do the PHP script to run a SELECT and display all pets.  

Then I move onto the script on pages 233-234 of the O'Reilly book, and I run into a problem.  The script is below.  When I access this, I get:
 

[Wed Nov 15 10:18:58 2017] [error] [client 192.168.1.13] PHP Parse error:  syntax error, unexpected $end in /var/www/html/pets/insert_data.php on line 96


I have run a `grep` and a `wc` on the script, and all of my braces and parentheses are matched.  Interestingly, using vim as my editor, is it just after the second 'echo <<<_END' that colour coding fails, so I guess the error is there?  But I can't see it.  Can someone help?   Thank you.
 

<?php // insert_data.php

include('../../db2_credentials/pets.sql') ;

$connection=mysql_connect($db_host,$db_username,$db_password) ;

// cannot connect ?  Exit

if (!$connection) {
    die ("Could not connect to the database: <br />" . mysql_error()) ;
}

$db_select = mysql_select_db($db_database) ;

if (!$db_select) {
    die ("Could not select the schema.  Please check databse details!<br />" . mysql_error() );
}

if (isset($_POST['animal_name']) &&
        isset($_POST['animal_dob']) &&
        isset($_POST['animal_species']) &&
        isset($_POST['animal_colour']) &&
        isset($_POST['animal_sex'])) {

    $animal_name = get_post('animal_name') ;
    $animal_dob = get_post('animal_dob') ;
    $animal_species = get_post('animal_species') ;
    $animal_colour = get_post('animal_colour') ;
    $animal_sex = get_post('animal_sex') ;

    if (isset($_POST['delete']) && $animal_name != "") {
        $query = "DELETE FROM animals WHERE animal_name = '$animal_name'" ;

            if (!mysql_query($query, $db_server))
                echo "DELETE failed: $query<br />" .
                mysql_error() . "<br /><br />";
    }
    else {
        $query="INSERT INTO animals VALUES" .
               "($animal_name,$animal_dob,$animal_species,$animal_colour,$animal_sex)"    ;

            if (!mysql_query($query, $db_server))
                echo "DELETE failed: $query<br />" .
                mysql_error() . "<br /><br />";

    }

        }

echo <<<_END
<form action="insert_data.php" method="post"><pre>
         Name <input type="text" name="animal_name" />
Date of Birth <input type="text" name="animal_dob" />
      Species <input type="text" name="animal_species" />
       Colour <input type="text" name="animal_colour" />
          Sex <input type="text" name="animal_sex" />
             <input type="submit" value="ADD RECORD" />
</pre></form>
_END;

$query = "SELECT * FROM animals" ;
$result = mysql_query($query) ;

if (!$result) die ("Database access failed: " . mysql_error());

$rows=mysql_num_rows($result) ;

for ($count = 0 ; $count < $rows ; ++$count ) {

    $row=mysql_fetch_row($result) ;
    echo <<<_END
        <pre>
           Animal ID $row[0]
                Name $row[1]
        Date of Brth $row[2]
             Species $row[3]
              Colour $row[4]
                 Sex $row[5]
        </pre>
        <form action="insert_data.php" method="post">
        <input type="hidden" name="delete" value="yes" />
        <input type="submit" value="DELETE RECORD" /></form>
        _END;

Share this post


Link to post
Share on other sites

Ok, well, because if you want to output something via echo, you have to signalize what. if for example you want to echo out a string, it looks like this:

 

echo "string"; 

a function on the other hand looks like this:
 

echo $crud->current_date(); 

http://php.net/manual/en/function.echo.php
 

echo "
<form action='insert_data.php' method='post'><pre>
         Name <input type='text' name='animal_name' />
Date of Birth <input type='text'name='animal_dob' />
      Species <input type='text' name='animal_species' />
       Colour <input type='text' name='animal_colour' />
          Sex <input type='text' name='animal_sex' />
             <input type='submit' value='ADD RECORD' />
</pre></form>";
Edited by AzeS

Share this post


Link to post
Share on other sites

the problem is because the closing heredoc _END; identifier doesn't start in the first column in a line.

 

there's big red warning in the php.net string/heredoc documentation -

 

Warning 
It is very important to note that the line with the closing identifier must contain no other characters, except a semicolon (;). That means especially that the identifier may not be indented, and there may not be any spaces or tabs before or after the semicolon. It's also important to realize that the first character before the closing identifier must be a newline as defined by the local operating system. This is \n on UNIX systems, including Mac OS X. The closing delimiter must also be followed by a newline. 
 
If this rule is broken and the closing identifier is not "clean", it will not be considered a closing identifier, and PHP will continue looking for one. If a proper closing identifier is not found before the end of the current file, a parse error will result at the last line. 

 

 

Share this post


Link to post
Share on other sites

 

the problem is because the closing heredoc _END; identifier doesn't start in the first column in a line.

 

Thank you!  :)

Share this post


Link to post
Share on other sites
I'm playing around with MySQL and PHP, using the O'Reilly book.

 

 

this code/book is horrifically bad, and not just because of the out of date mysql_ extension.

 

some problems -

 

1) include('../../db2_credentials/pets.sql') ; unless that particular path is outside of the document root folder, anyone can browse to that file and see your database connection credentials and gain access to your database. you should use a .php extension for any included/required file that contains php code.

 

2) include isn't a function and the () around the filename are unnecessary and just clutter up your code.

 

3) you should use 'require' for things that your code requires to work.

 

4) when you do update the code to use a current php database extension, the php PDO extension is the best choice. it is simpler and more constant to use than the php mysqli extension. you should also learn and use prepared queries when supplying values to the sql query statement.

 

5) you shouldn't output any internal error information when on a public server. for that particular code, the error handling should have used trigger_error() so that what happens with the error information will be controlled by php's error_reporting, display_errors, and log_errors settings and you can simply change those settings so that the error information will be logged when on a public server. when you switch to the php PDO extension, you would use exceptions to handle errors and simply let php catch the exceptions. php will use its error_reporting, display_errors, and log_errors settings to control what happens with the actual error information and all the error handling logic in the code can be removed, thereby simplifying and de-cluttering the code.

 

6)  

if (isset($_POST['animal_name']) &&        isset($_POST['animal_dob']) &&
        isset($_POST['animal_species']) &&
        isset($_POST['animal_colour']) &&
        isset($_POST['animal_sex'])) {

this coding method is verbose and error prone. programming is already a tedious task. you and the author of that book should look for ways to simplify code, not write out code that you have to change to match every form field. the purpose of the above code is to detect if a post method form was submitted before running the form processing code. the following single line of code accomplishes the same thing and doesn't need to be changed if any of the form fields change - 

if($_SERVER['REQUEST_METHOD'] == 'POST'){

if your form processing code needs to handle more than one form, you would use a hidden field that contains a value that's different for each form, then the form processing code will use a switch/case statement to control which form processing code to run.

 

7)  

$animal_name = get_post('animal_name') ;    $animal_dob = get_post('animal_dob') ;
    $animal_species = get_post('animal_species') ;
    $animal_colour = get_post('animal_colour') ;
    $animal_sex = get_post('animal_sex') ;

i/we don't know what the get_post() code does, but it probably is not appropriate, both when it was written, and now.

 

in general, there's no good reason to have line after line of code that's just copying form field values to discrete php variables. this is just more tedious typing that doesn't accomplish anything useful. the $_POST array variable that the data is in is a perfectly fine variable to use in the rest of the code and if you do have a need to copy that data to another array variable, such as if you want to trim all the data at once, you can do that using a single statement, not a separate statement for each form field.

 

8)  

if (isset($_POST['delete']) && $animal_name != "") {

you need to determine what action the code will take (delete, insert, update) and validate the input data separately and you need specific logic to detect each action (the lack of a delete input doesn't always mean you should try to insert data.)

 

you need to ALWAYS validate input data and only use the input data if it is valid. when validating input data, you need to setup a specific error message for each problem with each input value. the easiest way of doing this is to use a php array variable to hold the validation errors. you can then test at any point if there are errors or not by testing if the array is not empty() or is empty().

 

you would display the validation errors when you re-display the form. you would also re-populate the form field values when you re-display the form so that the visitor doesn't need to keep retyping the same information.

 

9 ) 

$query="INSERT INTO animals VALUES" .
               "($animal_name,$animal_dob,$animal_species,$animal_colour,$animal_sex)"    ;

you need to ALWAYS list out the column names in the query. this both helps when writing or reading the query and if the columns in your table should ever get rearranged, the query will still work.

 

10) 

$query = "SELECT * FROM animals" ;

you should ALWAYS list out the column names in the SELECT ... term. this will help when writing or reading the query and only the data you need will be selected and transferred to the php code. 

 

11) 

           Animal ID $row[0]
                Name $row[1]
        Date of Brth $row[2]
             Species $row[3]
              Colour $row[4]
                 Sex $row[5]

you should almost always use an associate array when fetching and using data. this will help when writing or reading code. the exception is when you are doing something simple like selecting a COUNT() value, but even in this case, by adding an alias name in the query, your code can use the associate alias name and be easier to understand. 

Edited by mac_gyver

Share this post


Link to post
Share on other sites

 

this code/book is horrifically bad, and not just because of the out of date mysql_ extension.

 

some problems -

 

1) include('../../db2_credentials/pets.sql') ; unless that particular path is outside of the document root folder, anyone can browse to that file and see your database connection credentials and gain access to your database. you should use a .php extension for any included/required file that contains php code.

 

 

 

Massive snip.  Beautiful - thank you for this massive amount of useful stuff.   Can you recommend a better book/course that would do what I need, i.e. basically show me the ropes of PHP/MySQL integration, and let me move on to building my own sites?

 

Thanks again. 

Share this post


Link to post
Share on other sites

Oh, as for point 1 - yes, that was a typo and the file should have been *.php.  It is located outside the http document root, so can't be served by the webserver.

 

Thanks again.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.