PHP paraméterátadás url-ben és szép url-ek htaccess-el

Ismét egy gyakori kérdést dolgoztam fel, amit amatőr php programozók tesznek fel rendszeresen. Szokásomhoz híven igyekszem ismét a már működő de rossz megoldástól a minél szebb megoldás felé haladni. A Többféle megoldás bemutatásának célja, hogy az olvasó ne csak egy kész megoldást kapjon, hanem lássa is az alternatívákat. Hogy ő maga választhasson.


Feltetted már valaha, vagy fel akartad tenni a következő kérdést valakinek?

Hogy lehet olyant csinálni, ami itt ezen az oldalon is van, hogy ilyen kérdőjelek, meg & jelek vannak az url-ben, és úgy változik az oldal tartalma?

Talán nem pont így fogalmazódott meg benned a kérdés, de ha valaha is ott motoszkált a fejedben hasonló, és még nem kaptál rá választ, vagy már kaptál választ, de érdekel többféle módszer, akkor olvasd tovább ezt a bejegyzést és megkapod a választ.

Ezen kívül kitérek még a szép url-ek kérdésére is. Amikor már nem látszik az url-ben sok & jel,
hanem olyan, mintha mindig más mappát nyitna meg. Valójában pedig csak az apache szervernek mondjuk meg, hogy irányítson át egy másik url-re, ami már a fent említett megoldást használja, vagy php-ból szimuláljuk.

Valamit már az elején tisztáznunk kell. Egy URL több részből áll, de beszéljünk csak kettőről. Az egyik az a fájl útvonala a szerveren. A másik pedig változók és értékek sorozata. Ezt a kettőt pedig kérdőjel választja el egymástól.

Valójában a "fájl útvonala" sem biztos, hogy egy az egyben a fájlrendszeri útvonalnak feleltethető meg, de ez az Apache HTTPD szerveren az alapértelmezett viselkedés. Valójában bármilyen kérésre bármilyen válasz érkezhet. Ezt használjuk ki a "szép url-eknél".

utvonal/fajlneve.php?valtozo1=ertek1&valtozo2=ertek2

Egy-egy változó-érték párt & jelek választanak el. Az egyenlőség jeltől balra a változó neve, jobbra pedig az értéke található, pont ahogy azt egyébként is megszokhattuk már PHP-ben is. Már csak azt kellene tudni, hogy ezt egy PHP programban hogyan kell elérni. Erre a $_GET nevű szuperglobális tömb való. Ami attól szuperglobális, hogy bárhol elérhető. Akár egy függvényen belül is. A fenti példából így az "ertek1" -et a következő módon lehetne kiírni.

print $_GET['valtozo1'];

Aki ismeri az elágazások fogalmát, az ezzel már meg is tudja oldani a változó tartalmat. Azért mutatok néhány példát is, ahol az "oldal" és "aloldal" nevű változókat fogom használni. Az első az a bizonyos működő, de nem szép megoldás.

<?php
if ($_GET['oldal'] == 'elso')
{
        print "Ez az első oldal";
}
else if($_GET['oldal'] == 'masodik')
{
        print "Ez a második oldal";
}
else if ($_GET['oldal'] == 'harmadik')
{
        print "Ez a harmadik oldal";
}
else
{
        print "Főoldal";
}
?>

Most aki megpróbálja lefuttatni és nem adja meg az oldal nevű változót az url-ben, annak vagy hiba nélkül lefut, vagy nem. Ez szerver beállítás kérdése. Tehát most, és a jövőben is javaslom az error_reporting függvény használatát az E_ALL paraméterrel (figyelem! Ez egy konstans! Csak azért nem kell idézőjelbe tenni), amivel az ilyen hibák megjeleníthetők. Ezt a programkódok elé kell írni természetesen.

<?php
error_reporting(E_ALL);
if ($_GET['oldal'] == 'elso')
{
        print "Ez az első oldal";
}
else if($_GET['oldal'] == 'masodik')
{
        print "Ez a második oldal";
}
else if ($_GET['oldal'] == 'harmadik')
{
        print "Ez a harmadik oldal";
}
else
{
        print "Főoldal";
}
?>

Erre egy hasonló hibaüzenet fog megjelenni

Notice: Undefined index: oldal in /var/www/phpparams/index.php on line 3

Az ilyeneket pedig nagyon nem szeretjük, tehát meg kell vizsgálni, hogy létezik-e az oldal nevű változó. Erre pedig az isset() -et használhatjuk. Erre is a csúnya módszer:

<?php
error_reporting(E_ALL);
if (isset($_GET['oldal']) and $_GET['oldal'] == 'elso')
{
        print "Ez az első oldal";
}
else if(isset($_GET['oldal']) and $_GET['oldal'] == 'masodik')
{
        print "Ez a második oldal";
}
else if (isset($_GET['oldal']) and $_GET['oldal'] == 'harmadik')
{
        print "Ez a harmadik oldal";
}
else
{
        print "Főoldal";
}
?>

A hibaüzenet eltűnik, mert minden feltételben először ellenőrizve lett a változó létezése is. Itt fontos, hogy a létezés vizsgálata legyen előbb. Másképp a hibaüzenet mindenképp megjelenne. Mégis egy rövidebb megoldást javaslok, ahol a ternáris operátor (ternary operator) siet segítségünkre.

