Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  4 4784
Hei folkens.

Begynte å lære PDO for en liten uke siden, samt at jeg er fersk i PHP generelt.

Har satt opp et testmiljø bare for å utvikle meg selv mer, og det er ikke noe som skal publiseres eller lignende.

Jeg har opprettet sider som heter: user.php, register.php, login.php, registered.php etc.

Dette er filer som er grunnmuren i miljøet her. Nå har jeg hentet ut data fra databasen ganske enkelt. Men nå har jeg opprettet et par test brukere på nettsiden for å sjekke mulighetene videre.


Problemet jeg støtter på nå er da:

Hvis jeg ser navnet til en bruker eller søker opp et brukernavn, så vil jeg ha mulighet til å klikke på dette brukernavnet for så å få opp all informasjon registrert på denne brukeren.

Hvis jeg skal hente ut all denne informasjonen om denne spesifikke brukeren via et script, hvordan gjøres dette da?

Jeg har sessions som er: $_SESSION['user_session'] = $userRow['user_id'];
Må jeg bruke user_id for å komme fram til den spesifikke brukeren jeg trykker på, og hvordan er det da jeg gjøre dette?

Trenger ikke løsning hvis dere ikke vil gi den, men i hvert fall en pekepinne så jeg lærere det til senere når jeg mest sannsynlig trenger det

Ha en fin kveld videre.
Jeg er ikke noe sprek på PHP men det finnes veldig mye lærestoff rundt emnet på nett.

Her er et eksempel på hvordan du henter ut id, firstname, lastname og echo/printer det på siden.

Kode

<?php
$sql = "SELECT id, firstname, lastname FROM MyGuests";
$result = $conn->query($sql);
 
if ($result->num_rows > 0) {
    // output data of each row
    while($row = $result->fetch_assoc()) {
        echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
    }
} else {
    echo "0 results";
}
?>
Se her for mer info.
https://yourl.no/09mqt
Det bør være fort gjort å sjekke hvordan andre gjør det. Det vanlige er å bruke id'en i lenken. http://nettsted.no/bruker/12346
Sist endret av fuzzy76; 18. april 2017 kl. 11:49.
Har holdt på å søkt 2 dager nå. Får opp ganske mye ang hvordan man får opp sin egen profil informasjon, men det er jo ganske enkelt.
Enten er jeg blind eller så er jeg rett og slett for dum til å bruke rette søkeord xD
Limited edition
Moff's Avatar
Her er et fungerende eksempel på hvordan du kan gjøre dette:

Kode

<?php

// Sjekk om det er angitt noen bruker-ID i query stringen (variabel i URL-en til sida)
if(!isset($_GET['id'])) {
	echo 'Du må angi en bruker-ID for å hente ut informasjon.';
	die();
}

// Koble til MySQL-databasen
$mysql = new PDO('mysql:host=localhost; charset=utf8; dbname=fisk', 'username', 'password', array(
	PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,	// Ved feil vil PDO throwe exceptions, slik at ting ikke krasjer i stillhet
	PDO::ATTR_EMULATE_PREPARES => false				// Vi vil håndtere prepared statements selv
));

// Lag en prepared statement (spørring)
$query = $mysql->prepare('SELECT * FROM users WHERE id = :id');

// Bind en variabel til spørringen
$query->bindParam(':id', $_GET['id']);

// Utfør spørring mot databasen
$query->execute();

// Hent alle rader fra spørringen
$row = $query->fetch(PDO::FETCH_ASSOC); // "assoc" = associative array, et array satt opp med key -> value i stedet for index -> value. Dette gjør at kolonnenavnene fra databasen blir satt som keys i arrayet

$result = null; // Placeholder for resultatet

if($row) {
	// Print resultat. htmlentities() sørger for å fjerne muligheten for XSS-angrep, ved at brukerne putter HTML eller Javascript i databasen din
	
	$result = 'Navn: ' . htmlentities($row['name']) . '<br>';
	$result .= 'Telefon: ' . htmlentities($row['phone']);
} else { // Ingen resultater
	$result = 'Fant ikke brukeren.';
}

?><!doctype html>
<html>
<head>
<title>Test</title>
<meta charset="utf-8" />
</head>
<body>
<?php

echo $result;

?>
</body>
</html>
Hvis du ikke har drevet mye med PHP, PDO eller programmering før, så er det sikkert et par nye ting som dukker opp her. Det aller første jeg gjør er å kontrollere om det finnes en variabel som heter $_GET['id']. I PHP så finnes det noen "magiske" variabler som alltid eksisterer. Disse er som regel prefikset med understrek og navnet inneholder bare store bokstaver. $_SESSION, $_SERVER, $_POST og $_GET er eksempler på slike. Som du sikkert har merket så er $_SESSION egnet for å lagre informasjon over tid; en session oppretter en cookie på brukeren sin PC med en PHP session ID i, som fungerer som et passord for å få tilgang til variabler du har lagret i $_SESSION-arrayet. Jeg bruker $_GET i dette tilfellet, og det er et array som inneholder alle variabler fra brukerens query string. Når du er inne på en nettside med en URL som inneholder tall eller lignende ting, så er det typisk query string-parametere. På dette forumet er det tonnevis av dem, for eksempel et tall som angir hvilken tråd det er du ser på. Standard-formatet for query strings er at du setter et spørsmålstegn bak URL-en, og deretter setter du variabelnavn etterfulgt av erlik-tegn og verdien til variabelen. For å legge til flere parametere adskiller du dem med &-tegnet. Her er noen eksempler:

