21. září bude sraz! Od 18.00 v restauraci Tradice v Praze u Anděla
Autor Zpráva
Jurasek
Profil
Zdravím vás přátelé!

Před časem jsem se tady ptal, jestli nevíte a neporadíte proč mi náhle přestal částečně fungovat PHP odpovědní formulář na mých stránkách.

Dostal jsem pár dobrých rad, které jsem ale vzhledem k mé naprosté neznalosti PHP nebyl schopen aplikovat, ani použít doporučené návody.

Nejlepší rada stejně byla to udělat celé znovu. A tak se i stalo. Napsal mi to polský programátor, kterého jsem nedávno potkal na cestách.

Jenže se to nepovedlo dotáhnout do konce, a on odjel někam úplně mimo.

Celé to funguje, ale rád bych doladil dvě věci (dva problémy), ale nevím jak.

1) Pokud někdo nevyplní všechna (tři) pole, stránka hodí chybu, napíše červeně ať pisatel vyplní všechna pole a přitom skočí nahoru.
2) Při tomto scénáři taky vše už vypsané zmizí.

V mé předchozí verzi (evidentně ale ne moc dobře řešené a navíc přestala náhle částečně fungovat) se při pokusu odeslat nevyplněný formulář objevila bublina se šipkou u příslušného pole s žádostí o vyplnění toho pole. Žádný skok nahoru, žádné zmizení již napsaného. To se mi líbilo.

Šlo by to nějak jednoduše přenastavit - něco jako dodat to staré do toho nového, aby to bylo dobré, ale fungovalo stejně.

Ještě doplním, že mám kontakt.html přejmenovaný na kontakt.php, v .htacces je to nastaveno (moc jsem nepochopil proč), a mám spojené oba jazyky (cz a en) do jednoho PHP formuláře - předtím jsem měl dva.
Pochopil jsem, že předtím to bylo celé kontrolováno z kontakt.html (proto mi to funguje off-line), kdežto teď je to kontrolováno PHP, což je asi jak to má být, ale nerozumím tomu ani trochu.

Pokud mi k tomu poradíte, dáte názory (jestli je kód dobrý), nebo to někdo přímo uměl spravit, byl bych moc rád, a už o mně v PHP sekci neuslyšíte :-D

Tady je původní Form - i bez zbytku (html a css) to funguje tak, jak bych chtěl:

<form method="POST" action="feedback-form-cs.php">

Jmeno:&nbsp;<input type="text" name="name" size="40" required><br>
E-mail:&nbsp;&nbsp;<input type="text" name="email" size="40" required><br>
Zprava:<br>
<textarea name="comment" cols="60" rows="10" required></textarea><br>

<input type="submit" value="Odeslat">
</form>

Celá má stránka je tady: vanishingworldphotography.com

Moc díky.


A tady je celý ten nový kód:

<?php
ob_start();
/*
    1. Check, if all variables was sent
    2. Prepare mail to send
    3. Send mail
    4.
        a) Show system message of success or failure
      or
        b) redirect to the success/failure page
*/

/* CONFIGURATION : start */

$adminEmail = 'MUJMEJL@halo.cz';

$subject = "Website Feedback";
$messages['cz'] = array(
    'systemSuccessMessage' => "Děkuji - vaše zpráva byla odeslána.",
    'emailErrorMessage' => "Něco se nepovedlo a vaše zpráva nebyla odeslána. Zkuste prosím znovu.",
    'dataErrorMessage' => "Vyplňte prosím všechny údaje.",
    );
$messages['en'] = array(
    'systemSuccessMessage' => "Thank you! Your message has been sent.",
    'emailErrorMessage' => "Something went wrong and your message was not sent. Please try again.",
    'dataErrorMessage' => "Please fill in all the fields.",
    );

$links['cz'] = array(
    'goback' => 'Go to Home page',
    'contactForm' => 'Back to Contact form',
);
$links['en'] = array(
    'goback' => 'Go to Home page',
    'contactForm' => 'Back to Contact form',
);

define('SEND_WITH_ERRORS', false); // true, if you want to have an email sent despite incomplete form, false, if you don't

/* CONFIGURATION : end  - DONT CHANGE ANYTHING BELOW */

$error = false; // no error at this point
$errorMessage = ''; // we need these two variables set before we use them anywhere later

    
// default language to use
$lang = 'en';

// what language we want to use
if(isset($_POST['form']['lang'])) {
    switch($_POST['form']['lang']) {
        // if the case the form was sent from the czeck form
        case 'cz':
            $lang = 'cz';
        break;
        
        // otherwise
        default:
            $lang = 'en';
        break;
    }
}