<?php
error_reporting(E_ALL);
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
if ($oldal == 'elso')
{
        print "Ez az első oldal";
}
else if($oldal == 'masodik')
{
        print "Ez a második oldal";
}
else if ($oldal == 'harmadik')
{
        print "Ez a harmadik oldal";
}
else
{
        print "Főoldal";
}
?>

Az $oldal változó a $_GET['oldal'] értékét kapja, ha létezik. Egyébként üreset. De innentől az $oldal biztos, hogy létezik. If helyett lehetne switch elágazással is megoldani.

<?php
error_reporting(E_ALL);
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
switch ($oldal)
{
        case 'elso':
                print "Ez az első oldal";
                break;
        case 'masodik':
                print "Ez a második oldal";
                break;
        case 'harmadik':
                print "Ez a harmadik oldal";
                break;
        default:
                print "Főoldal";
                break;
}
?>

A break-re szükség van, hogy csak az a kód fusson le, amelyik case utáni érték megfelel az $oldal változónak. A default pedig az if-ekbeni else ág alternatívája.

Ezzel már lehetne is kezdeni valamit. De ha már sokkal több kódot kéne írni egy feltételnek megfelelve, akkor ez így nem praktikus. Helyette az include használata javasolt. Ezzel lehet fájlokat importálni. És így külön fájlokba csoportosíthatók a forráskódok. Minden oldal forráskódja egy-egy fájlban lehet.
Létezik a párja, a require. Ez, ha nem található a fájl, akkor megszakítja a program futását. Mindkettőnek van egy olyan verziója, ami _once -ra végződik. (require_once, include_once) Ezekkel pedig, ha már egyszer be lett hívva az adott fájl, többször nem próbálja meg.

<?php
error_reporting(E_ALL);
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
switch ($oldal)
{
        case 'elso':
                include 'oldalak/elso.php';
                break;
        case 'masodik':
                include 'oldalak/masodik.php';
                break;
        case 'harmadik':
                include 'oldalak/harmadik.php';
                break;
        default:
                include "oldalak/fooldal.php";
                break;
}
?>

A példában az oldalak forráskódjai az "oldalak" nevű mappában levő fájlokban vannak. Észrevehető, hogy a fájloknak azonos nevet adtam, mint az átadott oldal változó értékei. Így még ennél is rövidebb megoldás lehet, ha egyszerűen a változó értékét behelyettesítjük az include-ba. Itt viszont arra kell figyelni, hogy beírható akár a ../index vagy a mappa/fajl is. Akkor pedig bármilyen fájlt meg lehet nyitni és így lefuttatni, ami nem szerencsés. Ebben segít a basename() függvény, ami az utolsó / utáni részt vágja le és adja vissza. Illetve a file_exists, amivel egy fájl létezése vizsgálható. Ha nem létezik, akkor a főoldalt jelenítjük meg.

<?php
error_reporting(E_ALL);
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
$oldal = 'oldalak/'.basename($oldal).'.php';
if (file_exists($oldal))
{
        include $oldal;
}
else
{
        include 'oldalak/fooldal.php';
}
?>

Aki figyelt, észrevehette, hogy még ezt is lehet rövidíteni a már ismert ternáris operátorral.

<?php
error_reporting(E_ALL);
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
$oldal = 'oldalak/'.basename($oldal).'.php';
include (file_exists($oldal)) ? $oldal : 'oldalak/fooldal.php';
?>

Azért ahhoz képest, hogy milyen hosszú volt az első kód, egész rövid lett és sokkal többet is tud. Ideje tehát újabb szintre lépni. Eddig is szempont volt a szép kód. De ha már szempont, akkor azt is jó megtanulni, hogy célszerű a php kódokat a fájlok elejére gyűjteni. És a html kód belsejében főleg csak kiírásokat alkalmazni, esetleg includeokat. Tehát az include helyett előbb még csak változóba kellene tenni a fájlnevet, és egy html dokumentum-ban includeolni.

<?php
error_reporting(E_ALL);
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
$oldal = 'oldalak/'.basename($oldal).'.php';
$oldal = (file_exists($oldal)) ? $oldal : 'oldalak/fooldal.php';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>PHP paraméterek</title>
    </head>
    <body>
                <ul>
                        <li><a href="index.php">Főoldal</a></li>
                        <li><a href="index.php?oldal=elso">Első</a>
                                <ul>
                                        <li><a href="index.php?oldal=elso&amp;aloldal=koszon">Köszön</a></li>
                                </ul>
                        </li>
                        <li><a href="index.php?oldal=masodik">Második</a></li>
                        <li><a href="index.php?oldal=harmadik">Harmadik</a></li>
                </ul>
                <?php include $oldal ?>
        </body>
</html>

Ezzel egy menüt is gyártottam, hogy könnyebb legyen a tesztelés. Megfigyelhető, hogy az & helyén én &amp; -ot írtam. Ez azért van, mert bár az url-ben & ként kell szerepelnie, html-ben vannak bizonyos karakterkódok, amik pont & -el kezdődnek. Maga az & jel is éppen ilyen, aminek a kódja az &amp;. Egyébként is működhetne, de adott esetben akár hibát is okozhatna. Minden esetre a html szintaktika hibás lenne tőle akkor is, ha jól jelenik meg az eredmény.