www.elg.no/index.php
www.elg.no/index.php?id=5
www.elg.no/index.php?id=5&fisk=torsk

Hvis du hadde sett på $_GET-arrayet på denne siden, så ville du ha hatt et tomt array på den øverste URL-en. På de to andre ville du sett at $_GET['id'] var lik 5, og på den siste ville også $_GET['fisk'] vært lik 'torsk'.

Mange nettsider bruker ulike teknikker for å skjule query stringer i URL-en. Dette dreier seg som regel om SEO (Search Engine Optimization) og at Google foretrekker nettsider med "rene og pene" URL-er. Det er da du får URL-er som www.elg.no/5 i stedet for www.elg.no/index.php?ìd=5. Det er noe ekstra kode på serveren som driver og oversetter URL-en fra ett format til et annet slik at brukeren (og Google) ser en "pen" URL uten spørsmålstegn og erlik-tegn. Hvis du bruker Apache så kan du lese om "mod rewrite" for å oppnå denne effekten. Also, hvis du bruker Apache, bruk nginx ("Engine X") i stedet. Apache er gammeldags.

Kan kjapt nevne at $_POST-arrayet er nesten det samme som $_GET, med den lille forskjellen at den henter variabler fra POST-data (typisk forms i HTML). POST-data er bra å bruke i de tilfellene hvor du gjør et ikke-persistent oppslag av data, for eksempel når en bruker logger på. Du vil jo helst ikke redirecte brukeren til en nettside hvor brukernavnet og passordet deres er skrevet i URL-en, og POST-data hjelper deg da med å "skjule" den informasjonen som sendes inn. POST-data er på ingen måte tryggere å bruke enn GET og query strings, men det vil i noen tilfeller være mer elegant. Det er klare regler for når du skal bruke de ulike HTTP-verbene (GET, POST, PUT og DELETE), men det kan du sikkert lese mer om senere en gang.

Det som skjer i skriptet ovenfor er at jeg sjekker om $_GET['id'] har en verdi, og hvis ikke, så avslutter skriptet med en feilmelding. Det er forøvrig litt skittent å bruke die(). Du bør helst skrive koden på en slik måte at du slipper å bruke denne, og i dette tilfellet kunne det vært løst med å wrappe MySQL-koden inn i en egen funksjon. Jeg bruker die() her for å gjøre koden litt enklere å lese.

Selve tilkoblingskoden for MySQL bør være relativt kjent. Jeg angir samtidig to options; jeg setter error mode til exception (krasj hvis det oppstår feil) og emulate prepared statements til false (jeg vil alltid håndtere prepared statements manuelt). Jeg pleier alltid å gjøre dette, selv om man ofte ikke trenger det. Jeg liker å være eksplisitt på slike ting, sånn at det ikke dukker opp noen merkelige feilmeldinger hvis du for eksempel deployer skriptet ditt til en server som er konfigurert litt anderledes enn den serveren du tester på.

Hvis du ikke vet hva en prepared statement er, så trenger du en kjapp innføring i et veldig vanlig hacker-angrep kalt SQL injections. En "injection" er det en hacker gjør når han eller hun planter kode et sted hvor man normalt sett ikke skulle ha klart å putte kode. Et klassisk eksempel er ved pålogging til en nettside, hvor man oppgir brukernavn og passord. Du har da kanskje en SQL-kode som ser slik ut:

Kode

SELECT * FROM users WHERE username = '$username' AND password = '$password'
Hvis du ikke bruker prepared statements og i stedet bare måker inn det brukeren har tastet inn som brukernavn og passord direkte i SQL-en din, uten å gjøre noen form for vasking eller validering - da er du på tynn is. Dette vil funke bra hvis brukernavnet jeg taster inn er "Moff", men hva skjer hvis jeg taster inn brukernavnet nedenfor?

Kode

' OR 1 = 1 LIMIT 1 --
Da vil SQL-en din bli seende slik ut:

Kode

SELECT * FROM users WHERE username = '' OR 1 = 1 LIMIT 1 -- ' AND password = '$password'
... noe som vil føre til at spørringen returnerer den første raden i users-tabellen, uten å nøle. Det som er en morsom bieffekt er at den første brukeren i en slik tabell vil være en administrator-bruker i 99% av alle tilfeller.

Dette er en SQL-injection. Før i tiden så var det vanlig praksis å sikre seg mot denne typen angrep ved å escape enkelte tegn i brukerens input, for eksempel ved å legge til en \backslash\ foran 'apostrofene'. I de aller fleste programmeringsspråk så vil en backslash foran et tegn bety at du vil at tegnet skal tolkes bokstavelig, og ikke som en funksjon. I PHP kan du for eksempel bruke dette til å printe 'apostrofer' i en string, selv om stringen i seg selv er 'omsluttet \'av\' apostrofer'.