/**
 * It sends email with information got in the form
 * 
 * @param array Data retrieved from the user
 * @return true or error message
 */
function sendEmail($f, $withErrors = false) {
    // we need to get configuration variables into the function
    global $subject, $messages, $adminEmail, $lang;
    
    // we want to read this email in UTF-8 (all special language characters) and as a plain text
    $headers = "MIME-Version: 1.0" . "\r\n" . 
               "Content-type: text/plain; charset=UTF-8" . "\r\n"; 
    
    $message = "
Name: " . $f['name'] ."\r\n
E-mail: " . $f['email'] ."\r\n
Message: \r\n
" . $f['comment'] . "
";
    
    $result = mail($adminEmail, $subject, $message, $headers);
    
    if($result) {
        return TRUE;
    }
    else {
        return $messages[$lang]['emailErrorMessage'];
    }
}

if(isset($_POST)) { // check if the form was sent by POST method
    if(isset($_POST['form'])) {
        // the form was sent, because our new variable (array) is set
        $f = $_POST['form']; // local variable $f as a shortcut to the $_POST['form'] array
        
        // isset checks if there is key 'name' in the array
        // strlen checks how long is the variable set under 'name' key - if at least 1 (one) sign is typed, than it returns true
        if(isset($f['name']) && strlen($f['name']) > 0 && isset($f['email']) && strlen($f['email']) > 0 && isset($f['comment']) && strlen($f['comment']) > 0) {
            // if all of these return true (all of them at the same time - thanks to '&&' operator, which means AND) then we have all data we need in order to send an email to the administrator
            
            // send email - we use a function to make the code more clear
            
            $result = sendEmail($f); // as a parameter we give all array with all the data
            
            if($result === true) { // we check what the function returned and act on that
                // all went well, when the function returned EXACTLY TRUE
            }
            else {
                // something is wrong and we would get our message in the $result variable
                $error = true;
                $errorMessage = $result;
            }
        }
        else {
            $error = true;
            if(SEND_WITH_ERRORS) {
                sendEmail($f, SEND_WITH_ERRORS);
            }
            $errorMessage = $messages[$lang]['dataErrorMessage'];
            $location = ($lang == 'cz') ? 'kontakt.php' : 'contact.php';
            header('Location: ' . $location . '?error=1');
            exit();
        }
    }
    else {
        // the form was not sent
        $error = true;
    }
}
else {
    $error = true; // no $_POST set = no form sent by POST method
}

$systemMessage = '';

if($error) {
    // error occured
    
    if(!isset($errorMessage) || strlen($errorMessage) == 0) {
        $errorMessage = $messages[$lang]['emailErrorMessage'];
    }
    
    // show error messsage
    $systemMessage = $errorMessage;
}
else {
    $systemMessage = $messages[$lang]['systemSuccessMessage'];
}
ob_end_flush();
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
<title><?php echo $systemMessage; ?></title>
<meta name="robots" content="noindex">
<meta http-equiv="Content-Language" content="en">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="icon" href="img/favicon.ico" type="image/x-icon">
</head>

<body>
<br>

<?php echo $systemMessage; ?>

<br>

<?php if($lang == 'cz') { ?>
    <input onclick="location.href='http://vanishingworldphotography.com/cs-index.html';" type="button" value="Přejít na Hlavní stránku">&nbsp;&nbsp;&nbsp;
    <input onclick="location.href='http://vanishingworldphotography.com/kontakt.html';" type="button" value="Zpět na Kontaktní formulář">
<?php } else if($lang == 'en') { ?>
    <input onclick="location.href='http://vanishingworldphotography.com/';" type="button" value="Go to Home page">&nbsp;&nbsp;&nbsp;
    <input onclick="location.href='http://vanishingworldphotography.com/contact.html';" type="button" value="Back to Contact form">
<?php } ?>

</body>

</html>
ProbablyYes
Profil
Jurasek:
V mé předchozí verzi... Žádný skok nahoru, žádné zmizení již napsaného. To se mi líbilo.
O to se stará „required“ vyplněné na konci <input> těch textových polí.
Jurasek
Profil
Díky, ano, ale jak to spojit s tím novým, ten funguje jinak.