Az html-ből látszik, hogy van az elso.php-ben egy aloldal is. Annak forráskódja ugyanúgy épülhet fel, mint a főoldal kiválasztása. Csupán más változónevet kell használni. És például ha van egy oldalak/elso.php, akkor annak aloldalai az oldalak/elso/ mappába kerülnek. És ebből a mappából lesznek includeolva. Ott már persze nem kell a komplett html "körítés", mert egyszer már megvolt. Tehát így nézne ki az elso.php, ha további fájlokra osztott aloldalakat használna:

<?php
error_reporting(E_ALL);
$aloldal = isset($_GET['aloldal']) ? $_GET['aloldal'] : '';
$aloldal = 'oldalak/elso/'.basename($aloldal).'.php';
$aloldal = (file_exists($aloldal)) ? $aloldal : 'oldalak/elso/fooldal.php';
include $aloldal;
?>

De jelenleg a példámban én csak a következő egyszerű forrást használtam, mivel csak egy rövid szöveg kiírásának eldöntéséről volt szó:

<?php
$aloldal = isset($_GET['aloldal']) ? $_GET['aloldal'] : '';
if ($aloldal == 'koszon')
{
        print 'Szia';
}
else
{
        print 'Nem köszönök';
}
?>

Bármelyik megoldást is választjuk, jobb mindenképp más változóneveket használni, mint a főoldalban. Mert jelen felépítés mellett felülírhatja az aloldal változója a főoldalét, és ezt nem biztos, hogy szeretnénk.

Ha már szépség, ne aprózzuk el! Apache szervernél használhatók .htaccess fájlok, amennyiben a szerveren engedélyezve van a használata. Ez nem kiterjesztés, hanem a fájl neve. Ponttal kezdődik, ami linux rendszereken a rejtett fájlok jellemzője. Ebbe lehet olyanokat írni, amit az apache szerver értelmezni tud.

Htaccess engedélyezése:
Általában egy httpd.conf nevű fájlt kell keresni a szerver mappájában. Ez nem a webgyökér könyvtárat jelenti, hanem ahova a szerver program lett feltelepítve! Nálam viszont ubuntu rendszeren ez a /etc/apache2/sites-available/default nevű, kiterjesztés nélküli fájl. amiben a következőhöz hasonlót kell keresni:

<Directory /var/www>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride none
        Order allow,deny
        allow from all
</Directory>

Az AllowOverride direktíva felel a htaccess-ek engedélyezéséért. Ha none van megadva, akkor tiltja. Át kell írni All -ra, és akkor a Directory tag-ben megadott mappában engedélyezi őket.

<Directory /var/www>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all
</Directory>

Persze, hogy ne legyen egyszerű az életünk, magát a mod_rewrite modult is engedélyezni kell, ha még nem volt. Ugyanis erre szükség lesz. Ehhez ubuntun a /etc/apache2/mods-enabled mappába kell tenni egy rewrite.load nevű fájlt, aminek a tartalma a következő.

LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so

Máshol is hasonló módon kell, csak máshol lehet nincs külön fájl erre, hanem a httpd.conf -ban van egy hasonló sor, és az elől kell kivenni a kettős kereszt jelet. Természetesen ezek után a beállítások után újra kell indítani a webszervert.

A mod_rewrite modul használata
Hozz létre az index.php mellett egy .htaccess nevű fájlt. A tartalma a következő legyen

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /phpparams/

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^([^/]+)(/([^/]+))? index.php?oldal=$1&aloldal=$3&%{QUERY_STRING}
</IfModule>

A RewriteBase után a saját mappád útvonalát írd, ahol az index.php-d van. Innentől fog számítódni a RewriteRule-ban a minta. Az egész egy IfModule tag-ben van, hogy csak akkor próbálja értelmezni az apache, ha a modul engedélyezve van. És miután engedélyezve van, még be is kell kapcsolni. Ezt végzi a RewriteEngine On sor. A két RewriteCond utasítás sorban a következőket jelenti: Csak akkor, ha nem létezik ilyen fájl, és nem létezik ilyen a mappa sem. A RewriteRule után először egy reguláris kifejezés jön, majd az az url, amire le kell cserélni, ami illeszkedik a kifejezésre. Itt konkrétan annyit tesz, hogy az első mappanevet az $1 változóba teszi, és ha van második mappa, akkor azt a $2 változóba. Majd a %{QUERY_STRING} változót még az url végére kell tenni, így a továbbra is változókként átadott értékek is megmaradnak. Az url most ilyesmi lesz:

http://hoszt/phpparams/elso/koszon

Az index.php

<?php
error_reporting(E_ALL);
$host = 'http://domained.hu';
$base = '/phpparams/';
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
$oldal = 'oldalak/'.basename($oldal).'.php';
$oldal = (file_exists($oldal)) ? $oldal : 'oldalak/fooldal.php';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>PHP paraméterek</title>
                <base href="<?php print $host.$base ?>" />
    </head>
    <body>
                <ul>
                        <li><a href=".">Főoldal</a></li>
                        <li><a href="elso">Első</a>
                                <ul>
                                        <li><a href="elso/koszon">Köszön</a></li>
                                </ul>
                        </li>
                        <li><a href="masodik">Második</a></li>
                        <li><a href="harmadik">Harmadik</a></li>
                </ul>
                <?php include $oldal ?>
        </body>
</html>

Egy másik megoldás a következő:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /phpparams/

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . index.php

</IfModule>

