Fra PDF til PNG med PHP på Windows

May 27, 2010 · Posted in Udvikling · Comment 

Her kommer en lille hurtig guide til hvordan man på en Windows maskine får sin PHP-installation til at konvertere PDF’er til PNG’er.

For at teste at alt er gået godt kan du teste med nedenstående script der konverterer første side af test.pdf om til et billede, og sender det til browseren:

<?php
  $im = new Imagick();
  $im->setResolution(130, 130);
  $im->readImage('./test.pdf[0]');
  $im->setImageFormat("png");
 
  header("Content-Type: image/png");
  print $im;

Bemærk at der kan være kommet nye versioner når du læser dette …

Streaming med flowplayer

March 12, 2010 · Posted in Udvikling · Comment 

Viser man video med flowplayer vil den som standard loade hele videoen, før end den begynder at afspille. Har man et 2 min. klip kan det nemt fylde 12 MB i god kvalitet. Det kan betyde at der nemt kan gå 20-30 sek. inden videoen begynder at afspille. Det er man typisk ikke interesseret i. Har man ikke en rigtig streaming server findes der dog alligevel et trick man kan bruge.

Der findes et H.264-streaming modul til Apache, som er meget nemt at sætte op. Bare følg de par trin på siden, og modulet virker. Når det er sat op, vil Apache kunne levere video fra vilkårlige steder i klippet.

Næste trin er at sætte flowplayer op til at bruge streaming. Her er det javascript-kode jeg bruger til at afspille med:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/javascript">
  $(document).ready(function() {
    flowplayer("player", {
      src:'flowplayer-3.1.5.swf',
      wmode: 'transparent'
    },
    {
      clip: {
        autoPlay: true,
        autoBuffering: true,
        provider: 'stream'
    },
    plugins:  {
      stream: {
        url: 'flowplayer.pseudostreaming-3.1.3.swf'
      },
      playlist: ['video.mp4']
    });
  });
</script>

Det der skal lægges mærke til er provider: 'stream' samt

1
2
3
stream: {
  url: 'flowplayer.pseudostreaming-3.1.3.swf'
},

Resten er almindelig brug.

Se mere om pseudostreaming på flowplayers hjemmeside.

Sådan fik jeg FFmpeg til at lave H.264

March 11, 2010 · Posted in Udvikling · Comment 

Til mit nye projekt combatclinic.com, som I sikkert har læst alt om ;-) leverer jeg video i H.264-format, og det encoder jeg med FFmpeg. Det viste sig at være lidt mere besværligt at sætte op end jeg havde regnet med, men her er min opskrift:

Tilføje følgende linje i /etc/apt/sources.list

deb http://www.debian-multimedia.org lenny main non-free

Kør apt-get update; apt-get install debian-multimedia-keyring for at opdatere pakkelisten.

Nu kan du installere FFmpeg og x264 ved at køre apt-get install ffmpeg x264.

Når du vil encode dine videoer skal du gøre det på følgende måde:

ffmpeg -i input.mov -vcodec libx264 output.mp4

Det var en meget hurtig guide, men også mest skrevet for at jeg selv kunne huske det til næste gang jeg skal gøre det :)

Undgå at folk linker til billeder

March 9, 2010 · Posted in Udvikling · Comment 

Hvis man vil undgå at folk linker til ens billeder eller videoer, kan man med mod_rewrite kigge på Referer-headeren, og se om brugeren kommer fra ens eget domæne

Her viser jeg hvordan man nægter adgang til .png-filer hvis folk ikke kommer fra www.example.com

1
2
3
RewriteEngine On
RewriteCond  %{HTTP_REFERER}  !^http://www.example.com/
RewriteRule \.png$ – [F]

[F] betyder Forbidden.

Det hjælper selvfølgelig ikke mod de folk der selv kan finde ud af at sætte Referer-headeren, men det hjælper mod almindelige browsere.

Sortering på tabeller

March 4, 2010 · Posted in Udvikling · 2 Comments 

Hvis der er en ting jeg hader, så er det at lave trivielle tabeller med sortering. Jeg har dog efterhånden fundet den løsning jeg bedst kan li’.

Typisk vil man ha’ noget html som dette:

1
2
3
4
5
<table>
  <tr>
    <th><a href="list.php?sort=name&amp;type=asc">Navn</a></th>
    <th><a href="list.php?sort=age&amp;type=asc">Alder</a></th>
[...]

Men det er pænt irriterende at generere linket, samt holde styr på om man sorterer stigende eller faldende, og der kommer sikkert også andre parametre med ind i URL’en. Så det har man ikke lyst til. Jeg ved godt at der findes Javascripts der kan sortere tabeller, men det virker kun hvis man ser hele tabellen, og ikke hvis der er flere sider.

Min løsning er at lave en form med nogle skjulte felter, og med manipulere den med jQuery når man klikker på th’erne.

Min tabel vil så se sådan ud:

1
2
3
4
5
<table>
  <tr>
    <th x:name="name" class="sortable">Navn</th>
    <th x:name="age" class="sortable">Alder</th>
[...]

