PHP arrays

december 14th, 2019

PHP Array Funktioner

FunctionDescription
array()Creates an array
array_change_key_case()Changes all keys in an array to lowercase or uppercase
array_chunk()Splits an array into chunks of arrays
array_column()Returns the values from a single column in the input array
array_combine()Creates an array by using the elements from one ”keys” array and one ”values” array
array_count_values()Counts all the values of an array
array_diff()Compare arrays, and returns the differences (compare values only)
array_diff_assoc()Compare arrays, and returns the differences (compare keys and values)
array_diff_key()Compare arrays, and returns the differences (compare keys only)
array_diff_uassoc()Compare arrays, and returns the differences (compare keys and values, using a user-defined key comparison function)
array_diff_ukey()Compare arrays, and returns the differences (compare keys only, using a user-defined key comparison function)
array_fill()Fills an array with values
array_fill_keys()Fills an array with values, specifying keys
array_filter()Filters the values of an array using a callback function
array_flip()Flips/Exchanges all keys with their associated values in an array
array_intersect()Compare arrays, and returns the matches (compare values only)
array_intersect_assoc()Compare arrays and returns the matches (compare keys and values)
array_intersect_key()Compare arrays, and returns the matches (compare keys only)
array_intersect_uassoc()Compare arrays, and returns the matches (compare keys and values, using a user-defined key comparison function)
array_intersect_ukey()Compare arrays, and returns the matches (compare keys only, using a user-defined key comparison function)
array_key_exists()Checks if the specified key exists in the array
array_keys()Returns all the keys of an array
array_map()Sends each value of an array to a user-made function, which returns new values
array_merge()Merges one or more arrays into one array
array_merge_recursive()Merges one or more arrays into one array recursively
array_multisort()Sorts multiple or multi-dimensional arrays
array_pad()Inserts a specified number of items, with a specified value, to an array
array_pop()Deletes the last element of an array
array_product()Calculates the product of the values in an array
array_push()Inserts one or more elements to the end of an array
array_rand()Returns one or more random keys from an array
array_reduce()Returns an array as a string, using a user-defined function
array_replace()Replaces the values of the first array with the values from following arrays
array_replace_recursive()Replaces the values of the first array with the values from following arrays recursively
array_reverse()Returns an array in the reverse order
array_search()Searches an array for a given value and returns the key
array_shift()Removes the first element from an array, and returns the value of the removed element
array_slice()Returns selected parts of an array
array_splice()Removes and replaces specified elements of an array
array_sum()Returns the sum of the values in an array
array_udiff()Compare arrays, and returns the differences (compare values only, using a user-defined key comparison function)
array_udiff_assoc()Compare arrays, and returns the differences (compare keys and values, using a built-in function to compare the keys and a user-defined function to compare the values)
array_udiff_uassoc()Compare arrays, and returns the differences (compare keys and values, using two user-defined key comparison functions)
array_uintersect()Compare arrays, and returns the matches (compare values only, using a user-defined key comparison function)
array_uintersect_assoc()Compare arrays, and returns the matches (compare keys and values, using a built-in function to compare the keys and a user-defined function to compare the values)
array_uintersect_uassoc()Compare arrays, and returns the matches (compare keys and values, using two user-defined key comparison functions)
array_unique()Removes duplicate values from an array
array_unshift()Adds one or more elements to the beginning of an array
array_values()Returns all the values of an array
array_walk()Applies a user function to every member of an array
array_walk_recursive()Applies a user function recursively to every member of an array
arsort()Sorts an associative array in descending order, according to the value
asort()Sorts an associative array in ascending order, according to the value
compact()Create array containing variables and their values
count()Returns the number of elements in an array
current()Returns the current element in an array
each()Deprecated from PHP 7.2. Returns the current key and value pair from an array
end()Sets the internal pointer of an array to its last element
extract()Imports variables into the current symbol table from an array
in_array()Checks if a specified value exists in an array
key()Fetches a key from an array
krsort()Sorts an associative array in descending order, according to the key
ksort()Sorts an associative array in ascending order, according to the key
list()Assigns variables as if they were an array
natcasesort()Sorts an array using a case insensitive ”natural order” algorithm
natsort()Sorts an array using a ”natural order” algorithm
next()Advance the internal array pointer of an array
pos()Alias of current()
prev()Rewinds the internal array pointer
range()Creates an array containing a range of elements
reset()Sets the internal pointer of an array to its first element
rsort()Sorts an indexed array in descending order
shuffle()Shuffles an array
sizeof()Alias of count()
sort()Sorts an indexed array in ascending order
uasort()Sorts an array by values using a user-defined comparison function
uksort()Sorts an array by keys using a user-defined comparison function
usort()Sorts an array using a user-defined comparison function