Itt a szabály már sokkal rövidebb. A pont jelenti, hogy az egész fájlnevet cserélje le az index.php-re jelen esetben. Ezzel viszont nem kerülnek a $_GET -be az oldal és aloldal változók. Viszont az index.php-ben a $_SERVER['REQUEST_URI'] változóból továbbra is kinyerhetők. A következő kódot kell írni a fájl elejére még:

$host = 'http://domained.hu';
$base = '/phpparams/';
$baselength = strlen($base);
$url = substr($_SERVER['REQUEST_URI'],$baselength);
$url = array_merge(array('path'=>''),parse_url($url));
$get = explode('/',$url['path']);
$_GET['oldal'] = ($get) ? array_shift($get) : '';
$_GET['aloldal'] = ($get) ? array_shift($get) : '';

A $base változóba ugyanazt kell írni, mint a .htaccess fájlban a RewriteBase után. Ezt majd a html-ben is meg kell adni a <base> tag-ben a fejlécben. A

$baselength = strlen($base);
$url = substr($_SERVER['REQUEST_URI'],$baselength);

sorok vágják le a project gyökérkönyvtár előtti útvonalat. Vagyis marad az elso/koszon Persze még a végén ott maradhatnak a ?valami=akármi -ként átadott paraméterek is, de most csak az útvonal kell. És annak minden mappáját egy tömbbe tenni. Ezt teszi a következő két sor:

$url = array_merge(array('path'=>''),parse_url($url));
$get = explode('/',$url['path']);

Az array_shift függvénnyel a tömb első elemét lehet kivenni és egyben visszaadni változóba. Az oldal és aloldal változónál is meg kell tenni. Ezt teszi az utolsó két sor, amit már nem idézek újra.

Tehát az index.php most:

<?php
error_reporting(E_ALL);
$host = 'http://domained.hu';
$base = '/phpparams/';
$baselength = strlen($base);
$url = substr($_SERVER['REQUEST_URI'],$baselength);
$url = array_merge(array('path'=>''),parse_url($url));
$get = explode('/',$url['path']);
$_GET['oldal'] = ($get) ? array_shift($get) : '';
$_GET['aloldal'] = ($get) ? array_shift($get) : '';

$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
$oldal = 'oldalak/'.basename($oldal).'.php';
$oldal = (file_exists($oldal)) ? $oldal : 'oldalak/fooldal.php';
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>PHP paraméterek</title>
                <base href="<?php print $host.$base ?>" />
    </head>
    <body>
                <ul>
                        <li><a href=".">Főoldal</a></li>
                        <li><a href="elso">Első</a>
                                <ul>
                                        <li><a href="elso/koszon">Köszön</a></li>
                                </ul>
                        </li>
                        <li><a href="masodik">Második</a></li>
                        <li><a href="harmadik">Harmadik</a></li>
                </ul>
                <?php include $oldal ?>
        </body>
</html>

A html <base> tag -ben lehet megadni azt az url-t, amit a weblapon minden url elé be kell tenni.

Azt hiszem, erről a témáról ennyit tudtam beszélni. Remélem segítettem valakinek vele. Éppen lehetne még felturbózni a megoldást, hogy ki- és bekapcsolható legyen a szép url-ek használata, de egyelőre talán ez is elég lesz :)

Kategóriák: 
Megosztás/Mentés

Hozzászólások

neogeo2 képe

Hasznos infó volt!
KÖSZÖNÖM!

Láng András képe

Megmondom őszintén nem értem elsőre az itt leírtakat, autodidakta módon sajátítottam el a weboldalkészítést, ennek megfelelően sablonokat használok elsősorban, azonban első ránézésre is nagyon hasznosnak tűnt a leírás, - majd pár nap alatt feldolgozom és hasznosítom... szükség van rá!! :)

köszi!

Rimelek képe

autodidakta módon sajátítottam el a weboldalkészítést

Mint ahogyan a legtöbben :) Ez egy ilyen téma. Sok sikert hozzá!

miki képe

Tök jó , csak nem akar összejönni a paraméter átadás.
a honlapon bekérem az adatokat input, átadom a php programnak, de az nem látja.

Rimelek képe

Részleteznéd a problémát? Hogy kéred be a paramétert és hogy próbálod meg felhasználni a programban? Használod a "szép url" részét is? Vagy csak a GET átadása nem megy?

miki képe

A problémám a következő: Irtam egy honlapot amibe html, css, javascriptet használok. php-t nem, mert azt most tanulom. A kapcsolat oldalon bekérem a nevet email-t várost stb, input -al Gondoltam átadom a paramétereket a php programnak és az elküldi a levelet imigyen:.

level_kuld.php?v1=lastname&....
aztán igy is
<a href="level_kuld.php?v1=<?= $lastname?> &v2=<?= $firstname?>">
nem működött.

Végül megoldottam (javascriptel), de szerettem volna php-vel és paraméter átadással megoldani.

Ja és nem szerettem volna átirni a html programot.

a html kódból:
az elején:
// <![CDATA[

jQuery(document).ready(function(){
        $('#contactform').submit(function(){                             
                var action = $(this).attr('action');
                $.post(action, {
                        lastname: $('#name').val(),
                        firstname: $('#firstname').val(),
                        email: $('#email').val(),
                        phone: $('#phone').val(),
                        fax: $('#fax').val(),
                        city: $('#city').val(),
                        address: $('#address').val(),
                        zipcode: $('#zipcode').val(),
                        comment: $('#comment').val()
                },
                        function(data){
                                $('#contactform #submit').attr('disabled','');
                                $('.response').remove();
                                $('#contactform').before('<p class="response">'+data+'</p>');
                                $('.response').slideDown();
                                if(data=='Message sent!') $('#contactform').slideUp();
                        }
                );
                return false;
        });
});