I mit stylesheet har jeg selvfølgelig en

1
2
3
table th.sortable {
  cursor:pointer;
}

Og måske en text-decoration:underline så man kan se at man kan trykke på feltet.

Så laver jeg en form med to skjulte felter jeg bruger til at sortere med:

1
2
3
4
<form action="list.php" method="get" id="form">
  <input type="hidden" id="order_by" name="order_by" value="<{$smarty.get.order_by|escape|default:"name"}>"/>
  <input type="hidden" id="order_type" name="order_type" value="<{$smarty.get.order_type|escape|default:"asc"}>"/>
</form>

Derefter noget jQuery:

1
2
3
4
5
6
7
8
9
<script type="text/javascript">
$(document).ready(function() {
  $("th.sortable").click(function() {
    $("#order_by").val($(this).attr("x:name"));
    $("#order_type").val($("#order_type").val() == "desc" ? "asc" : "desc");
    $("#form").submit();
  });
});
</script>

Komprimer dit site og øg hastigheden

January 13, 2010 · Posted in Udvikling · Comment 

Apache har et lille lækkert modul der hedder mod_deflate, der gør det muligt at gzippe sine sider inden de sendes til brugeren. Det sparer båndbredte og øger hastigheden.

På et testsite fyldte forsiden til at begynde med 309 KB. Efter jeg tilføjede mod_deflate til min .htaccess fik jeg sitet ned på 143 KB. Hvilket betyder rigtig meget hvis ens site har et stort load. Det kan også have betydning ift. ens placering i søgemaskiner. Da loadtiden bl.a. kan indgå i søgemaskinens vurdering af, hvilken placering siden skal have.

For at bruge mod_deflate skal man indsætte følgende i sin .htaccess:

1
2
3
<IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/html text/css
</IfModule>

Hvilket aktiverer mod_deflate for text/html og text/css. Man kan selvfølgelig tilføje alle de typer man vil. Det er nok meget nærliggende også at tilføje text/plain, text/xml og application/javascript.

(Bemærk at javascript ikke er text/javascript)

Hvis man er på jagt efter en udelukkende php-løsning kan man tilføje

1
ob_start("ob_gzhandler");

I toppen af sine php-filer (eller i en include-fil der inkluderes på alle siderne), men mod_deflate har samme virkning og er nemmere at implementere. Det kræver dog, som med alt andet, at serveren understøtter det. Hvis man laver en

1
phpinfo();

Vil man under “Loaded Modules” kunne se om modulet er tilgængeligt.

For flere hastighedstips se mit indlæg om mod_expires.

Spore hvilke links brugeren trykker på

January 1, 2010 · Posted in Udvikling · 3 Comments 

I nogen tilfælde vil jeg holde styr på hvilke links brugeren trykker på når vedkommende forlader min side. Normalt vil jeg løse dette ved at tilføje et proxy-script der sender videre. Fx:

  <a href="redir.php?url=http://mbn.dk">mbn.dk</a>

Det gi’r dog nogle grimme adresser, og problemer hvis brugeren fx vil kopiere adressen og bruge den andre steder.

En løsning som jeg synes er pænere er at bruge noget Javascript der kigger på de events browseren fyrer af når man trykker på et link. Eks:

<script type="text/javascript">
  $(document).ready(function() {
    $("a[target=_blank]").mousedown(function() {
      $.post("link_tracker.php", { url: $(this).attr("href") } );
    });
  });
</script>

Efterfølgende skal link_tracker.php samle $_POST['url'] op og behandle den …

Bemærk at jeg kun matcher de events hvor target-attributten er sat til “_blank”. Jeg kan måske ved fordel matche på alle links, og så checke om de starter med “http://”. Jeg matcher på mousedown og ikke click af den simple årsag at mousedown matcher mere. Fx midterklik. Dog matcher den ikke hvis man trykker på linket via tastatur, men koden kan nemt udvides til at tage højde for de senarier.

Ovenstående kræver jQuery som jeg loader via:

<script type="text/javascript"
        src="http://www.google.com/jsapi"></script>
 
<script type="text/javascript">
  google.load("jquery", "1.3");
  google.load("jqueryui", "1.7");
</script>

Sprog i Smarty

December 28, 2009 · Posted in Udvikling · Comment 

I forlængelse at mit forrige indlæg vil jeg komme med nogle idéer til hvordan man kan tilføje sprogsupport i Smarty.

Det jeg gerne vil ende med er en løsning hvor jeg i mine templates kan skrive noget lignende:

1
<h1>{translate}Welcome to my site{/translate}</h1>

Men også

1
<title>{$title|translate}</title>

Jeg vil også kunne angive sproget direkte, fx:

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
 
<head>
<title>{$title|translate:"fr"}</title>
</head>
 
<body>
 
<h1>{translate lang="fr"}Welcome to my site{/translate}</h1>
 
</body>
 
</html>

Jeg vil aldrig kalde Smarty direkte, men altid via min egen klasse som extend’er Smarty. Det gør det bl.a. nemmere at sætte diverse indstillinger op. I min egen klasse vil jeg, for at understøtte sprog, tilføje en block og en modifier. Det gør jeg på følgende måde:

1
2
3
4
5
6
7
8
class mbnSmarty extends Smarty {
 
  public function __construct() {
    $this->register_modifier('translate', 'smarty_m_translate');
    $this->register_block('translate', 'smarty_b_translate');
  }
 
}

Bagefter skal jeg skrive de to funktioner hhv. smarty_b_translate og smarty_m_translate.

1
2
3
4
5
6
7
8
9
10
11
12
13
function smarty_b_translate($args, $str, &$smarty, &$repeat) {
  if (!$repeat) {
    $text = new Text();
    $text->setText($content);    
    return $text->translate($args['lang'] ? $args['lang'] : LANG);
  }
}
 
function smarty_m_translate($str, $lang = LANG) {
  $text = new Text();
  $text->setText($str);
  return $text->translate($lang);
}

Jeg har i mine eksempler gået ud fra, at der er defineret en LANG-konstant på følgende måde:

1
define("LANG", "da");

Jeg bruger også en Text-klasse, som I selv må lave :)

Sprogstyring via mod_rewrite

December 27, 2009 · Posted in Udvikling · Comment 

En lille idé til hvordan man kan styre sprog via Apaches mod_rewrite.

Normalt definerer jeg en konstant ved navn URL der indeholder den absolutte adresse til forsiden af mit website. Fx:

1
define("URL", "http://www.example.com");

Hver gang jeg skal linke i HTML/Smarty eller sende videre via PHP bruger jeg konstanten.

Nu vil jeg tilføje sprog som et ekstra “lag” på mine adresser, så jeg fremover kalder example.com/en/about.php for den engelske udgave, og example.com/fr/about.php for den fanske udgave af about.php; men jeg vil ikke have to versioner af about.php liggende.

Derfor laver jeg en lille rewrite-regl der omskriver førnævnte adresser til example.com/about.php?lang=en og example.com/about.php?lang=fr.

Reglen kan ses herunder. Bemærk at jeg kun checker på to a-z og ikke på de tilladte sprog. Det burde man måske gøre.

1
2
RewriteEngine On
RewriteRule  ^([a-z]{2})/(.*)$  $2?lang=$1 [QSA]

Jeg tilføjer QSA som betyder query string append, hvilket gør at eventuelle andre parametre til siden stadig kommer med.

Næste trin bliver at lave noget PHP der behandler ovenstående. Jeg vil typisk sætte min URL-konstant på i en header-fil der bliver inkluderet på alle sider. Før jeg definerer min konstant, laver jeg et check på $_GET['lang'] for at se om den er på listen over tilladte sprog. Er den det liver den tilføjet til konstanten, og på den måde vil alle mine linke indeholde sprogangivelsen.

1
2
3
4
5
6
7
8
9
$valid_languages = array("en", "de", "fr", "da");
 
if (in_array($_GET['lang'], $valid_languages)) {
  define("URL", "http://www.example.com/".$_GET['lang']);
}
 
else {
  define("URL", "http://www.example.com");
}

Det kan måske være meget smart at have to konstanter til URL’en. Én med sprog, og en uden, da det ikke er alle steder man vil angive sprog – fx billeder, stylesheets og javascript m.m.

E_NOTICE i PHP

December 16, 2009 · Posted in Udvikling · Comment 

Jeg ender altid med at kommer i slåskamp med andre php-udviklere omkring notices i koden, fordi min kode laver typisk mange. Hvis man lige har lært at slå notices til i php, vil man måske opfatte en notice som en fejl, men det er det ikke. Hvilket man også kan aflede af navnet – fejl plejer at hedde noget med error.

Jeg gør det typisk altid i if-sætninger for at gøre koden mere overskuelig og letlæselig. Nedenstående to eksempler viser først hvordan jeg plejer at lave mine if-sætninger, og sidste viser hvordan man skal skrive samme kode for at undgå en E_NOTICE.

1
2
  if ($id = (int) $_GET['id']) {
  }
1
2
3
  if (isset($_GET['id']) && is_numeric($_GET['id'])) {
    $id = (int) $_GET['id'];
  }

Man opnår det samme med de to stykker kode, men jeg vil mene at første er noget nemmere at læse.

Next Page »


  • Om websmed.dk

    Jeg hedder Morten, og jeg har udviklet webapplikationer siden slutningen af 90'erne.

    Jeg vil her dele ud af min erfaring, og med jævne mellemrum poste nogle tips og tricks, samt løsningsforslag på generelle dagligdags problemstillinger.

    Jeg har en forkærlighed for PHP og MySQL, hvorfor I nok vil se flest indlæg der vedrører den gren af webudvikling.

    Jeg har en anden blog af mere personlig karakter på mbn.dk, hvor I kan finde kontaktmuligheder m.m.

    Mine indlæg vil tit være baseret på problemstillinger i mit daglige virke, eller i mit eget firma MRLYTICS, hvor jeg sælger kundeundersøgelser samt kundedatabaser.

    Denne side er hostet hos slicehost.

  • Skrevet på Twitter