Visa felmeddelanden php

juli 30th, 2019

För att sidan ska skriva ut eventuella felmeddelanden som php-koden genererar lägger man till följande tre rader i filen .htaccess

php_flag display_startup_errors on
php_flag display_errors on
php_flag html_errors on

Programera objektorienterat i php

december 12th, 2017

PHP är ett hybridspråk. Det innebär är att man kan välja att skriva både procedurellt/strukturerat och objektorienterat. Det går även att blanda dessa två paradigmer.
Med procedurell eller strukturerad programmering i PHP menar man att ett program är uppbyggt av en serie funktioner som är placerade i det globala utrymmet. Skriver man objektorienterat väljer man istället att inkapsla funktioner och variabler (eller metoder och attribut som de brukar kallas i objektorientering) i klasser. Man skapar sedan instanser (dessa kallas objekt) av dessa klasser. Objektorientering kan vara underbart. Det är ett sätt att inte bara inkapsla data och funktionalitet utan att gruppera kod på ett snyggt och logiskt sätt.

I många fall är det en fördel att skriva objektorienterad PHP.  Ett klassiskt exempel i PHP-sammanhang är en klass som abstraherar kommunikation med en databas. I en ”databasklass” kan man lagra data som t.ex. databaskopplingen, den senast utförda SQL-frågan, antalet SQL-frågor som utförts osv. Genom att inkapsla dessa data i ett objekt slipper man ha variabler relaterade till databaskommunikationen i det globala utrymmet vilket gör applikationen ”snyggare” och gör att man löper mindre risk för namnkollisioner. Utöver data kan man inkludera t.ex. funktioner för felhantering. Ett objekt av databasklassen är dessutom praktiskt att skicka runt till funktioner och metoder i andra klasser. Generellt sätt kan man säga att om man upptäcker att man har klasser som enbart består av metoder har man varit en dålig objektorienterare. Det är först när man drar nytta av klassers förmåga att inkapsla både data och funktionalitet som man börjar utnyttja objektorientering till fullo.

 

Använd print_r() för att skriva ut en array

december 9th, 2017

Allt som ofta är man i behov av att skriva ut värdet av en variabel och då kanske man använder sig av echo eller print. Detta går så klart bra, men om man vill skriva ut en array eller ett object blir det problem. För detta ändamål finns den eminenta funktionen print_r(). Funktionen skriver ut data om en variabel på ett strukturerat sätt. Är det en skalär (”vanlig variabel”) skriver den ut den som om man hade använt echo, men är det en array skriver den ut ut värdet av varje element med indrag så att det blir snyggt och prydligt. Ett hett tips är att göra en egen funktion som först skriver ut HTML-taggen <pre> innan den anropar print_r(). Såhär t.ex.

function dump()
{
echo ’<pre>’;

$num_args = func_num_args();
for ($i = 0; $i < $num_args; ++$i)
{
print_r(func_get_arg($i));
echo ”\n\n”;
}

echo ’</pre>’;
exit;
}

Ovanstående funktion tar ett godtyckligt antal inparametrar vilket kan vara praktiskt när man utvecklar. Vill du t.ex. skriva ut värdet av variabeln $name och arrayen $addresses anropar du funktionen med:

dump($name, $addresses);

Lita inte på indata från användaren

december 8th, 2017

Det absolut viktigaste att ha i åtanke om man vill skriva PHP-kod utan säkerhetshål är att aldrig lita på data som kommer utifrån, dvs. från användaren. Även om man förväntar sig att ett id-nummer från URL:en (t.ex. ”script.php?id=5”) skall vara ett heltal, får man aldrig lita på att det är det. Det är inga problem att byta ut femman i URL:en mot en annan siffra eller mot lite SQL. Detsamma gäller data som skickas över POST eller via cookies. Att byta ut indata så att skriptet kör en annan SQL-sats än den programmeraren tänkt kallas att göra en SQL-injektion. SQL-injektioner är troligtvis det största säkerhetproblemet i all webbprogrammering.

Hur förhindrar man detta då? Jo, genom att validera all data som kommer från användaren. Om man förväntar sig ett heltal större än 0 (t.ex. ett id-nummer) ser man till att denna variabel faktiskt är ett heltal. Man kontrollerar också, om möjligt, att detta heltal är rätt heltal. Vi börjar med att illustrera hur lite osäker PHP-kod skulle kunna se ut. Följande exempel skall ta bort en rad i databasen:

mysql_query(’DELETE FROM tabell WHERE id=’.$_GET[’id’]) or exit(mysql_error());

Det där kommer fungera jättebra så länge id från URL:en är ett heltal och det är rätt heltal. Vem som helst kan dock byta ut id i URL:en till något annat tal och på så sätt radera en helt annan rad än den det var tänkt. Något som är ännu värre är dock att man kan byta ut femman mot lite vanlig text. Vad hade t.ex. hänt om man anropat skriptet med ”script.php?id=id”? Då hade följande SQL-sats körts:

DELETE FROM tabell WHERE id=id

Dvs. radera alla rader där id=id. Det hade raderat alla rader i tabellen! Inte bra. För att förhindra att id är något annat än det man förväntar sig (i det här fallet ett heltal) kan man använda t.ex. intval(). Det intval() gör är att det försöker tyda heltalsvärdet av en variabel. Har en variabel värdet ’5’ returnerar intval() heltalet 5. Har en variabel värdet ’asdf’ returnerar intval() heltalet 0 då den inte kan tyda något heltal i ’asdf’. Exakt hur intval() fungerar går att läsa i PHP-manualen. Ovanstående osäkra kod skulle kunna bytas ut mot det här:

mysql_query(’DELETE FROM table WHERE id=’.intval($_GET[’id’])) or exit(mysql_error());

Om man nu hade anropat skriptet med id=id hade intval() konverterat $_GET[’id’] till 0 och SQL-satsen som körts hade då blivit:

DELETE FROM tabell WHERE id=0

Eftersom man vanligtvis aldrig har id-nummer som är mindre än 1 skulle ovanstående kod vara ofarlig. Det kan dock vara en god idé att utföra lite mer kontroll av id-variabeln än så. Det är vanligt att man först tar reda på heltalsvärdet av id och sen kontrollerar så att det har ett vettigt värde. Om man t.ex. förväntar sig ett heltal mellan 1 och 1000 kan man göra såhär:

$id = intval($_GET[’id’]);

if ($id < 1 || $id > 1000)
exit(’Aja baja!’);

mysql_query(’DELETE FROM table WHERE id=’.$id) or exit(mysql_error());

Med några enkla knep har vi säkrat vårt skript från SQL-injektioner. Vårt skript är dock långt ifrån säkert. Som jag nämnde inledningsvis kan man ju bara byta ut id mot ett annat heltal och på så sätt ta bort en annan rad i databasen. Hur löser man detta då? Det är lite knepigare. Det man får göra är att på något sätt kontrollera att den aktiva användaren har rättigheter att radera raden i fråga. Alltså, innan man kör databasfrågan som tar bort raden, kontrollerar man så att $id är ett id som får tas bort. Hur man gör detta tänker jag inte gå in på. Det finns nämligen så många sätt. Vanligast är väl att köra en SELECT-fråga och ta reda på om $id får tas bort av den aktiva användaren.

Ett annat klassiskt misstag är att inkludera PHP-skript enbart baserat på vad som anges i URL:en. Det kan ibland vara praktiskt att skicka med en parameter till ett skript och att låta denna parameter bestämma vilket skript eller vilken sida som skall visas för besökaren. Man skulle t.ex. kunna tänka sig att man har ett skript index.php och att detta skript visar olika sidor beroende på vad man anger för page i URL:en. Skriver man in index.php?page=about.php skall sidan about.php inkluderas. Skriptet index.php kanske då kör följande kod:

include $_GET[’page’];

En mycket dålig idé. En illvillig användare kan bara byta ut about.php mot något annat skript som han/hon kanske inte har tillgång till vanligtvis eller kanske t.o.m. en känslig fil någon annanstans på hårdisken på servern. Om man anropat skriptet med t.ex. page=/etc/passwd hade det skrivit ut innehållet i passwd-filen (om det är ett *NIX-system). Tro mig när jag säger att det är en dålig idé.

En vanligt förekommande åsikt är att problemet kan lösas genom att tvinga dit en filändelse på slutet av det som skall inkluderas. Såhär:

include $_GET[’page’].’.php’;

Detta löser dock inte problemet. Om magic_quotes_gpc är avstängt i php.ini (vilket det bör vara), kan man komma runt skyddet genom att anropa skriptet med t.ex. page=/etc/passwd%00 där %00 representerar tecknet NUL (vilket PHP tolkar som slutet på en sträng). Att bara smälla dit en filändelse på slutet är alltså en dålig idé det också. Tack och lov finns det en snygg och effektiv lösning. Skriptet index.php kan säkras från denna typ av attack med följande lilla kodsnutt:

switch ($_GET[’page’])
{
case ’about’:
require ’about.php’;
break;

    case ’contact’:
require ’contact.php’;
break;

    default:
require ’default.php’;
break;
}