// ]]>

a mezők bekérése:

<form action="level_kuld.php" method="post" id="contactform">
        <div class="field">
                <label for="lastname">Vezetéknév:<span title="Kötelezően kitöltendő" class="req_asterisk">*</span></label>
                                                <input type="text" name="lastname" id="lastname" maxlength="60" class="wide required" />
        </div>

a php kód:

<?php

if(!$_POST) exit;

$email = $_POST['email'];

//$error[] = preg_match('/\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i', $_POST['email']) ? '' : 'INVALID EMAIL ADDRESS';
if(!eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*" ."@"."([a-z0-9]+([\.-][a-z0-9]+)*)+"."\\.[a-z]{2,}"."$",$email )){
        $error.="Invalid email address entered";
        $errors=1;
}
if($errors==1) echo $error;
else{
        $values = array('lastname','firstname','email','phone','fax','city','address','zipcode','comment');
        $required = array('lastname','firstname','email','phone','fax','city','address','zipcode','comment');
         
        $your_email = "mikilaci1@gmail.com";
        $email_subject = " ".$_POST['subject'];
        $email_content = " \n";
       
        foreach($values as $key => $value){
          if(in_array($value,$required)){
                if ($key != 'firstname' && $key != 'lastname' && $key != 'email') {
                   if( empty($_POST[$value]) ) { print 'PLEASE FILL IN REQUIRED FIELDS'; exit; }
                }
                $email_content .= ' '.$_POST[$value]."\n";
          }
        }

        if(@mail($your_email,$email_subject,$email_content)) {
                print 'Message sent!';
        } else {
                print 'ERROR!';
        }
}
?>

igy megy

Bocs, a zavarásért, egyébként Tőled kaptam egy csomó hasznos infót úgyhogy köszönöm. Azért kíváncsi lennék miért nem ment

Rimelek képe

Ez a programkód szintaktikai hibás. A mailto linknél. Azon túl, ha jól látom, megmutattad az elvileg működő kódot, és csak utaltál a rosszra.

Nem értem például, mit értesz ez alatt:
level_kuld.php?v1=lastname&....

A v1 után a lastname változó akart volna lenni? Vagy csak kipróbáltad, hogy maga a lastname átkerül-e, mint szöveg?

És ez:
<a href="level_kuld.php?v1=<?= $lastname?> &v2=<?= $firstname?>">

Annyiban hibás, hogy a <?= kiírást nem célszerű használni. Nem biztos, hogy működik. Ez viszont igen:
<a href="level_kuld.php?v1=<?php echo $lastname?> &v2=<?php echo $firstname?>">

Abban a kódban, amiről azt írtad, működik, post metódussal küldöd az űrlapot és $_POST változóból veszed a változókat. Az első példáidban viszont url-ben küldöd, ahol ugyanezt a $_GET változóból kellene venni. Az e-mailküldést viszont ne GET-tel csináld soha!

Egyébként a javascriptben is POST-tal küldöd el az adatokat. Én a cikkben végig GET-ről írtam. Elvégre a címe is az url-ről szól.

Az eregi függvény is elavult. Nem ajánlott használni. A preg_match hasonló. Annak a használatának nézz utána. De ezt csak plusz információként mondom. Az eregi is van, ahol működhet. De nem garantált, hogy minden szerveren hibaüzenet nélkül.

UI: Láthatod, hogy kiszíneztem a kódjaidat. Ezt te is megteheted és tedd is meg kérlek, ha forráskódot illesztesz be! Itt az üzenet űrlap alatt láthatod a listát, hogy milyen forráskódot hogyan színezhetsz.

HTML: <html5>Ide a html kód</html5>
PHP: <php>Ide a php kód</php>
Javascript: <javascript>Ide a javascript kód</javascript>
Színezés nélküli kód: <code>Ide a kód</code>

miki képe

Köszönöm
Megint segitettél

Katona András képe

Helo. Nagyon jó ez a leírás. Erre voltam pontosan kíváncsi, hogy mire jó ez php-s url. Ráadásul magyar leírást csak ezt találtam erről a témáról.

Viszont felmerült bennem egy kérdés. Ha pl. a "lapok" mappán belül van még egy mappa, és abban van a fájl amit megszeretnék jeleníteni az includolt változónál, azt hogy tudom elérni? Hogy kell paraméterezni az url-t?

Tehát:
index fájl: lapok/index.php
másik fájl: lapok/egyeb/egyeb.php

Válaszod előre köszönöm! :)

Rimelek képe

Üdv. Teljesen mindegy, hogyan paraméterezed az url-t. A lényeg, hogy az url-át vizsgálva valamilyen php fájlt beillesztesz és ezzel lefuttatsz. Az utolsó teljes példámban arra mutattam megoldást, a főoldalak egy konkrét mappában vannak. Nálam ez az "oldalak" volt. De hívhatod "lapok"-nak is. Amint a főoldalt kiválasztod, a főoldalt tartalmaző php fájlban kezelheted az aoldalait. Hasonlóképpen, mint a főoldalt is a fő fájlban. Ha csak az "egyéb" oldalakat akarod elkülöníteni, ami szintén főoldal, de valamilyen módon kategórizálod őket, akkor is használhatod a főoldal és aloldal megoldást. De azt is megteheted, hogy egyszerűen ott is keresed a fájlokat, ha a fő mappában nem találtad meg. Ez csak egy feltétel. Ha létezik a fájl a főmappában, akkor include. Ha nem létezik, akkor ha létezik az egyeb mappában, akkor include. Ha ott sem, akkor hibaüzenet.