En mer moderne tilnærming som PDO støtter er prepared statements. Dette er ikke noe som er særegen for PDO eller MySQL, du finner det i de aller fleste databaser og de aller fleste programmeringsspråk.

Kort fortalt så skriver du opp hvordan spørringen din skal se ut med variabler i stedet for ekte verdier. Deretter fyller du inn variablene med ekte verdier i et eget steg, sånn at du kan være 100% sikker på at databasen ikke misforstår hva du prøver å si. Brukeren kan dermed ikke plante kode i SQL-en din. I PDO bruker vi prepare() og bindParam() for å gjøre dette.

execute() er metoden som faktisk utfører spørringen. Når du har utført den, så kan du gjenbruke den samme SQL-en ved å kjøre bindParam og execute på nytt med andre verdier. Du kan altså resirkulere SQL-er, noe som kan spare mye tid og ressurser.

fetch() og fetchAll() er metodene PDO bruker for å lese ut resultater fra en spørring. Bruk fetch() når du forventer én rad eller bare vil hente første rad fra et resultat. Bruk fetchAll() hvis du forventer mer enn én rad. Jeg bruker nesten alltid PDO::FETCH_ASSOC, fordi det er den mest praktiske måten å lese data på. Det finnes mange alternativer, og en ting som det er lurt å være klar over er at du kan lese data direkte til et objekt. Dette er spesielt nyttig hvis du skal hente et stort antall kolonner knyttet til for eksempel en bruker eller et produkt. Du kan da definere et objekt i PHP med felter som samsvarer med kolonnene i databasen, og få PDO til å fylle dette objektet med data direkte. Det kan spare deg for mye kjedelig mapping-kode, og det er mye lettere å vedlikeholde.

Noen synes sikkert det er fjas å definere $result som null i PHP. Dette er noe jeg personlig foretrekker å gjøre fordi det er god programmeringsskikk å definere alle variabler man bruker. Hvis du lærer deg et "skikkelig" programmerinsspråk, som C# eller Java, så vil du få en feilmelding hvis du fjerner denne linjen. Årsaken er at $result ville blitt definert i et annet scope enn den brukes i (innenfor en if-statement), og da er det ikke gyldig å kalle på denne variabelen utenfor if-statementen, slik vi gjør helt nederst i skriptet. PHP tilsvarer nynorsk innenfor programmeringsspråk, i den forstand at det er ikke så nøye med rettskriving. Bare sleng på en -ar-ending her og der, så treffer du 9 av 10 ganger.

Til slutt, en kommentar til if($row). Hvis du sjekker dokumentasjonen for fetch() så vil du se at den returnerer false hvis noe går galt. "Går galt" inkluderer også at spørringen ikke returnerer noen rader (bruker-ID-en er da ikke gyldig).

Jeg har kommentert hva htmlentities() er til for i koden også; kort fortalt så er det en billig måte å stoppe XSS-angrep på. XSS, eller Cross Site Scripting, er en form for injection-angrep det også, men det er først og fremst rettet mot andre brukere av nettsiden din i stedet for deg som administrator (slik en SQL-injection er). Det man kan utnytte denne typen sikkerhetshull til er å plante et Javascript som redirecter brukeren til en nettside hackeren kontrollerer eller utføre andre typer operasjoner på vegne av andre brukere. Moderne nettlesere som Chrome og Edge er veldig godt sikret mot XSS-angrep, men det er ikke alt de klarer å fange opp. Hvis du er interessert i temaet så kan det være lurt å lese mer om XSRF-angrep også, eller Cross Site Request Forgery. Dette er et hacker-angrep som går ut på at en bruker utnytter et XSS-hull for å få kontroll over andre tjenester som en bruker er pålogget. For eksempel så kunne en hacker ha utnyttet et sikkerhetshull i din nettside for å ta kontroll over nettbanken til en av dine brukere. Det finnes selvsagt mange måter å stoppe dette på, både hos deg og hos nettbanken - og de aller fleste store tjenester er allerede godt sikret mot denne typen angrep.

Likevel - når du skal utvikle for web, så må du ha et bevisst forhold til sikkerhet fra dag 1. En fin tommelfingerregel å ha er å anse absolutt all interaksjon og input fra en bruker som et forsøk på å hacke nettsiden din. Valider all input, hver gang, hele tiden.

Siden jeg allerede har skrevet en halv roman så kan jeg legge til en morsom story; jeg spiller et velkjent sandkasse-spill som har et veldig aktivt utvikler-miljø, med svært mange unge som bruker spillet til å lære seg programmering. Hver gang jeg er innom en spillserver hvor noen har programmert en bank-funksjon, av typen hvor du kan sette inn og ta ut valuta, så prøver jeg alltid å sette inn eller ta ut negative beløp. De som programmerer har kanskje tenkt på å sjekke at inputen min er et tall - men har de husket å sjekke om det er et positivt tall? Needless to say så er jeg millionær på forholdsvis mange servere, uten å ha jobbet mer enn 10 sekunder for pengene.
Sist endret av Moff; 19. april 2017 kl. 01:01.