Aloittelen php:n koodaamista olio-pohjaisesti.
Onko oikeaoppista kirjoittaa suoraa koodia eli iffiä jne. toisensa perään ja väliin aina funktioita, mikäli ko. funktiota tarvitsee useampaan kertaan? Vai onko jotenkin "siistimpää" tehdä enemmänkin funktioita, vaikkei niitä tarvitsisi kuin sen yhden ainoan kerran?
Harjoittelen tekemällä "web-kauppaa". Olenko oikeilla jäljillä, kun Olio-luokkina mulla on mm. Tuote ja Uusi_Kayttaja (eli siis aika pitkälle tietokannan taulusta tulee suoraan yksi olio)?
Olen tosiaan aika aloittelija, joten anteeksi jos kysymykseni olivat ihan hassuja.. :) Kiitos asiallisista vastauksista!
Ai niin, kertokaa vielä (jotta mä kehtaa kysyä irl-kaverilta neuvoa), lausutaanko apache "apashe" vai "apakhe"? :)
Kyllä nuo oliot ihan järkeviltä kuulostavat, en ole tosin olioiden kanssa leikkinyt pitkään aikaan. Niin siis sen luokan sisään laitetaan toiminta ja toiminnallinen osio on sitä "iffiä peräperää" eli kutsutaan niitä olioita ja tehdään halutut asiat (jos tämä nyt mitään selventää). Ja minä lausun ihan "apassi", englanniksi taitaa mennä näin jos nuo äännemerkit mitään sanovat.
LAMP on itselleni tutumpi sana webbimaailmasta:
Linux, Apache, MySQL ja PHP
Uskon että web-kauppaa varten joudut tekemään satoja rivejä koodia eri tiedostoihin. Kerää funktiot omaan tiedostoon jonka liität nätisti muihin:
<? include "inc/funtiot.php"; ?>
kasetti kirjoitti:
LAMP on itselleni tutumpi sana webbimaailmasta:
Linux, Apache, MySQL ja PHP
<offtopic>Kas, minä käytän sitten näköjään NLPR-ympäristöä: NetBSD, Lighttpd, PostrgreSQL ja Ruby ^___^</offtopic>
Mutta siis tarvitseeko _aivan kaiken_ olla luokkien sisällä? Vai riittääkö jos luokkien sisällä on yleisimmän toiminnot, kuten Käyttäjän tietojen tulostaminen näytölle, tallentaminen tietokantaan jne.?
Ja sitten olisi lisäksi sellainen "peruskoodi", jossa on niitä iffejä jne.? Esim. Ote "peruskoodista":
if( !(ereg("^(.+)@(.+)\\.(.+)$",$email)) )
{
print "Sähköpostiosoitteessasi on virhe.";
echo ('<br><a href="http://127.0.0.1/kauppa/uusi_kayttaja.php"
exit;
}
require "Kayttaja.php";
$uusiKayttaja = new Kayttaja;
$uusiKayttaja->AsetaTiedot($tunnus, $firstname, $sukunimi, $email, $salasana);
$uusiKayttaja->TallennaTiedot();
print "Seuraavat tiedot on tallennettu tietokantaan:";
echo '<br><br>';
$uusiKayttaja->TulostaTiedot();
Käytäpä kooditageja niin saa helpommin selvää :).
Niin, tee tuolle rekisteröinnille oma luokka ja sinne funkkari tarkistaEmail() sun muut funktiot, joita tarvitset rekisteröintiin.
Kiitos tsuriga, ja kaikki muutkin. Seuraavaksi teen siis rekisteröinnille oman luokan. Ilmeisesti rekisteröimissivu (pelkkä html-lomake) saa olla omana tiedostonaan?
Olisiko nuo TarkistaEmail() yms. voinut laittaa Kayttaja-luokkaankin, koska käyttäjän tietojahan siinä tarkistellaan?
Ilmeisesti sisäänkirjautumisellekin tehdään oma luokkansa? Minne siis tehdään funktiota missä tarkistetaan onko kentät tyhjiä, onko salasana oikein jne.?
Olette olleet todella suureksi avuksi. Tulen varmaan vielä kyselemään lisää tyhmiä kysymyksiä, mutta enköhän minä tästä pikkuhiljaa opi. :)
Itse olen kokenut lomakkeiden teon niin työlääksi, että olen luonut niille oman lomake-luokkansa sekä eri elementeille omat luokkansa (input, textarea, select) ja homma on helpottunut huomattavasti. Eli jos tekeminen loppuu, niin siitähän on hyvä jatkaa... :)
tsuriga kirjoitti:
Käytäpä kooditageja niin saa helpommin selvää :).
Niin, tee tuolle rekisteröinnille oma luokka ja sinne funkkari tarkistaEmail() sun muut funktiot, joita tarvitset rekisteröintiin.
En tiedä, tarkoititko tarkistaEmaililla vain tuota ereggiä, vaiko myös noita echoiluja (hmm, print ja echo peräkkäin), mutta itse en tykkää laittaa tuollaisia ilmoituksia luokkiin, vaan pidän luokat abstrakteina, jolloin niitä voi helpommin käyttää uudelleen (mitä en tosin ole ikinä tehnyt).
Täytyy kyllä todeta, että PHP4:llä olio-ohjelmointi on aika rajoittunutta, eikä sen parhaita puolia pääse juuri käyttämään. PHP5:n kohdalla asiat kait ovat paremmin, en ole tutustunut.
Kiitoksia jälleen. Loistavaa, että täältä saa näin paljon apua!
Ilmeisesti "oikeita" olio-ohjelmointitapoja on tosi paljon, kaikki tekee vähän niin kuin parhaaksi näkee. Mutta on tosi kiva kuulla teidän muiden neuvoja, saan siitä paljon apua.
Tarkoitin vain sitä ereggiä, ei mitään tuommoisia tulostuksia funktioihin, vaan tulostellaan funktioiden palautusarvon perusteella sitten itse "ohjelmassa", tästä poikkeuksena funktiot, joiden tarkoitus nimenomaan on tulostaa jotain joka joko toistuu useasti tai on muuten vain kätevä esittää funktiona. Olio-ohjelmointi on tosiaan paljon paljon tärkeämmässä osassa PHP 5:ssa kuin nelosessa.
Ihan pikku vinkkinä käytä echo tai print älä molempia sekasin. Näin koodi on helppo lukuisempaa. Echo on kuulemma hitusen nopeempakin, ainaskin kirjoittaa ;)
Sekä laita url osoite omaan muuttujaan, näin vältytään koodiin koskemiselta kun kaupan osoite vaihtuu.
Tämä on tietenkin makuasia, mutta includeta tarvittavat tiedostot heti sivun alussa äläkä ohjelman keskellä, näin näkee vilkasulla mitä tiedostoja sivu tarvitsee.
Itse laittaisin kaikki tarkistus jutut yhteen functioon, jolloin functio kutsun kanssa määrätään mitä halutaan tarkistaa ja paluu arvona on true tai false riippuen läpäiseekö tarkistuksen. Tällöin koodissa vain if(tarkista('email',$email)) // email kirjoitettu oikein. Olioiden kanssa varmaan kannattaisi tarkistuksille tehdä oma luokka(?)
Sekä parempa keino on tulostaa suoraan lomake uudestaan ja tarvittavat virheilmoitukset kuin palaa takaisin linkki.
Varmaan tiedätkin https://www.php.net/manual/fi/language.
Uuh Opiskelija, osaa se Ohjelmointiputkan leiska / selaimesi rivittää viestit automaagisesti, jos selkeyttä kaipaat niin käytä vaikka ranskalaisia viivoja tai yhtä enteriä, ei sillä ole tarkoitus hyppiä. Ja suomeksi se on "funktio" :).
lainaus:
Sekä laita url osoite omaan muuttujaan, näin vältytään koodiin koskemiselta kun kaupan osoite vaihtuu.
Kätevintä on käyttää relatiivisia polkuja, ei tarvitse välittää domainnimen muutoksista.
lainaus:
tarkista('email',$email)
Tee joko jokaisen kohdan tarkistukselle oma funktio tai syötä tarkistus-funktiolle kaikki käyttäjän tiedot arrayssa, jotka kaikki tarkistetaan kerralla, halutun tarkistuskohteen syöttäminen parametrina on tavallaan ylimääräistä työtä, näyttääkin purkalta.
lainaus:
Tämä on tietenkin makuasia, mutta includeta tarvittavat tiedostot heti sivun alussa äläkä ohjelman keskellä, näin näkee vilkasulla mitä tiedostoja sivu tarvitsee.
Juu esitellään tarvittavat luokat aina ohjelman alussa.
Antees noista entterin painalluksista, väsyneenä niitä tulee laitettua liikaa ja vääriin paikkoihinkin, mutta eipäs tuo paljoa haittane. Ennemmin muutama entteri liikaa kuin liian vähän :)
lainaus:
Tee joko jokaisen kohdan tarkistukselle oma funktio...halutun tarkistuskohteen syöttäminen parametrina on tavallaan ylimääräistä työtä, näyttääkin purkalta.
Tämäkin taitaa olla niitä tottumus kysymyksiä, itse pidän tuota selkeempänä ja helppo käyttöisenä, ihan sama syöttääkö tarkistus kohteen funktion nimessä tai parametrina. Empä sanoisi tuota purkaksi tuon paremetri jutun takia.
Vertaapa sitä esimerkiksi siihen, että syötät kaikki tiedot arrayssa funktiolle:
<?php /** * Tarkistuksen kohde syötetään parametrina */ function tarkista($str, $kohde) { return (1==2); } // ja koodissa tarkista($email, 'email'); tarkista($nimi, 'nimi'); tarkista(.. /** * Funktiolle syötetään arvot taulukossa */ function tarkista($arr) { return (1==2); } // ja koodissa $käyttäjäntiedot = array(); $käyttäjäntiedot[]=$_POST['email']; $käyttäjäntiedot[]=$_POST['nimi']; tarkista($käyttäjäntiedot); ?>
Näin ei tule ylimääräisiä funktiokutsuja ja jos käyttäjäntiedot-taulukon määrittelee koodin alussa, on koodin tutkailijalle heti selvää, mitä tietoja tarkastetaan. Tietysti voi määrittää myös omat muuttujat, mutta yhden taulukon käyttö on selkeämpää, ei välttämättä tarvitse edes muistaa indeksien nimiä, onhan foreach. Lisäksi funktiokutsua ei tarvitse muokata jos haluaa lisätä uuden tiedon käyttäjästä, vaan pelkkä copy-paste riittää.
Erillisten funktioiden tekemisessä on se hyöty, että luokkaa voi käyttää monipuolisemmin, jos ei vaikka haluakaan tarkistaa käyttäjän kaikkia tietoja. Ja luokistahan tulisi tehdä mahdollisimman monikäyttöisiä, kuitenkin niin, että luokalla on yksi osa-alue, johon se keskittyy.
Niin ja itse tietysti käyttäisin kielenä englantia, näin saadaan potentiaalisesti maksimaalinen hyöty skriptistä.
Meneeköhän tämä lähelle oikeaa tapaa:
<?php function TsekkaaTyhjat() { if (($this->tunnus == "") || ($this->etunimi == "") || ($this->sukunimi == "") || ($this->email == "") || ($this->salasana == "") || ($this->salasana2 == "")) { return true; } } ?>
ja
<?php $uusiRekisterointi->TsekkaaSalasanat(); if (TsekkaaSalasanat == true); { echo "Salasanan varmistus ei täsmää alkuperäiseen salasanaan. Ole hyvä ja palaa takaisin korjaamaan lomaketta."; echo ('<br><a href="http://127.0.0.1/kalenteri/uusi_kayttaja.php">Takaisin rekisteröitymissivulle</a>'); exit; } ?>
Käytä nyt niitä kooditageja, keskustelun ohjeista löytyy ohjeet. Noitten lukeminen on yhtä työlästä kuin märälle talouspaperille puukolla koodaaminen. Kommentoin koodia kooditageissa:
<?php /** * Yleistä: Laita koodin alkuun "error_reporting(E_ALL);" * ja aja koodi parserin läpi, näet suurimman osan virheistä. Jos tulee outo virheilmoitus, käytä ensin hakutoimintoa ("headers already sent.." on wanha) */ /** * Aloita funktion nimi aina pienellä, luokkien nimet taasen isolla. * Virheellinen funktio: * Funktion tulisi palauttaa aina jokin arvo jos se sellaiseksi on määritelty, nyt funktio * ei palauta mitään (ellei PHP käyttäydy taas miten sattuu ja hyppää virheen yli) * jos if ei toteudu, laita loppuun "else return false;". * Funktion voisi tietysti toteuttaa myös one-linerina. */ function TsekkaaTyhjat() { if (($this->tunnus == "") || ($this->etunimi == "") || ($this->sukunimi == "") || ($this->email == "") || ($this->salasana == "") || ($this->salasana2 == "")) { return true; } } ?> ja <?php /** * Eikö tuo if pitäisi olla "if ($uusiRekisterointi == true) {"? */ $uusiRekisterointi->TsekkaaSalasanat(); if (TsekkaaSalasanat == true) { /** * Mihinkäs tässä kahta echoa tarvitaan? Echo ei ole funktio vaan komentorakenne, jotenka sen kanssa ei yleensä käytetä sulkuja. * Tulosta tuo linkki suhteelliseksi, "kalenteri/uusi_kayttaja.php" */ echo "Salasanan varmistus ei täsmää alkuperäiseen salasanaan. Ole hyvä ja palaa takaisin korjaamaan lomaketta."; echo ('<br><a href="http://127.0.0.1/kalenteri/uusi_kayttaja.php">Takaisin rekisteröitymissivulle</a>'); exit; } ?>
Hei, kiitos tsuriga!
Mä pastesin väärän pätkän, mutta sitten tämä sivusto meni jumiin enkä saanut sitä enää korjattua. Mutta kiitos silti, tuosta oli taas iso apu!
Kommentoisitteko tätä? Onko tämä nyt edes jotain sinne päin:
<?php class Kirjautuminen { var $tunnus; var $salasana; var $tyhjat; function asetatiedot($ptunnus, $psalasana, $ptyhjat) { $this->tunnus = $ptunnus; $this->salasana = $psalasana; $this->tyhjat =$ptyhjat; } function tsekkaatyhjat() { if (($this->tunnus == "") || ($this->salasana == "")) { print $this->tyhjat; } else { return false; } } } ?> <? require "Kirjautuminen.php"; include "funktiot.php"; $yhteys = AvaaTietokanta(); $tyhjat = "Käyttäjätunnus tai salasana puuttuu." . '<br><a href="index.php">Takaisin sisäänkirjautumissivulle</a>'; $uusiKirjautuminen = new Kirjautuminen; $uusiKirjautuminen->asetatiedot($_POST['tunnus'], $_POST['salasana'], $tyhjat); $uusiKirjautuminen->tsekkaatyhjat($_POST['tunnus'], $_POST['salasana']); ?>
Olio-ohjelmointi on toki kivaa, silloin, kun oliolla ei saavuteta mitään muuta kuin ylimääräinen olio (kuten tässä esimerkissä), ei sitä mielestäni kannata käyttää. ;-) Eli ei olioita pelkästään olioiden takia. Muuten kyllä käytän itsekin.
Noh, onhan tämä tietysti makuasiakin.
hmmp: olen samaa mieltä. Mutta tarkoituksena on nimenomaan opetella olio-ohjelmointia. :(
Mutta tosiaan, kommentteja muilta? :)
käytä avaaTietokanta() (pienellä) ja new Kirjautuminen() (sulut lopussa, luokilla on aina konstruktorit, mutta php:ssä niitä ei vaadita skripteihin). Ja asetatiedot voisi olla konstruktori. Eikä noita funktion parametrien muuttujanimiä tarvitse kirjoittaa eri tavalla (näin siis ainakin Javassa), eli kyllä pitäisi toimia $this->tunnus=$tunnus, missä $tunnus on saatu parametrina ja $this->tunnus siis on itse luokan muuttuja. Ja funktioissa on kätevä kirjoittaa aina uusi sana isolla tyyliin tsekkaaTyhjat.
Ok, kiitos tsuriga! Nuo if-rakenteet on siis suht. ok?
Sieltä puuttuu se toinen returni taas muuten. Kai se tolla iffillä pelittää. Tuo ptyhjat-parametri on melko turha, itse tekisin jotenkin:
<?php class Authenticator() { var $errormessages = array('Missing username or password'); var $occured_errors = array(); function checkData($data) { return (checkName($data[0]) && checkPassword($data[1])); } function checkName($name) { if (strlen($name)>1) return true; else { $occured_errors[] = $errormessages[0]; return false; } } function checkPassword($psw) { if (strlen($psw)>5) return true; else { $occured_errors[] = $errormessages[0]; return false; } } function getErrorMessages() { return $this->occured_errors; } function flush_errors() { $this->occured_errors = array(); } } ?>
koska:
-Englanti on pop, sitä ymmärtää useampi kuin suomea.
-Haluat ehkä tarkistaa syötetyistä tiedoista muutakin kuin sen, että onko niitä annettu ollenkaan, siksi erilliset metodit kaikille (ja niitä voi käyttää näin myös erikseen mikäli tarve vaatii)
-On käytännöllisempää laittaa funktiot vain palauttamaan jokin arvo, nyt virheen sattuessa se tulostetaan virheluetteloon, jonka voi halutessaan poimia.
Luokassa voisi tietysti olla vielä setLanguage-funktio kielen asettamiseksi ja flush_errors -funktiota voisi kutsua checkData:n suorittamisen yhteydessä.
Kiitos jälleen. Muutama kysymys:
Onko funktion pakko palauttaa mitään? Ilmeisesti ei? Eikö esim. tämä ole ihan ok?
function tsekkaaSalasanat() { if (($this->salasana != $this->salasana2)) { print $this->errormessages[1]; exit; } }
Ja sitten: miten kannattaisi toteuttaa se, että jos esim. salasanojen tsekkauksessa tulee virhe, niin tulostetaan virheilmoitus ja siirrytään taas kirjautumaan uudestaan? Kun aiemminhan mulla oli vaan linkki etusivulle, mutta kätevämpi olisi jos se menisi automaattisesti (ja siis sitten siellä etusivulla olisi se virheilmoitus).
Tinna kirjoitti:
Ja sitten: miten kannattaisi toteuttaa se, että jos esim. salasanojen tsekkauksessa tulee virhe, niin tulostetaan virheilmoitus ja siirrytään taas kirjautumaan uudestaan? Kun aiemminhan mulla oli vaan linkki etusivulle, mutta kätevämpi olisi jos se menisi automaattisesti (ja siis sitten siellä etusivulla olisi se virheilmoitus).
Mitä jos tekisit vaikka niin, että ohjaisit käyttäjän ( header("Location: sivu.php");
) login-sivulle ja antaisit get:illä tiedon errorista, eli:
Funktion ei ole pakko palauttaa mitään, mutta jos palautat jotain jossakin vaiheessa funktiota, niin sen tulisi palauttaa jokin arvo aina. Eli jos palautat iffissä jotain niin myös elsen tulisi palauttaa jotain. PHP tosin viitannee kintaalla moisille säännöille :S. Kyllä tuo funktiosi on ihan ok, exit on tuossa kohtaa turha, koska funktion suoritus loppuu kuitenkin. Tuosta virheen tulostuksesta en osaa antaa mitään erikoisen hyviä neuvoja, sillä olen sitä itsekin miettinyt ja lähes jokainen tapa tuntuu purkahtavalta tai epästandardimaiselta. Yksi tapa tietysti on ohjata käyttäjä takaisin indexiin noin kuten Heikki tuossa yllä mainitseekin
Kiitos jälleen. :)
Osaakohan kukaan sanoa, mitä tarkoittaa virheilmoitus:
Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at c:\wamp\www\kauppa\Login.php:5) in...
Samantapainen virheilmoitus tulee jos yritätä tehdä noita header-käskyjä.
Onkohan mahdollista, että ongelmat liittyvät jotenkin seuraavaan:
$tunnus = $_POST['tunnus']; $salasana = $_POST['salasana'];
Eli kun lähetän postilla kirjautumissivulta Login-sivulle tietoja, mun täytyy Login-sivulla merkitä juuri lähetetyt tiedot noin: $_POST['tunnus'];, eikä pelkkä $tunnus riitä, niin kuin ainakin erään kirjan esimerkissä.
Olet tulostanut rivillä 5 jotain. Sinun täytyy ENSIN antaa headerit ja session_start() -käsky, sitten vasta tulostukset.
Hyvä tapa on laittaa aina sivun alkuun session_start(). http://wiki.mureakuha.com/wiki/Mitä_tarkoittaa_
Tosi hienoa, että täällä saa vastauksia välillä vähän tyhmiinkiin kysymyksiin. :)
Seuraava kysymykseni on, että mitä tietoja mun kannattaa nettikaupassani välittää sessioneiden kauta? Siis ei esim. salasanaa, mutta kävisikö asiakasnumero? Vai tartteeko niitä tietoja olla useampi?
Aihe on jo aika vanha, joten et voi enää vastata siihen.