De bárhogyan kezelheted a problémát, ahogy logikusnak találod. Például készíthetsz egy tömböt is arról, hogy melyik oldalad melyik php fájlban van. És így amikor jön az url-ből az "oldal" változó, akkor nem a lapok/$oldal.php -t include-olod, hanem a lapok/$oldalak[$oldal] fájlt.

<?php
error_reporting(E_ALL);
$oldalak = array(
    'mittudomen' => 'egyeb/mittudomen.php',
    'eztsetudom' => 'eztsetudom.php',
    'hmm' => 'gondolkodo/oldal.php'
);
$oldal = isset($_GET['oldal']) ? $_GET['oldal'] : '';
$oldal = 'oldalak/'.$oldalak[$oldal]);
include (file_exists($oldal)) ? $oldal : 'oldalak/fooldal.php';
?>

Így a 'mittudomen' értékre az oldalak/egyeb/mittudomen.php tölt be. De a 'hmm' értékre az oldalak/gondolkodo/oldal.php.

Ezeket csak érdekességnek írtam. De a legegyszerűbb, ha ilyen esetben maradsz a switch elágazást használó megoldásnál. És akkor tényleg azt includeolsz, amit akarsz.

Anonymous képe

Hello.

Az index.php hivatkozásból történő kiiktatásáról, a mod_rewrite-tal kapcsolatban kérdeznék.
Joomla 2.5+Virtuemart2.0 párosítást használok, webáruházhoz.
Elsőre azt tippelem, a Keresőoptimalizálási beállítások-nál, "A Keresőbarát URL-címek"et és "Az URL-átírás használata"t - IGENre kell állítani (?)

Az én esetemben már létezik .htaccess file, a gyökérben (itt található az index.php is)
Az általad javasolt

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /phpparams/
 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
 
RewriteRule ^([^/]+)(/([^/]+))? index.php?oldal=$1&aloldal=$3&%{QUERY_STRING}
</IfModule>

utasítást ebbe a meglevő .htaccess-be kellene elhelyeznem?

Az aggaszt, hogy az index.php kiikatásával kapcsolatban több javaslatot is találtam a neten.

Az egyik az általad javasolt

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /phpparams/
 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
 
RewriteRule ^([^/]+)(/([^/]+))? index.php?oldal=$1&aloldal=$3&%{QUERY_STRING}
</IfModule>

Egy másik pl

<IfModule mod_rewrite.c>

# Enable Rewrite Engine
# ------------------------------
RewriteEngine On
RewriteBase /

# Redirect index.php Requests
# ------------------------------
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{THE_REQUEST} !/system/.*
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,L]

# Standard ExpressionEngine Rewrite
# ------------------------------
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]

</IfModule>

Vagy

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Send would-be 404 requests to Craft
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
    RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>

De azzal is találkoztam, hogy bizonyos esetben (ha a mod_rewrite nincs engedélyezve a szerveren) ajánlatos az <IfModule> </IfModule> elhagyása.
"It's also better to leave out the <IfModule> lines. If mod_rewrite isn't enabled on your server, you want to see an error message, not spend hours trying to figure out why your links don't work properly."

A szerverhez nincs közvetlen hozzáférésem. Az <IfModule> kihagyásával bepróbálhatom ezeket a "Rewrite"-okat? És melyiket - az említettek közül?
Félve nyúlok a kódokhoz :) - mert már tudom, hogy nem mindig célravezető ha valami beég az adatbázisba :)

Előre is köszönöm.
Üdv, A.

Rimelek képe

Üdv. Joomlaval és beállításaival kapcsolatban nem tudok nyilatkozni. De ha be lehet kapcsolni benne az URL átírását, akkor elvileg kell is lennie benne már egy kész megoldásnak arra, hogy azt le is kezelje. És akkor neked is azokat kéne követni.

Így Joomlatól függetlenül válaszolok a kérdésedre. De ha bele kell írni a htaccess-be, akkor minden bizonnyal abba, ami már létezik, ha létezik.

A leírt megoldások bármelyike jó lehet. Csak azt kell megérteni, melyik mit csinál. És hogyan tudod kezelni aztán a paramétereket.

Az én megoldásom főleg azoknak készült, akik csak szeretnék megérteni a rewrite modul használatát alap szinten. Komolyabb oldalaknál már inkább átadják az egész útvonalat valahogy a php fájlnak. És az szétdarabolja, ahogy tetszik. Az egyes részei alapján pedig eldönti, mit töltsön be. Ezt az elvet követi a második és harmadik megoldás is.

A második megoldás még azt is megnézi, hogy ha a HTTP kérés GET metódussal érkezett (tehát egy POST-tal küldött űrlapnál nem) és szerepel benne az index.php is, de nincs benne a "/system" (mert mondjuk az máshova van irányítva), akkor az index.php/valami útvonalakat átirányítja arra az URL-re, ahol nincs benne az index.php.