Tohle je ze starého kódu, v tom novém je to řešeno jinak. To asi nemůžu jen přidat.........
bestik_63
Profil
chápu správně že pokud se nevyplní všechny tři pole tak se před odesláním má provést toto:
1) Pokud někdo nevyplní všechna (tři) pole, stránka hodí chybu, napíše červeně ať pisatel vyplní všechna pole a přitom skočí nahoru.

a toto taky zcela úplně nechápu :
2) Při tomto scénáři taky vše už vypsané zmizí.
ProbablyYes
Profil
Jurasek:
To asi nemůžu jen přidat...
On je tvůj dotaz totiž dost zmatený, chápu, o co se snažíš, ale dodal jsi html formulář, kde už to přidané je a php+html část nějaké stránky, která vůbec formulář neobsahuje. Alespoň ho nejsem schopný najít.
Tomáš123
Profil
Jurasek:
Obecne prejdi pri základnej validácii vstupných hodnôt pole $_POST. Ak je index prázdny, niečo nebolo vyplnené a ty vieš, že máš vypísať chybovú hlášku. Máš dokonca aj všetky hodnoty, ktoré užívateľ zadal. Stačí sa správne rozhodnúť, kedy formulár znovu zobraziť (s hodnotami od užívateľa) a kedy nie. Formulár by nemal byť zobrazený iba vtedy, keď sa všetko správne spracuje a odošle. Potom iba jednoduchým echom predvyplníš value všetkých neprázdnych polí, ktoré si obdržal.

Kód v náznaku:
<?php
  $show = true;
  $error = true;
  foreach($_POST as $index) {
    if(!empty($index)) {
      $error = false;
    }
  }
  if($error !== true) {
    //validácia - ak sa nenájde chyba pokúsiť sa o odoslanie
    //ak sa podarí odoslať, $show = false;
  }
?>
<form method="POST">
  <input type="text" name="name" value="<?php echo !empty($_POST['name']) ? $_POST['name'] : '';?>">
  <input type="text" name="email" value="<?php echo !empty($_POST['email']) ? $_POST['email'] : '';?>">
</form>    
Jan Kozák
Profil
Tomáš123:
Kontrola ve skriptu, který přidal Jurasek, je podstatně lepší než ta tvá, protože také kontroluje, zda byly odeslány všechny hodnoty, které jsou pro vytvoření e-mailu potřeba. Co kontroluješ ty, je ve skutečnosti docela zbytečné.

Jurasek:
Řešení tvého problému je ve skutečnosti velmi jednoduché. Do formuláře na kontakt.html a contact.html přidej required na konec formulářových polí. Kolonka pro jméno se z <input type="text" name="form[name]" size="40"> nahradí <input type="text" name="form[name]" size="40" required>.
Díky tomu bude formulář reagovat stejně, jako reagoval v té staré verzi.
Cca u každého dvacátého uživatele, který chybně formulář vyplní, se sice na samostatné stránce zobrazí chybová hláška na nové stránce, ale 1) to není příliš pravděpodobný stav a počet takto postižitelných uživatelů se bude postupem času snižovat s tím, jak bude klesat poměr zastaralých internetových prohlížečů;
2) Upravit skript tak, aby na nevyplněné položky upozorňoval bez načtení nové stránky úplně všechny uživatele, by pro tebe asi bylo příliš náročné.
Tomáš123
Profil
Jan Kozák:
Mojim cieľom nebolo zabezpečiť kód. Nevedel som ani na čo slúži. Iba som načrtol riešenie vyplnenia polí podľa toho, čo zadal užívateľ. Neskôr som si všimol, že Poliak tiež použil medzipremennú $error. Skript som ale nenapodobňoval (ako to mohlo vyzerať). Ale k téme: Išlo mi o načrtnutie jednoduchej podoby riešenia zabezpečenia straty údajov po nesprávnom vyplnení a odoslaní.
V rýchlosti som zabudol podmieniť zobrazenie formulára. Chcel som teda napísať takýto kód:
<?php
  $show = true;
  $error = true;
  foreach($_POST as $index) {
    if(!empty($index)) {
      $error = false;
    }
  }
  if($error !== true) {
    //validácia - ak sa nenájde chyba pokúsiť sa o odoslanie
    //ak sa podarí odoslať, $show = false;
  }
if($show !== false) :?>
<form method="POST">
  <input type="text" name="name" value="<?php echo !empty($_POST['name']) ? $_POST['name'] : '';?>">
  <input type="text" name="email" value="<?php echo !empty($_POST['email']) ? $_POST['email'] : '';?>">
