HTML zawiera kilka błędów, a formularz używany do wyszukiwania kempingów w rzeczywistości nie podaje żadnych danych, najprawdopodobniej z powodu niektórych błędów w kodzie HTML. ul
element może mieć li
elementy tylko jako elementy potomne - ale te li
elementy mogą mieć inną zawartość (zazwyczaj nie jest to najlepszy sposób na zrobienie tego IMO w tym przypadku) i tworzyć elementy wejściowe dowolnego typu, które powinny mieć atrybut nazwy i ogólnie wartość. W przypadku formularza rezerwacji fire
,electric
i sewer
powinien być nazwany jako taki z wartością 1 (patrz poprzednie pytanie). Selektory dat muszą mieć nazwy, więc albo zamiast identyfikatora, albo nazwij je startdate
i enddate
ponieważ skrypt php oczekuje ich w tablicy POST.
Jeśli formularz pomyślnie przesłał dane, a zapytanie sql działało poprawnie, gdzie pojawiłyby się wyniki? Widzę, że akcja formularza to includes/reserve.inc.php
który jest drugą częścią kodu ( PHP ), ale nie wyświetla żadnej treści.
Edycja kodu HTML w przeglądarce w celu dodania atrybutów do różnych elementów formularza i zmiana ich wartości przed przesłaniem formularza dała następujące parametry POST na aktywnej stronie...
startdate=01%2F03%2F2018&enddate=01%2F17%2F2018&fire=1&electric=1&sewer=1&submit1=
Podczas gdy przed tylko submit1
pojawiał się. Jednak nadal nie odesłano wyników.
Jak już masz jQuery
na stronie dla różnych zadań, być może należałoby użyć ajax do POST danych do skryptu PHP zaplecza i użyć wywołania zwrotnego, aby dodać zawartość HTML do bieżącej strony? Na pewno coś do przemyślenia.
<?php
@session_start();
require_once("includes/dbh.inc.php");
?>
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('#login-trigger').click(function(){
$(this).next('#login-content').slideToggle();
$(this).toggleClass('active');
if ($(this).hasClass('active')) $(this).find('span').html('▲')
else $(this).find('span').html('▼')
})
});
$(document).ready(function(){
$('#reserve-trigger').click(function(){
$(this).next('#reserve-content').slideToggle();
$(this).toggleClass('active');
})
});
$('#reserve-trigger').on('focusout', function () {
$(this).toggleClass('active');
});
$('#login-trigger').on('focusout', function () {
$(this).toggleClass('active');
});
</script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js">
<script>
$(document).ready(function() { $("#startdate").datepicker(); });
$(document).ready(function() { $("#enddate").datepicker(); });
</script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<header>
<div class='container'>
<div id='branding'>
<h1><span class='highlight'>Whispering</span> Winds Park</h1>
</div>
<nav>
<ul>
<li class='current'><a href='index.php'>Home</a></li>
<li><a href='mission.php'>Our Mission</a></li>
<li><a href='donate.php'>Donate</a></li>
<li><a id='reserve-trigger' href='#'>Camping</a>
<div id='reserve-content' tabindex='-1'>
<form action='includes/reserve.inc.php' method='POST'>
<fieldset>
<!--
child elements of a `ul` should be `li` only
so you required a few more `<li></li>` around
certain items here
Form input elements require a name attribute and a type for the datepickers
-->
<ul>
<li><input type='text' id='startdate' name='startdate' placeholder='Start Date' /></li>
<li><input type='text' id='enddate' name='enddate' placeholder='End Date'/></li>
<!--
The checkboxes require a name attribute otherwise they will not appear
in the POST array data. Set the value to `1` as it is a bit stored in
the db anyway
-->
<li><label for='fire'>Fire Pit: </label><input type='checkbox' name='Fire' value=1></li>
<li><label for='electric'>Electricity: </label><input type='checkbox' name='Electric' value=1></li>
<li><label for='sewer'>Sewage: </label><input type='checkbox' name='Sewer' value=1></li>
<li><button type='submit' class='button3' name='submit1'>Find a Reservation</button></li>
</ul>
</fieldset>
</form>
</div>
</li>
<!-- /*login button*/ -->
<?php
if( isset( $_SESSION["u_uid"] ) ) {
echo '
<li>
<form action="includes/logout.inc.php" method="POST">
<button type="submit" class="button_1" name="Submit">Logout</button>
</form>
</li>';
} else {
echo
'<li id="login">
<a id="login-trigger" href="#">
<button class="button_1">Log in <span>▼</span></button>
</a>
<div id="login-content" tabindex="-1">
<form action="includes/login.inc.php" method="POST">
<fieldset id="inputs">
<input type="text" name="uid" placeholder="Username" required>
<input type="password" name="pwd" placeholder="Password" required>
<button type="submit" class="button3" name="Submit">Log In</button>
</fieldset>
</form>
</div>
</li>
<li id="signup">
<a href="signup.php"><button class="button_1">Sign up</button></a>
</li>';
}
if( isset( $_SESSION["u_admin"] ) ) {
echo '
<li id="signup">
<a href="admin.php"><button class="button_1">Admin</button></a>
</li>';
}
?>
</ul>
</nav>
</div>
</header>
</body>
</html>
Przechodząc do skryptu zaplecza.
Czy masz tabele o nazwie campsite
i campsites
? Wszystkie instrukcje sql mają wbudowane zmienne, które pomimo użycia mysqli_real_escape_string
, pozostawia Twój kod potencjalnie podatny na wstrzyknięcie SQL, więc powinieneś użyć prepared statements
za każdym razem, gdy używasz danych wejściowych dostarczonych przez użytkownika. Wystarczy jedno pole, które można wykorzystać, aby naruszyć cały system! Nie mogłem do końca zrozumieć logiki tego, co się tam działo (prawdopodobnie za mało kofeiny), więc poniższe może być zbyt chybione
<?php
session_start();
/* Prevent direct access to this script in the browser */
if ( realpath(__FILE__) == realpath( $_SERVER['SCRIPT_FILENAME'] ) ) {
/* could send a 403 but Not Found is probably better */
header( 'HTTP/1.0 404 Not Found', TRUE, 404 );
die( header( 'location: /index.php' ) );
}
if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['submit1'], $_POST['startdate'], $_POST['enddate'], $_POST['fire'], $_POST['electric'], $_POST['sewer'] ) ) {
if ( empty( $_POST['startdate'] ) || empty( $_POST['enddate'] ) ) {
exit( header( 'Location: ../index.php?index=empty_dates' ) );
}
/* results from search query will be stored in this array for later use */
$output=array();
require_once('dbh.inc.php');
/*
Do startdate and enddate need to be session variables???
*/
$startdate = filter_input( INPUT_POST,'startdate',FILTER_SANITIZE_SPECIAL_CHARS );
$enddate = filter_input( INPUT_POST,'enddate',FILTER_SANITIZE_SPECIAL_CHARS );
$fire = filter_var( filter_input( INPUT_POST,'fire', FILTER_SANITIZE_NUMBER_INT ), FILTER_VALIDATE_INT );
$electric = filter_var( filter_input( INPUT_POST,'electric', FILTER_SANITIZE_NUMBER_INT ), FILTER_VALIDATE_INT );
$sewer = filter_var( filter_input( INPUT_POST,'sewer', FILTER_SANITIZE_NUMBER_INT ), FILTER_VALIDATE_INT );
/*
Dates from the DatePicker are in mm/dd/yyyy
but typically we would want to use yyyy/mm/dd
in the database.
*/
$startdate=DateTime::createFromFormat( 'm/d/Y', $startdate )->format('Y-m-d');
$enddate=DateTime::createFromFormat( 'm/d/Y', $enddate )->format('Y-m-d');
if( $fire > 1 or $fire < 0 or is_string( $fire ) ) $fire=0;
if( $electric > 1 or $electric < 0 or is_string( $electric ) ) $electric=0;
if( $sewer > 1 or $sewer < 0 or is_string( $sewer ) ) $sewer=0;
$sql='select `site_id`,`uid`,`startdate`,`enddate`,`s_price` from `campsite`
where `water`=? and `fire`=? and `electric`=? and `site_id` not in (
select `site_id`
from `reservation`
where `startdate` >= ? and `startdate` <= ?
)';
$stmt=$conn->prepare( $sql );
if( $stmt ){
$stmt->bind_param('iiiss', $sewer, $fire, $electric, $startdate, $enddate );
$result = $stmt->execute();
$rows = $result->num_rows;
if( $result && $rows > 0 ){
$stmt->store_result();
$stmt->bind_result( $id, $uid, $start, $end, $price );
while( $stmt->fetch() ){
$output[]=array(
'site_id' => $id,
'uid' => $uid,
'startdate' => $start,
'enddate' => $end,
's_price' => $price
);
}
$stmt->free_result();
$stmt->close();
$conn->close();
/*
Now we should have an array with the recordset data from the search
Depending upon form submission method ( standard or ajax ) you need to
do something with that data. Typically you would let the user know the
results of the search ( otherwise what is the point of letting them search? )
So, you could format the results here as HTML or send back json etc
*/
foreach( $output as $index => $site ){
echo "
<pre>
{$site['site_id']}
{$site['uid']}
{$site['startdate']}
{$site['enddate']}
{$site['s_price']}
</pre>";
}
} else {
exit( header('Location: /index.php?error=no_available_camps') );
}
} else {
echo "Failed to prepare sql query";
}
}
?>
"; } } else { exit( header('Lokalizacja:/index.php?error=no_available_camps') ); } } else { echo "Nie udało się przygotować zapytania sql"; } }?> Były tam inne instrukcje sql, ale jak powiedziałem, nie mogłem do końca postępować zgodnie z logiką, więc powyższe jest najprawdopodobniej niekompletne/błędne, ale powinno trochę pomóc przynajmniej w przygotowanych instrukcjach.
Inne punkty
Masz nieobsługiwany błąd na campground.php
strona, która ujawnia
includes/reserve.php
i /reserve.php
oba dają wynik 404-Not Found
błąd
Być może użyj .htaccess
plik w images
katalog, aby zapobiec hotlinkowaniu lub przeglądaniu katalogów.
Jest tam kilka oszałamiających obrazów, ale niektóre są, szczerze mówiąc, absolutnie ogromne i pomimo tego, że większość ludzi ma szybkie łącze szerokopasmowe, pobieranie pliku jpg o wielkości 3,7 Mb w ramach przepływu HTML nieco spowalnia - więc być może trochę optymalizacji obrazu byłoby dobre pomysł też. To powiedziawszy - chciałbym sam pojechać do tego miejsca!