A "Standard ExpressionEngine Rewrite" pedig (bár én még így nem láttam használni változót, ahogy az első RewriteCond-ban van) megadja, hogy bizonyos kiterjesztésű fájlokat akkor sem irányít az index.php-re, ha azok egyébként nem léteznek. Ez is egy hasznos feltétel lehet. De ha nem használod, akkor sincs katasztrófa. Az oldal működni fog, csak ha vannak hibásan linkelt képek, css-ek a forrásban, akkor az mind betölti a php-t is. És ott kell lekezelned ezt az esetet. Kevésbé hatékony. De lehet, hogy egyszer pont ez kell.

Ebben a megoldásban még kiemelném, hogy nem kérdőjel után a hagyományos query string-ben adja át az útvonalat, hanem egyszerűen egy / jellel folytatva az index.php-t. Nem biztos, hogy a szerver ezt támogatja. Őszintén megmondom, nem tudom, mennyire megszokott. De például a Symfony keretrendszer is erre alapozza az URL-jeit. Mivel én állítottam össze hozzá a szervert és elsőre nem figyeltem erre, nálam akkor nem működött.

A harmadik megoldásban pedig átadja az útvonalat egy q változónak az URL-ben. Teljesen jó ez is. Itt csak a favicon és még egy mintának megfelelő png fájlok vannak kivételbe rakva, hogy azokat ne adja át a php-nek, ha nem léteznek.

Használja még a QSA-t (Query String Append), amitől a query stringet is átadja az átírt url után. Ezt a második megoldás nem tette. Így egy ilyen URL-ből: "/utvonal?valtozo=ertek" elveszne a valtozo=ertek (de már régen játszottam rewrite-tal)

Tehát ezeket figyelembe véve kell egyik vagy másik megoldást alkalmazni. Akár vegyesen. Nincs kőbe vésve a megoldás. Igény szerint kell kialakítani.

A második megoldásban az útvonalat a $_SERVER['REQUEST_URI'] -ban találod. Míg a harmadikban a $_GET['p'] -ben.

Az IfModule -t pedig tényleg el is lehet hagyni, ha a rewrite modul szerves része az oldalnak. Ha volna olyan eset, amikor az oldal a rewrite nélkül is képes működni, csak valami plusz funkcionalitást nyújtana valahol, akkor kellene. Most nem tudok ilyen esetre példát mondani. De jogos az érvelés a hibaüzenettel kapcsolatban.

Anonymous képe

2 nap szenvedés után. Vééééégre!!! Köszönöm Uram!! Köszönöm :D

Anonymous képe

A fenti htaccess kódhoz, hogyan tehetek hozzá olyan kódot, ami keresés, hely és keresés query-vel?
Tehát a jelenlegi: index.php?oldal=elsooldal&aloldal=elsoaloldal ==> page.hu/elsooldal/elsoaloldal
És én ehhez szeretnék egy ilyesfélét: index.php?oldal=elsooldal&hely=kereseshely&kereses=keresesneve ==> page.hu/elsooldal/kereseshely/keresesneve

És mindezt úgy, hogy $_GET-ben is submit gombbal lejátssza, mert valahogy nem engedte, vagy az volt a probléma, hogy ha hozzáírtam a keresés htaccesst, a mellette levő ez a tutorialban levő kód nem működött.

Rimelek képe

Fent több htaccess-t is írtam. Melyik megoldásra gondolsz? Amiben minden szabályt külön írsz le benne, vagy amiben mindent az index.php-re irányítasz? Ez a kétszintű oldalkezelés egy általános megoldás. Ha neked további argumentumaid vannak, az is megoldható, de bonyolítja a helyzetet, ezért a második megoldást javaslom hozzá. Amikor mindent az index.php-re irányítasz (vagy egy kiválasztott fájlra speciális esetben) és abban a fájlban php-vel sokkal egyszerűbben dolgozhatod fel, mi történjen a kapott URL alapján.

Még tudom javasolni a Konfigurálható szép url-ek htaccess-el cikket is, amiben még írtam a témáról.

Az űrlapoknál a legegyszerűbb, ha elküldöd POST-tal az adatokat és egy átirányítással a megfelelő url-re dobod a felhasználót.

Egyelőre ennyit tudok csak írni. Próbálkozz és ha nem megy, akkor még próbálok segíteni.

Anonymous képe

Köszönöm szépen a segítséget! :)
A második megoldással és az űrlap POST átirányításával sikerült! :

Anonymous képe