Anropas skriptet med page=about inkluderas about.php. Anropas det med page=contact inkluderas contact.php. Försöker man anropa det med något annat inkluderas en standardsida (default.php). I exemplet ovan använder jag require() istället för include(). Den enda skillnaden mellan de två är att include genererar en varning om filen inte kan inkluderas och require genererar ett fel så att skriptet avbryts. Man bör alltså använda require om man inte vill att skriptet skall fortsätta exekvera om en filinkludering misslyckas. Jag kan inte tänka mig en situation när man vill det, så mitt tips är att ni håller er till require. Om man är osäker på om filen redan kan ha inkluderats tidigare, kan man välja att använda require_once() istället.

Kontrollera alltid returvärdet från mysql_query()

december 7th, 2017

Då man ställer en fråga mot MySQL (eller någon annan databas) är det viktigt att alltid kontrollera så att inget gick fel. Det är mycket vanligt att folk missar detta och när de då några rader senare skall hämta ut de data de förväntar sig SQL-frågan returnerat, får de det notoriska felmeddelandet ”supplied argument is not a valid MySQL result resource”. Det enklaste sättet att kontrollera så att mysql_query() gick som det skulle är att lägga till en liten villkorssats efter anropet. Såhär t.ex.

$sql = ’SELECT foo FROM bar WHERE id=’.$id;
$result = mysql_query($sql) or exit(mysql_error());

Om SQL-frågan av någon anledning inte går som den ska kommer PHP avsluta skriptet och skriva ut felmeddelandet från MySQL. I 95% av fallen är detta tillräckligt för att man ska kunna se vad som är fel. Är man osäker kan man skriva ut SQL-frågan istället för att köra den. Alltså:

$sql = ’SELECT foo FROM barWHERE id=’.$id;
exit($sql);

Förlita dig inte på register_globals

december 7th, 2017

Om man programmerat PHP ett tag har man säkerligen stött på register.globals tidigare. Denna inställning i PHP:s konfigurationsfil php.ini gör att all data som skickas via GET, POST, cookies och sessions automagiskt registreras som variabler. Om man t.ex. skriver in ”script.php?id=5” i adressfältet när man kör ett skript kommer det automatiskt skapas en variabel $id med värdet 5. Detta må vara praktiskt i många fall, men det leder allt för ofta till säkerhethål i skripten.

Hur gör man istället då? Jo, sedan version 4.1.o finns det i PHP ett antal arrayer som man har tillgång till överallt i sin PHP-kod. Dessa är de s.k. superglobala arrayerna och de heter $_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_REQUEST och $_SESSION.  Istället för att förlita sig på att det finns en variabel $id helt automatiskt, får man åtkomst till id genom $_GET[’id’].

PHP enkelfnuttar eller dubbelfnuttar (citattecken)

juni 29th, 2017

Skillnaden mellan enkelfnuttar och dubbelfnuttar i php kan ibland vara avgörande.

Ta exemplet:

&lt;?php
echo 'hello world in techbowl';
?&gt;
&lt;?php
echo "hello world in techbowl";
?&gt;

Dessa rader producerar exakt samma resultat men den med enkelfnuttar är bättre eftersom de ger exakt det resultat som står mellan dem, medans med  dubbelfnuttar så processas  det som står mellan fnuttarna.

Ett exempel:

&lt;?php

$example = 'hello world in techbowl';

echo '$example'; // outcome will be $example

echo "$example"; // outcome will be hello world in techbowl
?&gt;

Så om man inte behöver processa det som skrivs mellan fnuttarna blir det effektivare att använda enkelfnuttar. I enstaka utfall blir naturligvis skillnaden minimal men om du har en loop som kör tusentals gånger så blir skillnaden avgörande.

PHP loopar och uppräkning

juni 29th, 2017

 

Loopar och uppräkning används ofta vid programmering.

Principen är enkel men det finns några sätt att göra dina loopar eller uppräkningar mer effektiva.

Sätt max-värdet för din loop innan och inte i loopen så behöver du inte anropa din count() funktion i varje loop:

$max = count($array);
for ($i = 0; $i &lt; $max; $i++)
//is faster than
for ($i = 0; $i &lt; count($array); $i++)
When checking the length of strings:
Use isset where possible in replace of strlen. (cite)
if (!isset($foo{5})) { echo "Foo is too short"; }
//is faster than
if (strlen($foo) &lt; 5) { echo "Foo is too short"; }

array_pop

februari 22nd, 2013
mixed array_pop ( array &$array )

Med hjälp av funktionen array_pop så kan man snabbt och smidigt returnera det sista värdet i en array eller ett fält samtidigt som detta plockas bort från densamma. Ifall variabeln är tom, eller inte en array, så kommer NULL att returneras. En varning blir dessutom resultatet om man försöker applicera funktionen på en variabel som inte är en array.

Exempel

$cars = array("Volvo", "Saab", "Toyota");
$toyota = array_pop($cars);
print_r($cars);

Skriver ut:
Array
(
[0] => Volvo
[1] => Saab
)