Ohjelmoin*kielet ja - paradigmat 5op Markus Norrena
Kotitehtävä 1 Tee kirjautumisjärjestelmä ilman tietokantaa. Sivustolle jolla on vähintään 2 eri sivua. Kysyy tunnusta ja muistaa kirjautumisen ettei kysy uudestaan siirryttäessä sivulta toiselle. Ei päästä millekään sivulle ellei ole oikeaa salasanaa. Käytä funktioita koodissasi (hyvä koodaustapa). Palauta koodisi ja linkki sivulle Markukselle sähköpostitse. (Älä käytä palvelimen htaccess tiedostoa tähän.)
Kotitehtävä 2 Tutustu & valitse framework itsellesi: Symfony Henri CodeIgniter An< Phalcon Samuli Laravel Tiina Node.js PeFeri CoffeeScript Joel AngularJS Nikke MooTools Chrisu
Kotitehtävä 3 Asenna valitsemasi frameworkki ja tee "hello world" tasoinen koe sillä. Symfony Henri CodeIgniter An< Phalcon Samuli Laravel Tiina Node.js PeFeri CoffeeScript Joel AngularJS Nikke MooTools Chrisu
Tämän päivän teemat Tietokannan käyttö PHP:llä (MySQL ja PDO) File Upload esimerkki Tutustumme näihin harjoitustehtävän kautta. Lisäksi voisimme yrittää ratkoa "framework" ongelmat yhdessä jotta kaikki pääsevät eteenpäin. Nämä kalvot ovat jo kurssisivulla: http://users.metropolia.fi/~norrm/k14/okp/
Tämän päivän tehtävä Tee alkeellinen kuvagallerian alku Käytännössä kaksi sivua Yksi jolla voi ladata kuvia palvelimelle (file upload) Toinen jolla ladattuja kuvia voi katsoa (ja selata) Tallenna tietokantaan tiedot ladatuista kuvista (Kuvan nimi käyttäjän syöttämä) Kuvatiedoston nimi Polku minne se tallennettiin Päivämäärä milloin lisätty (tyyppi php kertoo) (koko php kertoo)
Tehtävän tasuta,etoa: Tietokannat, MySql ja PDO
Kertausta: SSH yhteys: 195.148.97.131 MySQL käynnistyy: mysql -u [käyttäjänimi] -p [enter] Kurssin käyttäjätunnus: okp ja salasana: oli9trr3 Esim: mysql -u okp -p Luokaa itsellenne oma tietokanta: mysql> create database markus-okp; Myös phpmyadmin löytyy: hfp://195.148.97.131/phpmyadmin/
Tai käyttäkää luokan koneille asennettua XAMPPia Sisältää: Apache, MySQL, PHP ja Perl c:\win\xampp\htdocs näkyy osoitteessa http://localhost/
MySQL:n käyfö PHP:llä Perinteinen tapa <?php // aukaistaan tietokantayhteys $mysql_yhteys = @mysql_connect("", "okp", "oli9trr3") or die("tietokantaan ei saatu yhteyttä."); @mysql_select_db("markus-okp", $mysql_yhteys) or die("tietokantaa markus-okp ei löytynyt."); // suoritetaan kysely $query = "select nro, kala from kalat"; $result = mysql_query($query); // tulostetaan kyselyn tulos // käydään läpi ja tulostetaan tulos while($rivi = mysql_fetch_array($result)) { print "$rivi["nro"] $rivi["kala"]<br>\n"; }?>
SQL kertausta: Create table luo taulun int on kokonaisluku varchar() on hyvä määre lyhyille tekstikentille» MySQLssä: PHPssä: CREATE TABLE Persons ( PersonID int, LastName varchar(255), FirstName varchar(255), Address varchar(255), City varchar(255) ); $sqlkom = "Create table puhluettelo ( etunimi varchar (30), sukunimi varchar (40), puhnro varchar(20))"; mysql_query($sqlkom) or die("virhe SQL-komennossa: ". mysql_error($mysql_yhteys));
insert into Täyttää taulua datalla MySQLssä: insert into markus_kalat set nro=14, kala = 'siika'; INSERT INTO Customers (CustomerName, City, Country) VALUES ('Cardinal', 'Stavanger', 'Norway'); PHPssä: $sqlkom="insert into puhluettelo (etunimi, sukunimi, puhnro) values ('$etu','$suku','$puh')"; Ensimmäisessä sulkulausekkeessa luetellaan taulun ne kentät, eli sarakkeet, joille asetetaan sisältö Toisessa sulkulausekkeessa muuttujat, joiden arvot niihin viedään On myös suoritettava mysql_query -lause Sarakkeet joille ei arvoa sijoiteta saavat arvon NULL
Luetaan taulusta select -komennolla, tässä määreellä order by PHP:ssä $sqlkom="select * from puhluettelo order by sukunimi, etunimi"; $hakutulos=mysql_query($sqlkom) or die("virhe SQL-komennossa: ". mysql_error($mysqlyhteys)); tulos asetetaan nyt muuttujaan $hakutulos Se on siellä taulukkomuodossa ja voidaan käsitellä vaikkapa seuraavasti: while ($tulosrivi=mysql_fetch_array($hakutulos)) { $et = $tulosrivi["etunimi"]; $su = $tulosrivi["sukunimi"]; $pu = $tulosrivi["puhnro"]; }
While lauseen mysql_fetch_array -funktio hakee seuraavan rivin tulosjoukosta ja sijoittaa sen assosiatiivisen taulukon $tulosrivi arvoksi Assosiatiivinen taulukko tarkoittaa että sen arvoon voidaan viitata avaimella joka tässä tapauksessa on tietokannan sarakkeen nimi
Update muuttaa jo syötetyn arvon muuksi update taulu set ika='22' where ika='21'; Update kalat set kala='monni' where nro=2; Delete poistaa rivin taulusta delete from markus_kalat where nro=15; delete from taulunnimi where runoilija is null; drop table poistaa taulun Alter table muuttaa itse taulun määreitä (describenäkymä) alter table kalat add column (vari varchar(10)); Exit poistuu mysql:stä
MySQL:n käyfö PHP:llä Modernimpia tapoja ovat MySQLi Toimii pitkäl* samalla tapaa kuin perinteiset esimerkit, mufa kutsut nimetään MySQLi. Voidaan käyfää olio- ohjelmoinnin mukaises* tai sifen ei. Esimerkki:
MySQLi <?php // aukaistaan tietokantayhteys $mysql_yhteys = @mysqli_connect("", "okp", "oli9trr3", "markus-okp") or die("virhe: ". mysqli_error($mysql_yhteys)); // suoritetaan kysely $query = "select nro, kala from kalat" or die("virhe: ". mysqli_error($mysql_yhteys)); $result = $mysql_yhteys->query($query); // tulostetaan kyselyn tulos // käydään läpi ja tulostetaan tulos while($rivi = mysql_fetch_array($result)) { echo $rivi["nro"]." ". $rivi["kala"]." <br>\n"; }?>
PDO Puhtaas* olio- ohjelmoinnin mukainen tapa tehdä nämä samat asiat. Tämä on suositeltavin tapa tällä hetkellä, mufa kaikkia tavat ovat OK. PDO:lla voi käyttää MySQL:n lisäksi muitakin tietokantaohjelmia yhtenäisellä tavalla. Kokeilkaa soveltaa esimerkkikoodia:
<?php // muodostetaan yhteys tietokantaan $yhteys = new PDO("mysql:host=localhost;dbname=markus-okp", "okp", "oli9trr3"); // valmistetaan kysely $kysely = $yhteys->prepare("select * FROM markus_kalat"); // suoritetaan kysely $kysely->execute(); // näytetään kyselyn tulokset taulukossa echo "<table border=\"1\" cellpadding=\"2\">"; // käsitellään tulostaulun rivit yksi kerrallaan while ($rivi = $kysely->fetch()) { echo "<tr>"; echo "<td>". htmlspecialchars($rivi["nro"]). "</td>"; echo "<td>". htmlspecialchars($rivi["kala"]). "</td>"; echo "</tr>"; } echo "</table>";?>
Kyselyssä on kaksi vaihetta: ensin kysely valmistetaan metodilla prepare, sitten se suoritetaan metodilla execute. Metodi fetch palauttaa yksi kerrallaan kyselyn tuottamat rivit, kunnes rivejä ei enää ole, jolloin metodi palauttaa arvon false ja silmukka päättyy. htmlspecialchars muuttaa erikoismerkit htmlkoodiksi, esim: & = & < = < Lisätään koodiin virheiden hallintaa:
<?php // muodostetaan yhteys tietokantaan (virheenkäsittelyllä) try { $yhteys = new PDO("mysql:host=localhost;dbname=markus-okp", "okp", "oli9trr3"); } catch (PDOException $e) { die("virhe: ". $e->getmessage()); } // virheenkäsittely: virheet aiheuttavat poikkeuksen $yhteys->setattribute(pdo::attr_errmode, PDO::ERRMODE_EXCEPTION); try { // valmistetaan kysely $kysely = $yhteys->prepare("select * FROM markus_kalat"); // suoritetaan kysely $kysely->execute(); } catch (PDOException $e) { die("virhe: ". $e->getmessage()); } // näytetään kyselyn tulokset taulukossa echo "<table border=\"1\" cellpadding=\"2\">"; // käsitellään tulostaulun rivit yksi kerrallaan while ($rivi = $kysely->fetch()) { echo "<tr>"; echo "<td>". htmlspecialchars($rivi["nro"]). "</td>"; echo "<td>". htmlspecialchars($rivi["kala"]). "</td>"; echo "</tr>"; } echo "</table>";?> Sama virheenkäsittelyllä!
Try catch Antaa meille mahdollisuuden hallita virhetilanteita, eli päättää mitä tehdä jos virhe esiintyy try-osion koodissa die Lopettaa ohjelman suorituksen ja tulostaa viestin
Äskeisessä PDO-koodissa oli tällaiset: -> Kutsuu luokan metodeja, eli funktioita jotka tekevät jotain tiettyä, edellisessä esimerkissä: $yhteys = new PDO(...); // luo ilmentymän luokasta $yhteys->setattribute(...); // kutsuu luokan sisäistä setattribute -funktiota $kysely = $yhteys->prepare(...); // kutsuu prepare funktiota luokasta :: Kutsuu luokan staattista metodia (funktiota joka on luokassa eikä olion ilmentymässä) $yhteys->setattribute(pdo::attr_errmode, PDO::ERRMODE_EXCEPTION);
<?php PDO ja SQL-kyselyn parametrit //Seuraava koodi hakee vain rivit, joissa hinta on 3: $kysely = $yhteys->prepare("select * FROM tuotteet WHERE hinta =?"); $kysely->execute(array(3)); //Seuraava koodi taas hakee rivit, joissa nimi on peruna tai porkkana: $kysely = $yhteys->prepare("select * FROM tuotteet WHERE nimi =? OR nimi =?"); $kysely->execute(array("peruna", "porkkana")); /* Kyselyt INSERT, UPDATE, DELETE suoritetaan vastaavasti kuin kysely SELECT. Seuraava koodi muuttaa porkkanan hinnaksi 4: */ $kysely = $yhteys->prepare("update tuotteet SET hinta =? WHERE nimi =?"); $kysely->execute(array(4, "porkkana"));?> Kyselyn mahdollisten muuttuvien parametrien kohdalle merkitään kysymysmerkki kyselyn valmistuksessa. Kyselyn suorituksessa ilmoitetaan parametrien senkertaiset arvot niiden esiintymisjärjestyksessä.
Kumpaa käyttää? PDO Proseduraalinen malli?
Muutamia PHP:n MySQL funktioita: Mysql_affected_rows() palauttaa INSERT, DELETE tai UPDATE kyselyn muuttamien rivien määrän mysql_fetch_array() hakee kyselyn tuloksesta seuraavan rivin assosiatiivisena taulukkona mysql_fetch_row() hakee kyselyn tuloksesta seuraavan rivin yksinkertaisena taulukkona Lisää MySQL funktioita: http://fi2.php.net/manual/en/ref.mysql.php
Yleisiä SQL tietotyyppejä Varchar() Vaihtelevanpituinen tekstikenttä, maksimipituus on määriteltävä Char() Tietynpituinen tekstikenttä Text Pidemmille tekstikentille Int() Kokonaisluku Decimal() Tarkka desimaaliluku Float Liukuluku Datetime Päivämäärä muodossa VVVV-KK-PP HH:MM:SS Time Aika muodossa HH:MM:SS Date Päivämäärä VVVV-KK-PP Create table kayttaja (nimi varchar(20), kirjautuminen datetime, id int);
Lisää PHP:tä require Käskyllä liitetään tiedoston sisältö koodiimme Hyöty on mm. että liitettävää koodia ei tarvitse kirjoittaa joka ohjelmaan / tiedostoon uudestaan Esim tiedosto db.php: Muodostaa yhteyden meille MySQL-palvelimelle Käytetään tiedostoa käskyllä: require 'db.php'; esim:
db.php <?php // aukaistaan tietokantayhteys $mysql_yhteys = @mysql_connect("", "okp", "oli9trr3") or die("tietokantaan ei saatu yhteyttä."); @mysql_select_db("markus-okp", $mysql_yhteys) or die("tietokantaa markus-okp ei löytynyt.");?> sqlkoe.php <?php require 'db.php'; // suoritetaan kysely $query = "select nro, kala from markus_kalat"; $result = mysql_query($query); // tulostetaan kyselyn tulos?>
Include -käsky on kuin require, paitsi ettei aiheuta virhettä ellei tiedostoa löydy eli ei voida luottaa siihen että tiedosto löytyi include("header.php"); require("header.php"); require lopettaa ohjelman ja antaa virheilmoituksen ellei tiedostoa löydy
Jos on paljon ristiin liitettäviä tiedostoja kannattaa käyttää include_once(); require_once(); Jolloin PHP pitää huolen että tiedostot liitetään vain kerran.
Kertausta Lomakkeiden käsittelystä PHP:ssä Voimme viitata suoraan lomakkeen kenttiin PHP:ssä: $_GET["nimi"] $_POST["nimi"] Eli postitustavasta riippuu kumpaa käytämme (get / post)
Tässä esimerkki jolla voimme tarkistaa onko tietoa lähetetty: if (!empty($_post['nimi'])) { echo ($_POST['nimi']); }! On negaatio, eli lause pseudokoodina: "ellei nimi-postaus ole tyhjä niin "
Tiedostojen siirtäminen palvelimelle (File upload)
Luo palvelimelle kansio ladafaville Esim: kuville /public_html/kuvagalleria/uploads Ongelma: ei ole hyvä antaa kaikille kirjoitusoikeu>a kansioon. Ratkaisu: Muutetaan webbipalvelin kansion omistajaksi ja annetaan vain sille kirjoitusoikeudet. Webbipalvelimen (Apachen) käyfäjätunnus näkyy phpinfo(); - käskyllä
Luo palvelimelle kansio ladafaville Esim: kuville /public_html/kuvagalleria/uploads Webbipalvelimen käyfäjätunnus meillä: www- data Anna unixissa komentorivikäsky: sudo chown www-data uploads Jossa www- data on apache- prosessin käyfäjätunnus Ja tarkista efä oikeudet (chmod) ovat muuten kunnossa
Palvelimen php.ini Sisältää asetuksia jotka vaikufavat uploadiin, esim: File upload on/off, ladafavan *edoston kokorajoitukset jne. Ovat yleensä OK, mufa joskus voi olla hyvä tarkistaa / muufaa
Perus upload- käskyt: lomake <form action="tallenna.php" enctype="multipart/form-data" method="post"> <input type="hidden" name="max_file_size" value="1000000" /> <input type="file" name="kuva" /> <input type="submit" name="submit" value="upload" /> </form>
tallenna.php if(isset($_post['submit'])) { // process the form data $tmp_file = $_FILES['kuva']['tmp_name']; $target_file = basename($_files['kuva']['name']); $upload_dir = "uploads"; // move_uploaded_file will return false if $tmp_file is // not a valid upload file or if it cannot be moved for // any other reason } if(move_uploaded_file($tmp_file, $upload_dir."/".$target_file)){ echo "File uploaded successfully."; } else { echo $_FILES['kuva']['error']; }
Tiedostojen siirtämistä palvelimelle (File upload) Käytetään PHP:n funk*ota "move_uploaded_file" Kun funk*o siirtää *edoston palvelimelle, se luo myös taulukkomuufujan $_FILES joka sisältää *etoja *edostosta move_uploaded_files ofaa kaksi parametria, ensimmäinen kertoo funk*olle mistä se löytää siirrefävän *edoston, ja toinen parametri kertoo minne *edosto siirretään
Funk*o on jo luonut *edostosta *lapäsen kopion, johon viifaamme käyfäen $_FILES - taulukkomuufujaa Kuvia voi lähefää lomakkeella useita, joten viifaamme oikeaan kuvaan lomakkeen kentän nimellä, eli 'kuva' TaulukkomuuFujan 'tmp_name' - kohdassa on *edostosta jo luotu *lapäiskopion sijain* $_FILES - taulukkomuufujan 'name' indeksiin on tallennefu *edoston alkuperäinen nimi
Php.net:in manuaali: hfp://php.net/manual/en/features.file- upload.php W3schools hfp://www.w3schools.com/php/ php_file_upload.asp
Ko*tehtävä 4 Viimeistele tämän päivän tehtävä, eli "alkeellinen kuvagalleria".
Kotitehtävä 5 "Framework" Selvittele ja suunnittele, mihin valitsemasi Framework soveltuu ja mikä olisi sinua kiinnostava kokeiluprojekti? Esittele ensi kerralla suunnitelma mitä aiot Frameworkilla toteuttaa kurssin aikana (7 kertaa jäljellä) Suunnitelman tulee sisältää viikkokohtainen edistymisaikataulu! Palauta suunnitelmasi Facebook-ryhmäämme (Tiedostot -kohtaan). Varmista tunnilla ettei sinulla ole ongelmia asentaa ja käyttää sitä!
Ensi kerralla Olio-ohjelmoinnin aloitus