Vagyis hát azt hittem, hogy sikerült :(
header-rel próbáltam átirányítani, maga a cím át is irányítódott, viszont ezzel eltűnt a kért adat a $_POST-ból.
header:
header("Location:/keresesek/". $hely_url ."/". $kereses_url ." ");
Így tehát átirányított, viszont minden elemet megjelenít, nem csak azt, amit a POST-tal kerestem.

Rimelek képe

Épp a postban levő értékek alapján kell átirányítani, hogy így a postra már ne legyen szükség és minden az url-ben legyen. Ha neked a fenti két komponensen kívül van még egy harmadik is, amit nem akarsz vagy nem tudsz az url-be útvonalként beépíteni, akkor azt add meg query stringként.

Anonymous képe

Ez az egész POST, tulajdonképp a két adaton kívül (hely,keresés query) csak ki szeretném íratni az adott helyen. header tehát átirányítja, azonban az adatot nem tudom hol kiíratni, próbáltam úgy, hogy a foreach előtt beszúrok egy $_GET[]-et, de sajnos sehogy sem jeleníti meg a megfelelő célon

 if(isset($_POST['searching'])){
                                $kereses = $_POST['q'];
                                $hely = $_POST['county'];
                                $kereses = preg_replace("[^ 0-9a-zA-Z]", " ", $kereses);
                                $hely = preg_replace("[^ 0-9a-zA-Z]", " ", $hely);

                        $result = $info->Search($kereses);
                        if($result) {
                                header("Location:/keresesek/". (empty($hely) ? '' : "". $hely ."/" ) . $kereses ." ");
                                foreach( $result as $row ) {
                                        echo '
                                                        '
. $row['keresestalalat']. ' <br />
                                                        '
. $row['keresesleiras']. ' <br />';
                                        }}}

Rimelek képe

Miután csak akkor keresel, amikor a POST-ot megkapod, majd átirányítasz, utána nem lesz mire keresni. A POST-ot csak arra!! használd, hogy legyen miből átirányítani. Ne ott futtasd a search metódust! Az átirányítás után (ha az én leírásomból dolgoztál), akkor valamelyik $_GET változóban lesz az egész útvonal. /keresesek/hely/kereses. És ezt feldolgozhatod php-vel. Ha a javasolt konfigurálható szép url-ek cikkből indulsz ki, akkor ott ezt reguláris kifejezésekkel úgy érheted el, hogy az eredményt bármilyen GET változóba beleirányíthatod. De anélkül nincs semmid az útvonalon kívül. Amit ismerve a felépítését, feldolgozhatsz egy egyszerú explode() függvénnyel a per jelek mentén feldarabolva az útvonalat. Egy tömböt kapsz és annak az utolsó elemét kell átadnod a search metódusnak.

Anonymous képe

Most már közelebb járok sokkal, azonban most abba a gondba ütköztem, hogy ugyebár én úgy szeretném lebonyolítani, hogy ../hely/kereses, viszont ezt több formába, tehát
ha ../hely akkor kilistáz mindent, ami a helyhez vonatkozik,
ha pedig ../hely/kereses akkor a hely alapján keresi meg a keresési kulcsszavakat,
ha pedig ../kereses akkor simán helytől függetlenül keresi meg a kulcsszavakat.
Itt annyi a problémám, hogy ezt így a kód nem tudja felfogni, hogy mikor is keres az user hely, és sima keresés alapján, hisz az aloldal, aloldal2 változik, ha másabbak a keresési feltételek

eddig ilyesmi megoldásokkal próbálkoztam, de ugyebár ilyenkor kell előjönnie a fenti problémának

if (!empty($aloldal) && !empty($aloldal2))
{
        $kereses = $aloldal2;
        $hely = $aloldal;
        $result = $info->SearchByPlace($kereses,$hely);
}

else {
        $kereses = $aloldal;
        $result = $info->Search($kereses);
}

Aztán még ez az egész annyival bővülne ki, hogy ../hely/kereses/page/oldalszám, ami szintúgy változik ezek után, hisz ../hely/page/oldalszám, így a page-t venné a keresésnek, tehát lejjebb csúszik egy változóval.

Rimelek képe

Továbbra is a konfigurálható szép url-ek cikket javaslom, amit linkeltem neked korábbi hozzászólásban. Gyakorlatilag két szabályt kellene írnod vele. Így nézne ki:

$patterns = array(
     '^(?P<hely>[^/]+)/(?P<kereses>[^/]+)(/page/(?P<oldalszam>\d+))?',
     '^(?P<kereses>[^/]+)(/page/(?P<oldalszam>\d+))?',
);

Ha valamit elgépeltem volna, akkor elnézést. Nem próbáltam ki, de nagyjából így kell elképzelni.

Anonymous képe

Átírtam konfigurálhatóak alapján, viszont itt is ugyanabba botlok, ha csak hely alapján keresek, akkor a hely lesz a keresési kulcsszó

tehát a $_GET['URL'] kiíratása után egyik esetben ezt kapom:
keresesek/valami/page/1
itt:
keresesek => oldal
valami => hely
page => keresési kulcsszó, ennek az értéke "valami"-nek kellene lennie
1 => ez pedig a "page" lenne
míg a másikban:
keresesek/kukutyin/valami/page/1

itt:
keresesek => oldal
kukutyin => hely
valami => keresési kulcsszó
page => page
1 => 1
tehát ebben az esetben helyes lehetne

Anonymous képe

Szia.
Segítségedet szeretném kérni, az általad mutatott megoldáshoz.
.htaccess: RewriteRule . index.php használom és minden szépen működik, 2 dolgot kivéve.
1. Kép méretezőm külön van (background:url(kepmeretez?kepnev=...), ezt hogy lehet újra működésre bírni.

Rimelek képe

Helló, feltétel kell neked. Ha a kepmeretez oldalt egy másik htaccess kezeli, akkor, feltételezve, hogy az oldalad a gyökérmappában van, valami ilyesmi:

RewriteCond ${REQUEST_URI} !=/kepmeretez
RewriteRule . index.php

Vagy beteheted az összes olyan fájlt egy almappába, amit nem kell htaccess-szel feldolgozni és akkor így nézne ki:

RewriteCond ${REQUEST_FILENAME} !^/kivetelmappa/
RewriteRule . index.php

Utóbbi reguláris kifejezésként ellenőrzi a fájl útvonalának elejét.

De az első megoldás elég kell legyen.

UI: Sokadik szerkesztés után remélem már jól megértettem a kérdést és jól válaszoltam.