</form>
<?php endif; ?>
Zabezpečený nie je, ale snáď z neho je poznať môj zámer.
Alphard
Profil
Tomáš123 [#8]:
Mám takový pocit, že [#7] Jan Kozák narážel na problém toho, že vy určujete OR celé sekvence, tj. když je alespoň jedno pole vyplněné, je to správně. Původní tazatel tam měl AND, tj. všechna pole musí být vyplněná, aby to bylo správně.
Tomáš123
Profil
Alphard:
Aha, to som si vôbec neuvedomil. Chcel som to napísať tak, aby sa vždy na začiatku počítalo s chybou a muselo sa niečo stať, aby sa predpoklad zmenil. V tomto prípade by bolo asi najjednoduchšie nastaviť $error na false a negovať podmienku a hodnotu premennej $error vo vnútri.

Ospravedlňujem sa za chybu, nechcem vlákno rozvádzať iným smerom.
Jurasek
Profil
Vážení přátelé,

děkuji vám všem za reakce, pomoc a trpělivost. Omlouvám se za mírné zpoždění, ale dostal jsem se se svým počítačem k internetu až teď.

Uvědomuji si, že můj dotaz byl asi trochu zmatený (jak někdo výše napsal), těžko se to celé vysvětluje, zvlášť když, v případě PHP, moc nevím o čem mluvím :-D (a to jsem celé stránky vymyslel a napsal sám). A děkuji za (úspěšnou) snahu mě pochopit.

To co mi radil (moc si toho a ochoty vážím) Tomáš123, by na mě stejně bylo moc složité, a tak jsem rád, že jste se shodli, že to není třeba.

Udělal jsem, co mi radili ProbablyYes, Lukáš (ten mi to poslal rovnou jako Feedback ze stránek) a Jan Kozák, který mi to ještě navíc i dobře vysvětlil :-D

A funguje to! Skvěle. Až na jeden poslední problém - v obou jazycích je bublina česky. Poradíte, jak to vyřešit?

Můj formulář teď tedy vypadá takto (a pracuje s PHP scriptem, který jsem dal celý hned v úvodu do dotazu):

<?php
if(isset($_GET['error'])) {
    ?>
    <p class="error">Please fill in all the fields.</p>
    <?php
}
?>

<form method="POST" action="feedback-form.php">

Name:&nbsp;&nbsp;<input type="text" name="form[name]" size="40" required><br>
E-mail:&nbsp;<input type="text" name="form[email]" size="40" required><br>
Comments:<br>
<textarea name="form[comment]" cols="60" rows="10" required></textarea><br>

<input type="hidden" name="form[lang]" value="en" />
<input type="submit" value="Submit">
</form>

Nevěděl jsem, jestli tam mám nechat i tuto část (anebo jestli stačí jen to required):

<?php
if(isset($_GET['error'])) {
    ?>
    <p class="error">Please fill in all the fields.</p>
    <?php
}
?>

Než jsem se vrátil sem, vyzkoušel jsem on-line všechny možnosti (abych vás v případě úspěchu dále neotravoval), tzn. v en verzi to tam nechal, v cz verzi ne, pak v obou ne a nakonec jsem to nechal(radši) v obou verzích.

Výsledek je ale stále stejný: funguje to perfektně, tak jak jsem si přál, ale bublina je pořád jen česky.

Moc si vaší pomoci vážím.

P.S. Mimochodem, je teď tady tímpádem dostupný celý funkční formulář s PHP scriptem, a tak pokud někdo staví stránku a potřebuje odpovědní systém, klidně si ho může celý vzít - rád pomůžu, když můžu :-D
Jurasek
Profil
...........aha............tak ve Firefoxu je to v obou případech česky (jak jsem psal výše) a v IE je to zase v obou případech anglicky...................., jak jsem právě zjistil.

A v Chrome zase česky.
ProbablyYes
Profil
Jurasek:
Jak jsem psal, o zobrazení „bubliny“ se stará dodané „required“ daným inputům ve tvém formuláři. Je to tedy html a tu interpretuje počítač návštěvníka, konkrétně použitý prohlížeč. Pokud půjde o zahraničního návštěvníka, bude používat prohlížeč s jiným jazykem a takový prohlížeč hlášku nevypíše česky, ale jeho vlastním jazykem.
Každý prohlížeč to může zobrazit jinak a jazyk hlášky je závislý na prohlížeči.
Jurasek
Profil
Aha, díky, tak teď už mi to dává smysl: mám český Firefox ale anglický Explorer.

Díky moc vám všem, že jste mi problém vyřešili :-D

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0