tag:blogger.com,1999:blog-66602783935044694072024-02-21T04:43:18.566+01:00kodkodkod;Unknownnoreply@blogger.comBlogger20125tag:blogger.com,1999:blog-6660278393504469407.post-18881360794211139732014-04-25T09:27:00.001+02:002014-04-25T09:27:35.650+02:00Sorteringsalgoritmer visualiserade med folkdans<div dir="ltr" style="text-align: left;" trbidi="on">
Youtube-kanalen <a href="https://www.youtube.com/user/AlgoRythmics/videos" target="_blank">AlgoRythmics</a> visar hur olika algoritmer för sortering fungerar genom folkdanser från olika kulturer.<br />
<br />
<b>Bubble-sort med Küküllőmenti legényes (ungern)</b><br />
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/lyZQPjUT5B4" width="560"></iframe>
<br />
<br />
<b>Merge-sort med Siebenbürgensachsare (tyskland)</b><br />
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/XaqR3G_NVoo" width="560"></iframe>
<br />
<br />
Alla danser hittar du på <a href="https://www.youtube.com/user/AlgoRythmics/videos" target="_blank">youtube-kanalen</a>.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-41426096225719861152011-06-10T16:58:00.000+02:002011-06-10T16:58:18.689+02:00Skriv var du vill i kommandoraden med ANSI-sekvenserI över 10 år har jag undrat hur en del kommandoradsprogram gör för att skriva ut något på en specifik position på skärmen istället för (som det brukar var) längst ned i kommandoraden. T.ex. är det många program som visar en progressbar över hur långt en installationen har kommit eller hur mycket som laddats ned av en fil, se t.ex. <code>wget</code>.<br />
<br />
Idag tog jag äntligen mod till mig och googlade fram svaret. <br />
<br />
Svaret är ANSI escape-sekvenser. Man skriver helt enkelt ut några speciella sekvenser av tecken för att flytta pekaren eller ändra färg etc.<br />
<br />
Här är några exempel på escape-sekvenser för att flytta pekarens position:<br />
<br />
<b>\033[r;kH</b> - flytta pekaren till rad <i>r</i> och kolumn <i>k</i><br />
<b>\033[nA</b> - flytta pekaren <i>n</i> positioner uppåt<br />
<b>\033[nB</b> - flytta pekaren <i>n</i> positioner ner<br />
<b>\033[nC</b> - flytta pekaren <i>n</i> positioner höger<br />
<b>\033[nD</b> - flytta pekaren <i>n</i> positioner vänster<br />
<b>\033[s</b> - lagra nuvarande pekar-position<br />
<b>\033[u</b> - återställ lagrad pekar-position<br />
<b>\033[K</b> - sudda allt på raden från pekarens position<br />
<br />
Några sekvenser för att formatera text:<br />
<b>\033[1m</b> - fet eller extra stark färg på<br />
<b>\033[4m</b> - understruken text<br />
<b>\033[7m</b> - förgrund och bakgrund byter färg<br />
<br />
Några sekvenser för att byta färg på texten:<br />
<b>\033[31m</b> - röd text på svart bakgrund<br />
<b>\033[41m</b> - vit text på röd bakgrund<br />
<b>\033[32m</b> - grön text på svart bakgrund<br />
<b>\033[42m</b> - vit text på grön bakgrund<br />
<b>\033[33m</b> - gul text på svart bakgrund<br />
<b>\033[43m</b> - vit text på gul bakgrund<br />
<b>\033[34m</b> - blå text på svart bakgrund<br />
<b>\033[44m</b> - vit text på blå bakgrund<br />
<br />
Fler kommandon och mer info kan du hitta <a href="http://www.scribd.com/doc/51950177/191/Moving-The-Cursor" target="_blank">här</a>, <a href="http://en.wikipedia.org/wiki/ANSI_escape_code" target="_blank">här</a>, <a href="http://www.fantasi.se/article.php?key=escape-sekvenser" target="_blank">här</a> och <a href="http://www.robvanderwoude.com/ansi.php" target="_blank">här</a>.<br />
<br />
<h4>Ett par exempel med PHP</h4>Så för att t.ex. skriva ut något på en viss position i terminalen med php kan man göra en funktion som ser ut såhär:<br />
<br />
<pre class="php" name="code">function echoAt($row,$col){
echo "\033[s"; //lagra pekarens position
echo "\033[".$row.";".$col."H"; //flytta pekaren
echo $text; //skriv ut texten
echo "\033[u"; //återställ pekarens position
}
</pre><br />
Jag skrev även en lite mer komplicerad funktion som ritar ut en progressbar. <br />
<br />
<pre class="php" name="code">function printProgressbar($percentage,$size=50){
$filled = round($percentage*$size); //hur mycket ska vara ifyllt?
$info = number_format($percentage*100, 1, '.', '')."%"; //formatera info
$infoStart = intval($size/2-strlen($info)/2); //vill ha info centrerad
$output = "\033[s"; //lagra pekarens position
$output .= "\033[7m"; //invertera färger
$output .= "\033[35m"; //sätt färg för ifylld del
$output .= "\033[1000C"; //gå max till höger
$output .= "\033[".$size."D"; //gå till vänster
for($i=0; $i<$size; $i++){
if($i==$filled) $output .= "\033[37m"; //byt färg för ofylld
if($i>=$infoStart&&$i<$infoStart+strlen($info)){
$output .= substr($info,$i-$infoStart,1); //skriv ut info
}else{
$output .= " ";
}
}
$output .= "\033[u"; //återställ pekarens position
echo $output;
}
</pre>
<br>
Om du vill testa funktionen men inte har något tidskrävande jobb att använda den till så kan du testa med följande rader:<br>
<br>
<pre class="php" name="code">for($i=0; $i<=1000; $i++){
usleep(1500);
printProgressbar($i/1000.0);
}
</pre>
<br><br>
Så här ser den ut när den kör:
<br><br>
<img border="0" class="noborder" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB2Aik0-ksUmpq1Pt26picxgtijUDpdBtDekAtIfbR23nmDIpRTCn7kZPJh2PqQKShBLZS0CiTpa-elcZA-_aznXB0CsBqnxifYgyS16xYN4QTh1wvmrmdumHs19MJ9K8GHERWaPEGSNkN/s800/progressbar2.png" />
<br><br>
Hoppas du får någon nytta av detta. Jag har själv börjat lägga in progressbarer i alla jobb som tar mer än några sekunder.
Ett litet problem är dock att om man loggar utskrifterna från ett jobb och sedan öppnar det i en texteditor (typ <code>vim</code>) så får man massor av ANSI-sekvenser som gör loggen helt oläsbar. Skriver man däremot ut loggen med <code>cat</code>, <code>tail</code> eller liknande så spelas progressbaren upp i repris.
<h4>För windows-användare</h4>Sedan windows NT så används inte ANSI i DOS/kommandotolken. Men du kan aktivera det manuellt.
<br><br>
Öppna <code>c:\windows\system32\config.nt</code><br>
Lägg till följande rad längst ned i filen:<br>
<code>device=%SystemRoot%\system32\ansi.sys</code><br>
Starta om datorn.<br>
<h4>ANSI Art</h4>Har du inga program som behöver progressbars eller andra nyttiga ändamål för denna kunskap så kan du alltid använda ANSI-sekvenser för att skapa konst.
<br><br>
<iframe width="640" height="390" src="http://www.youtube.com/embed/r_cYOi3pnhA?rel=0" frameborder="0" allowfullscreen></iframe>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-43916837888766476552011-05-09T10:01:00.001+02:002011-05-09T10:01:00.174+02:00Från latin1 till UTF-8 i PHP och MySqlNär jag skapade databasen till Sovrat som senare skulle bli Pusha.se för ganska precis 5 år sedan hade jag inga större kunskaper om encoding. Latin1 (ISO-8859-1) var standard i min MySql-installation så latin1 fick det bli. För ett par veckor sedan tog jag tjuren vid hornen och konverterade allt till utf-8.<br />
<br />
Tänkte skriva ned några av de lärdomar jag dragit av konverteringsarbetet. Mest för att jag själv ska komma ihåg det om jag behöver göra det fler gånger och även för att någon annan stackare i samma situation ska få det lite lättare.<br />
<br />
<b>Ändra encoding överallt</b><br />
Det finns ganska många ställen man måste byta encoding på för att det ska få önskad effekt. Man ser inte heller om man gjort rätt förrän man bytt på alla dessa platser. Se till att följande använder utf-8 som encoding:<br />
<ul><li>MySql-databasen<br />
<pre class="sql" name="code">ALTER DATABASE databasnamn CHARACTER SET utf8;</pre></li>
<li>Varje databastabell<br />
<pre class="sql" name="code">ALTER TABLE tabell CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT = DYNAMIC;</pre></li>
<li>Varje kolumn i varje databas<br />
<pre class="sql" name="code">ALTER TABLE tabell MODIFY COLUMN kolumn VARCHAR(60) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;</pre></li>
<li>PHP-filerna med själva PHP-koden</li>
<li>setlocale i PHP<br />
<pre class="php" name="code">setlocale(LC_ALL, 'sv_SE.UTF-8', 'sve');</pre></li>
<li>Content-Type i HTTP-headern<br />
<pre class="php" name="code">header('Content-Type: text/html; charset=UTF-8');</pre></li>
<li>Content-Type i HTML-headern<br />
<pre class="html" name="code"><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></pre></li>
<li>MySql-anslutningen<br />
<pre class="php" name="code">mysql_set_charset('utf8',$link);</pre></li>
</ul><br />
<b>PHP inte byggt för UTF-8</b><br />
Av historiska skäl är PHP:s stöd för UTF-8 inte det bästa. T.ex. fungerar nästan ingen av de vanliga strängfunktionerna som <i>strlen()</i>, <i>substr()</i> m.fl. Detta beror på att PHP jobbar med en teckenkodning där varje tecken består av 1 byte medan det i UTF-8 även finns tecken som tar 2 eller 3 byte. <br />
<br />
Ett möjligt sätt att ta sig runt detta är att använda <i>utf8_decode()</i> och <i>utf8_encode()</i>. Om du t.ex. vill mäta längden på en sträng som är encodad med utf8 så kan du först decoda den innan du mäter. <br />
<br />
<pre class="php" name="code">$len = strlen(utf8_decode($utf8str));
</pre><br />
Vill man klippa en utf8-sträng så decodar man först, klipper och sen encodar man igen.<br />
<br />
<pre class="php" name="code">$utf8str = utf8_encode(substr(utf8_decode($utf8str),0,10));
</pre><br />
Ovanstående lösning blir dock ganska snabbt väldigt svårläst och ful och verkar dessutom inte fungera för riktigt konstiga tecken som kräver 3-byte. Vill man ha en snyggare lösning så får man istället använda PHP:s multibyte-funktioner. Dessvärre är <i>mbstring</i>-modulen inte installerad i PHP per default utan du måste själv <a href="http://www.php.net/manual/en/mbstring.installation.php" target="_blank">installera den</a>.<br />
<br />
När du väl har <i>mbstring</i> aktiverat så heter alla strängfunktioner precis som tidigare men med <i>mb_</i> före. T.ex. <i>mb_strlen()</i>, <i>mb_substr()</i>, <i>mb_strtolower()</i> o.s.v.<br />
<br />
Vissa strängfunktioner finns tyvärr inte i <i>mbstring</i> men däremot tar dessa funktioner en extra parameter där man kan specificera en encoding. Exempel på sådana funktioner är t.ex. <i>htmlentities()</i>, <i>htmlspecialchars()</i> m.fl. <br />
<br />
<pre class="php" name="code">$text = htmlentities($text,ENT_COMPAT,'UTF-8');
</pre><br />
Vissa reguljära uttryck kan förenklas lite när man använder UTF-8. Tidigare var jag tvungen att använda <code>a-zA-Z\xe5\xe4\xf6\xc5\xc4\xd6</code> för att få med åäöÅÄÖ men efter övergången fungerade det istället bra med <code>a-öA-Ö</code>.<br />
<br />
<b>Övrigt</b><br />
Jag har sett många rekommendationer att man ska köra följande två kommandon så fort anslutningen till MySql har skapats:<br />
<br />
<pre class="php" name="code">mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET utf8");
</pre><br />
Det har dock inte varit nödvändigt i mitt fall men det är något att testa om man har problem.<br />
<br />
Om man vill slippa ändra till UTF-8 manuellt för varje kolumn i en tabell så ska det fungera att använda följande query istället:<br />
<br />
<pre class="sql" name="code">ALTER TABLE tabellnamn CONVERT TO CHARACTER SET utf8;
</pre><br />
Jag tyckte dock att det kändes tryggare att konvertera en kolumn i taget. Speciellt då det ibland uppstod konverteringsfel som gjorde att man manuellt var tvungen att fixa någon rad i databasen. När man har väldigt många rader så tar det ett tag att bara konvertera en enda kolumn.<br />
<br />
I vissa fall kan det ha betydelse vad för <i>collation</i> man väljer för en kolumn i MySql. Det vanliga är <code>utf8_general_ci</code> men den har vissa brister som t.ex. innebär att åäö sorteras som aao. Vill man ha korrekt sortering kan man använda <code>utf8_unicode_ci</code> eller <code>utf8_bin</code>. Den senare jämför tecknen binärt vilket gör dina querys case sensetive.<br />
<br />
Se för allt i världen till att ha <b>backup på allt</b> innan du påbörjar ett konverteringsarbete.<br />
<br />
<b>Lycka till!</b>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-6660278393504469407.post-32416526913529790002011-02-04T14:13:00.001+01:002011-02-04T14:14:26.658+01:00Varning för NOT-operatorn i MySQL med indexPå senare tid har jag ibland använt NOT-operatorn ! i MySQL. T.ex. för att hämta alla registreringar som ännu ej processats:<br />
<br />
<pre class="sql" name="code">SELECT * FROM registrations WHERE !processed;
</pre><br />
Fältet <i>processed</i> i det här fallet är av typen TINYINT(1) (BOOLEAN).<br />
<br />
Idag upptäckte jag till min stora förvåning att om jag lägger ett index på <i>processed</i> så har det ingen som helst effekt om jag använder ! eller NOT för att hitta raderna.<br />
<br />
<pre class="sql" name="code">mysql> DESCRIBE SELECT * FROM registrations WHERE !processed;
+------+---------------+------+---------+------+--------+-------------+
| type | possible_keys | key | key_len | ref | rows | Extra |
+------+---------------+------+---------+------+--------+-------------+
| ALL | NULL | NULL | NULL | NULL | 578614 | Using where |
+------+---------------+------+---------+------+--------+-------------+
</pre><br />
Om jag däremot gör en helt vanlig jämförelse med 0 eller FALSE (som egentligen borde vara samma sak) så funkar det bra:<br />
<br />
<pre class="sql" name="code">mysql> DESCRIBE SELECT * FROM registrations WHERE processed=FALSE;
+------+----------------+----------------+---------+-------+------+-------+
| type | possible_keys | key | key_len | ref | rows | Extra |
+------+----------------+----------------+---------+-------+------+-------+
| ref | processedindex | processedindex | 1 | const | 1 | |
+------+----------------+----------------+---------+-------+------+-------+
</pre><br />
I den här tabellen med nästan 600 000 rader tog queryn med ! 0.60 sekunder medan den som använde indexet tog 0.00. <br />
<br />
Så kom ihåg! Använd inte "!", "NOT", "IS FALSE" eller liknande utan gör istället jämförelser med =. Även om de logiskt ger samma resultat.<br />
<br />
<i>Om någon vet varför det är på detta sätt så får ni gärna skriva en kommentar. Har sökt lite men inte hittat någon information om detta.</i>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-46008758214457135762011-02-04T09:59:00.002+01:002011-02-04T10:02:24.713+01:00Styr webbläsaren med din iPhones gyroskopMika Tuupola har gjort ett inspirerande experiment som blandar flera av de senaste och hetaste teknikerna. Han får en HTML5-logga som visas i webbläsaren på hans dator att rotera med hjälp av sin iPhones gyroskop. <br />
<br />
<iframe src="http://player.vimeo.com/video/19451023" width="610" height="458" frameborder="0"></iframe><br />
<br />
Gyroskopet får han tillgång till med iPhones <a href="https://developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/DeviceOrientationEventClassRef/DeviceOrientationEvent/DeviceOrientationEvent.html" target="_blank">DeviceOrientation API</a>. Kommunikationen mellan webbläsaren och iPhonen sker över en socketanslutning som skapats med <a href="http://dev.w3.org/html5/websockets/" target="_blank">WebSocket</a> som är en del av HTML5. Rotationen av loggan görs med <a href="http://www.w3.org/TR/css3-3d-transforms/" target="_blank">3D Transformationer i CSS3</a> (endast webkit än så länge).<br />
<br />
Testa själv:<br />
<a href="http://www.appelsiini.net/demo/websocket/html5.html" target="_blank">Öppna denna länk i safari på din dator</a><br />
<a href="http://www.appelsiini.net/demo/websocket/iphone.html" target="_blank">Öppna denna länk i din iPhone med iOS 4.2 eller högre</a><br />
<br />
Läs <a href="http://www.appelsiini.net/2011/iphone-controlled-html5-logo-and-cube" target="_blank">Mika Tuupola eget blogginlägg</a> om detta.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-23976167663180357322011-02-02T13:46:00.002+01:002011-03-01T08:35:26.802+01:00Radera aldrig data!Flickr är en av några få webbtjänster som jag faktiskt betalar för. Jag tycker flickr är snyggt, enkelt att använda och framförallt har det känts tryggt att ha sina fotografier (som kanske är det värdefullaste man har) lagrade i molnet och inte på någon egen hårddisk som kan krascha när som helst. Idag slutade det dock kännas tryggt. <br />
<br />
Flickr har råkat radera en betalande flickr-användares konto när de skulle radera någon helt annan som hade laddat upp copyright-skyddat material. Det är ungefär 4000 bilder som dessutom var flitigt inlänkade på andra sajter som har försvunnit. Flickr erbjöd den drabbade kunden 4 års gratis pro-medlemskap som ersättning. Mer om detta finns att läsa hos <a href="http://techcrunch.com/2011/02/02/flickr-accidentally-wipes-out-account-five-years-and-4000-photos-down-the-drain/" target="_blank">Techcrunch</a>.<br />
<br />
Några saker som man (framförallt flickr) kan lära sig av detta:<br />
<br />
<b>1. Det ska aldrig gå att radera information</b><br />
En webbtjänst bör aldrig innehålla en möjlighet att på riktigt radera information. Inte i admin-gränssnitt, ingenstanns. Man kan ha ett system för att markera saker som raderade så att de döljs för användarna men att på riktigt ta bort informationen finns det absolut ingen anledning till, speciellt inte när lagringsutrymme idag i princip är gratis.<br />
<br />
Jag brukar inte ens ge mina mysql-användare rättigheter att köra DELETE-kommandot.<br />
<br />
<b>2. Ta backup</b><br />
Att ta backup på all data åtminstone en gång per dygn borde vara en självklarhet. Speciellt om man har flera miljoner användare.<br />
<br />
<b>3. Ge en rimlig kompensation</b><br />
Om du klantar till det, visa att du tar det på allvar. Ge en kompensation som svider. När flickr erbjuder 4 års pro-medlemskap så förstår alla att det inte kostar dom ett öre. De kan med andra ord klanta till det hur många gånger som helst. De borde istället visa att det här var ett riktigt katastrofalt misstag, händer det igen förtjänar vi inte att få finnas kvar. Jag tycker inte en kompensation på $100 000 hade varit för mycket i det här fallet.<br />
<br />
Till sist tycker jag att det är märkligt av flickr att överhuvudtaget stänga av konton för att de innehåller copyright-skyddat material. De borde kanske dölja de aktuella bilderna och varna medlemmen några gånger först innan de bestämmer sig för att radera alla dess bilder för all framtid.<br />
<br />
<b>UPPDATERING:</b> <i>Flickr lyckades tillslut återställa personens bilder, så någon backup hade de trots allt. 25 års pro-medlemskap fick han också vilket känns som en rimlig kompensation när de faktiskt fick tillbaka bilderna.</i>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-6660278393504469407.post-76718528461427150702010-08-10T16:50:00.000+02:002010-08-10T16:50:44.622+02:00Unspecified Error vid användning av pasteHtml i Internet ExplorerEftersom Internet Explorer saknar stöd för execCommand med parametern "insertHtml" så får man använda sig av pasteHtml istället. <br />
<br />
<pre class="js" name="code">var html = "<strong>test</strong>";
if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
if (range.pasteHTML) {
range.pasteHTML(html);
}
}else{
document.execCommand("insertHtml", false, html);
}
</pre><br />
Första gången jag använde metoden ovan så fungerade det perfekt. Men idag när jag skulle göra samma sak så fick jag ett "Unspecified error" i Internet Explorer. Inte helt oväntat så är det lite svårt att felsöka ett "Unspecified error". Jag har ägnat halva dagen åt att googla problemet utan resultat. Till slut kom jag fram till att problemet berodde på att man måste ge det aktuella fönstret fokus. I detta fall så gällde det en iframe där jag ville klistra in kod så där såg lösningen ut såhär:<br />
<br />
<pre class="js" name="code">document.getElementById("iframeId").contentWindow.focus();
</pre><br />
Förhoppningsvis hittar ni denna lösning i google nu :)Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6660278393504469407.post-31825791247894480152010-06-08T22:00:00.000+02:002010-06-08T22:00:29.841+02:00Kör maskinkod i användarens webbläsare med Native Client (NaCl)Även om javascript bara blir snabbare och snabbare så ligger det ganska långt ifrån hastigheten på riktig maskinkod. Därför har Google startat ett projekt som heter Native Client (NaCl) som gör att man från javascript kan ladda ned och exekvera speciella exe-filer i användarens webbläsare. <br />
<br />
Det låter kanske lite läskigt men det verkar finnas ett väl genomarbetat säkerhetslager som kontrollerar att ingen farlig kod kan köras, man kommer t.ex. såklart inte åt användarens filsystem. Säkerhetskraven påverkar hastigheten något men det är ändå nästan lika snabbt som att köra ett vanligt program. <br />
<br />
En väldigt positiv sak är att man kan skriva sina spel eller beräkningstunga applikationer i vilket språk man vill så länge det har en NaCl-kompilator. <br />
<br />
Tyvärr är NaCl än så länge på ett tidigt experimentstadium men jag hoppas vi får se stöd för detta i alla browser inom kort.<br />
<br />
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/JSMWvC9p6Oc&hl=sv_SE&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/JSMWvC9p6Oc&hl=sv_SE&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object><br />
<br />
Mer info:<br />
<a href="http://code.google.com/events/io/2010/sessions/native-code-chrome.html" target="_blank">http://code.google.com/events/io/2010/sessions/native-code-chrome.html</a><br />
<a href="http://code.google.com/p/nativeclient/" target="_blank">http://code.google.com/p/nativeclient/</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-89335765561794435032010-06-01T16:13:00.000+02:002010-06-01T16:13:35.267+02:00Google dödar long-tail-trafikenGoogle har i början av maj gjort förändringar i sin algoritm som gör att undersidor på en sajt som inte har så många inlänkar inte längre rankar lika högt. Med andra ord kommer t.ex. permalänkar på bloggar att hamna betydligt lägre när bloggposterna blir äldre. <br />
<br />
<a href="http://www.webmasterworld.com/google/4125460.htm" target="_blank">WebmastersWorld</a> kallar denna uppdatering "Mayday" och google har bekräftat den, Matt Cuts säger:<br />
<br />
<blockquote>This is an algorithmic change in Google, looking for higher quality sites to surface for long tail queries. It went through vigorous testing and isn’t going to be rolled back.</blockquote><br />
Har du en blogg eller e-handelssajt har du förmodligen märkt av en kraftig minskning av trafik den senaste månaden som kanske inte enbart har orsakats av bra väder och förmodligen kommer att vara permanent.<br />
<br />
Det enda råd man kan ge är förmodligen att man bör försöka göra sig så oberoende av google-trafik som möjligt och satsa på att ge läsarna bra innehåll och en bra upplevelse snarare än att försöka optimera efter googles algoritm eftersom den ständigt förändras.<br />
<br />
Källor:<br />
<a href="http://www.webmasterworld.com/google/4125460.htm" target="_blank">http://www.webmasterworld.com/google/4125460.htm</a><br />
<a href="http://searchengineland.com/google-confirms-mayday-update-impacts-long-tail-traffic-43054" target="_blank">http://searchengineland.com/google-confirms-mayday-update-impacts-long-tail-traffic-43054</a>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-6660278393504469407.post-20503831713471557942010-05-31T23:53:00.001+02:002010-05-31T23:55:47.732+02:00Ladda php-klasser först när de ska användasIdag var jag på <a href="http://www.internetdagarna.se/pages/seminarier/optimera-sthlm" target="_blank">Optimera STHLM</a> och lyssnade på flera intressanta <a href="http://www.slideshare.net/internetfoundation" target="_blank">föreläsningar</a>. Det var inte jättemycket nytt under solen men inspirerade till att optimera sin kod än mer och kändes som ett väldigt bra initiativ av <a href="http://iis.se/" target="_blank">IIS</a>.<br />
<br />
En oväntad sak jag lärde mig var att php har en inbyggd funktion som talar om hur mycket minne ens php-script allokerat som mest under exekveringen, nämligen: <a href="http://www.php.net/manual/en/function.memory-get-peak-usage.php" target="_blank">memory_get_peak_usage()</a><br />
<br />
Jag var såklart tvungen att testa denna funktion på <a href="http://www.pusha.se" target="_blank">Pusha</a> där jag blev glatt överraskad av att Pusha som mest verkar använda 4mb minne. Till min förvåning visade det sig att <a href="http://qvaq.com">Qvaq</a> använde mer minne än vad Pusha gör vilket var väldigt märkligt eftersom Pusha består av betydligt fler klasser. Efter ett tag insåg jag dock att det beror på att vi på Pusha laddar in endast de klasser som verkligen används dynamiskt istället för att ladda alla klasser hela tiden.<br />
<br />
I vanliga fall kanske ens php-kod innehåller ett stort antal include-satser för att ladda in alla klasser man behöver, det kan se ut ungefär såhär (fast med hundratals rader):<br />
<br />
<pre class="php" name="code">include "classes/User.php";
include "classes/Link.php";
include "classes/Comment.php";
</pre><br />
För att istället ladda in en klass först när den behövs om den behövs över huvud taget så behöver man bara override:a funktionen <a href="http://php.net/manual/en/language.oop5.autoload.php" target="_blank">__autoload()</a>.<br />
<br />
Denna funktion anropas automatiskt i php så fort php stöter på en klass som den inte känner till och skickar med namnet på den saknade klassen som inparameter. Det enda du behöver göra i funktionen är alltså att inkludera den fil där klassen som saknas är definierad. Enklast tänkbara sätt att göra detta är såhär:<br />
<br />
<pre class="php" name="code">function __autoload($class) {
include "classes/".$class.".php";
}
</pre><br />
På Qvaq sänkte dessa förändringar minnesanvändningen med 0,5mb per sidladdning från 4,25mb till 3,75mb. Kanske ingen jättevinst men då innehåller inte Qvaq speciellt många klasser och har man många requests kan det bli en hel del sparat minne.<br />
<br />
Jag misstänkte att detta sätt att ladda in klasserna on-the-fly skulle göra att koden exekverades långsammare men enligt mina mätningar gick det lika snabbt eller möjligen till och med något snabbare.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-89628847971814544272010-05-20T20:01:00.000+02:002010-05-20T20:01:55.249+02:00Tiodubbla hastigheten på dina InnoDB-tabellerVi har precis fixat en ny databas-server till <a href="http://www.pusha.se">Pusha</a> och inatt satt jag uppe och försökte optimera inställningarna för MySQL. En förändring jag gjorde av standardinställningarna som gav oväntat bra effekt var att ändra <i>innodb_flush_log_at_trx_commit</i>. Denna variabel talar om för mysql hur ofta den ska skriva till loggen när man skriver till en innodb-tabell. <br />
<br />
Standardvärdet för <i>innodb_flush_log_at_trx_commit</i> är 1 vilket betyder att varenda uppdatering måste flushas till loggen direkt. Bygger man en bank så är nog detta att rekommendera men för de flesta applikationer som inte kräver extremt hög säkerhet så räcker nog värde 2 som innebär att man bara skriver till loggen en gång per sekund. Skulle operativsystemet krascha så förlorar man alltså maximalt en sekunds ändringar.<br />
<br />
Du ändrar värdet genom att lägga till denna rad under [mysqld] i /etc/mysql/my.cnf (eller var du nu har my.cnf):<br />
<br />
<pre>innodb_flush_log_at_trx_commit = 2
</pre><br />
Glöm inte att starta om mysql för att ändringen ska få effekt.<br />
<br />
Jag har inte gjort några exakta mätningar på hur stor skillnad detta gör men det blev synbart snabbare att pusha en länk på Pusha så det är minst 10 ggr så snabbt som med värdet 1.<br />
<br />
<a href="http://dev.mysql.com/doc/refman/4.1/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit" target="_blank">MySQL-dokumentationen för <i>innodb_flush_log_at_trx_commit</i></a><br />
<a href="http://www.mysqlperformanceblog.com/2006/09/29/what-to-tune-in-mysql-server-after-installation/" target="_blank">Fler tips på hur man finjusterar MySQL</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-53703650729957518062010-05-20T13:29:00.001+02:002010-05-20T13:30:44.976+02:00Spotify rekryterar med programmeringstävlingVill du ha ett jobb på <a href="http://www.spotify.com" target="_blank">spotify</a> så ska du boka in lördag den 29e maj i kalendern. Spotify anordnar då en programmeringstävling där man kan vinna (än så länge ospecifierade) priser och goda möjligheter till en anställning i företaget.<br />
<br />
På 4 timmar ska man lösa 6-8 uppgifter av en algoritmisk karaktär. Lösningarna ska skrivas i C, C++ eller Java och kommer att rättas av en dator. <br />
<br />
<a href="https://www.scrool.se/spotify/register" target="_blank">Mer information och anmälan</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-30308719131977403052010-05-20T11:24:00.000+02:002010-05-20T11:24:24.958+02:00Google lanserar Google Storage for DevelopersGoogle har <a href="http://googlecode.blogspot.com/2010/05/google-storage-for-developers-preview.html" target="_blank">lanserat</a> en tjänst för att lagra data i molnet - <a href="http://code.google.com/apis/storage/" target="_blank">Google Storage for Developers</a>. Egentligen en ren och skär kopia av <a href="http://aws.amazon.com/s3/" target="_blank">Amazon S3</a>. Även <a href="http://code.google.com/apis/storage/docs/overview.html#pricing" target="_blank">prissättningen</a> är i princip densamma som för S3, google storage är något dyrare men å andra sidan får man nu under deras "Preview" 100 gigabyte lagringsutrymme och 300 gigabyte bandbredd per månad gratis.<br />
<br />
Än så länge är tjänsten bara öppen för den amerikanska marknaden men förmodligen kommer det till Europa också så småningom.<br />
<br />
Det finns en sak som skulle kunna få mig att svika Amazon S3 och övergå till Google Storage. Om Google Storage tillåter att man döper objekt till en tom sträng så att man kan lägga in en "förstasida" för sin bucket så är jag såld. Tyvärr har jag inte lyckats utreda om det är så eller ej.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-36986256781145851482010-04-22T13:30:00.001+02:002010-04-22T13:32:24.988+02:00Världsbankens data nu tillgänglig för allaVärldsbanken som tidigare tagit betalt för sin data har nu bestämt sig för att de vill dela med sig av denna data gratis till alla och gör det på ett väldigt snyggt sätt på <a href="http://data.worldbank.org/" target="_blank">http://data.worldbank.org/</a>.<br />
<br />
<object height="385" width="640"><param name="movie" value="http://www.youtube.com/v/07LFJYB2o3I&hl=sv_SE&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/07LFJYB2o3I&hl=sv_SE&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFhgFC5KmwfY5VIxaUkI2eYDaLlKoc0r9c_0dmlU1NWhXkj3fQnqsdzVpMv_rxkL4po3bTfK-fuicdHdndcCSrKDNgQndC3506SIE8b1x-CZL_8kBf7A10_WB3dD8w2BDgPZTRYJ5ccPqd/s1600/rosling_small.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFhgFC5KmwfY5VIxaUkI2eYDaLlKoc0r9c_0dmlU1NWhXkj3fQnqsdzVpMv_rxkL4po3bTfK-fuicdHdndcCSrKDNgQndC3506SIE8b1x-CZL_8kBf7A10_WB3dD8w2BDgPZTRYJ5ccPqd/s320/rosling_small.jpg" /></a></div>Det kan mycket väl hända att vi till stor del har den fantastiska svensken Hans Rosling att tacka för detta. Han har under lång tid och i ganska hårda ordalag kritiserat världsbanken och dess chef Robert B Zoellick för att de inte delat med sig av datat. Rosling har bland annat sagt: <br />
<br />
<blockquote>"Det är underligt, på Pennsylvaniaavenyn i Washington finns två viktiga institutioner, Vita huset och Världsbanken. I den ena finns en ung, vald president och i den andra finns en gammal, tillsatt president. Den valda presidenten lärde sig genast använda internet och öppnade efter att ha valts sajten data.gov med fri tillgång till handlingar. Men den gamla presidenten säljer fortfarande sina data. Varför kan han inte promenera de 400 meterna till Vita huset för att lära av den unga presidenten?"</blockquote><br />
Rosling omnämns även i Världsbankens <a href="http://web.worldbank.org/WBSITE/EXTERNAL/NEWS/0,,contentMDK:22547256~pagePK:64257043~piPK:437376~theSitePK:4607,00.html" target="_blank">pressmeddelande</a> om att de öppnat upp datat.<br />
<br />
För dig som utvecklare är det såklart främst API:et som är intressant. Du hittar API-dokumentationen här: <a href="http://data.worldbank.org/node/10">http://data.worldbank.org/node/10</a><br />
<br />
<a href="http://www.dn.se/nyheter/varlden/varldsbanken-slapper-alla-siffror-fria-1.1081367" target="_blank">DN: Världsbanken släpper alla siffror fria</a>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6660278393504469407.post-263039747640651992010-04-22T13:05:00.001+02:002010-04-22T13:07:46.011+02:00Facebook dödar Facebook ConnectFacebook avlöjade på F8-konferensen igår sitt nya <a href="http://developers.facebook.com/docs/api" target="_blank">Open Graph API</a>.<br />
<br />
För utvecklare innebär det att det blir ett mer enhetligt api där man enkelt kan se hur olika facebook-objekt som användare, händelser, bilder o.s.v. hänger ihop. <br />
<br />
Vad gäller autentisering så kommer man på sikt att fasa ut Facebook Connect och istället ersätta det med <a href="http://oauth.net/" target="_blank">OAuth 2.0</a> (som twitter använder). Det är positivt på så sätt att OAuth är enklare och mer standardiserat än det virrvarr av javascript-requests som Connect består av. I samband med detta har man även gjort så att användaren bara behöver godkänna applikationen en gång istället för att behöva godkänna varje rättighet för sig som det är idag. Man skippar även de tidigare reglerna om att data bara får cacheas i 24 timmar vilket gör det betydligt enklare för oss utvecklare men kanske inte är helt bra ur användarnas synvinkel. <br />
<br />
Facebook har en historia av att vara väldigt radikala när de gör förändringar i sina api:er. Ofta tar de bort stöd för metoder samma dag som en inför en ersättning. Förhoppningsvis kommer de inte vara lika hårda denna gång, det vore tråkigt om de förstörde några miljoner Connect-sajter över en natt. Jag hoppas även att de tänkt igenom detta nya API ordentligt så vi slipper fler förändringar som gör att alla applikationer måste skrivas om från grunden.<br />
<br />
<a href="http://developers.facebook.com/docs/api" target="_blank">Graph API</a><br />
<a href="http://developers.facebook.com/docs/authentication/" target="_blank">Authentication</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-56114055589963098542010-04-19T22:52:00.001+02:002010-04-19T22:54:26.891+02:00Opacity i Internet ExplorerI CSS3 finns egenskapen <code>opacity</code> för att bestämma ett lagers transparens. Denna egenskap fungerar både i senare versioner av Firefox och Chrome. I Internet Explorer har man länge kunnat göra samma sak med filter: <code>alpha(opacity = 50);</code>. Detta har dock inte fungerat för lager som är relativt positionerade (vilket är nästan alla lager). <br />
<br />
Idag hittade jag dock en lösning på detta. Om man sätter <code>zoom: 1;</code> så börjar filtret fungera även för relativt positionerade lager. Så ett crossbrowser-säkert sätt att göra ett lager halvtransparent är detta:<br />
<br />
<pre class="css" name="code">.halvtransparent {
opacity: 0.5;
-moz-opacity:0.5;
filter: alpha(opacity = 50);
zoom: 1;
}
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-75320513551588889772010-03-17T23:33:00.002+01:002010-03-17T23:48:03.602+01:00Gzip-komprimering på Amazon S3Varje dag går världen miste om 99 år på grund av icke-komprimerat innehåll. Genom att gzippa dina html, css och javascript-filer m.m. kan många millisekunder sparas vid varje sidladdning samtidigt som du sparar bandbredd. Nästan alla webbservrar gzippar automatiskt innehåll om klienten berättar att den stöder gzip-kompression. Tyvärr gör inte Amazon S3 detta automatiskt.<br />
<br />
Även om inte S3 automatiskt skickar gzippade versioner av dina filer när klienten stöder gzip så kan du självklart lagra gzippade filer på S3. Du kan alltså komprimera t.ex. din css-fil lokalt och sedan ladda upp den till S3. Såhär gzippar du en fil i linux:<br />
<br />
<pre>gzip -c plain_text.txt > compressed.txt.gz
</pre><br />
Detta löser dock inte problemet helt för alla klienter stöder inte gzip och kommer alltså inte kunna läsa din komprimerade css-fil och därmed inte rendera din sajt korrekt.<br />
<br />
Den gyllene medelvägen blir att lagra både en okomprimerad och en komprimerad version på S3 med bara en liten skillnad i namnet, t.ex. <i>style.css</i> och <i>style.gz.css</i>.<br />
<br />
Sedan kan man med php eller något annat serverspråk enkelt avgöra om klienten har stöd för gzip och i så fall välja att ladda den gzippade versionen. Här är ett exempel på hur man tar reda på detta i php: <br />
<br />
<pre class="php" name="code"><?php
$gz = (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false)? 'gz.' : '';
?>
<link rel="stylesheet" type="text/css" href="http://s.example.com/style.<?=$gz?>css" />
</pre><br />
När du laddar upp den gzippade filen till S3 bör den ha "Content-Encoding: gzip" i sin header. Annars kommer inte webbläsarna förstå att innehållet är gzippat utan försöka läsa det som vanlig text. <br />
<br />
På <a href="http://www.pusha.se">Pusha</a> minskade vi på detta sätt storleken på vår css med 78% och javascriptet med nästan lika mycket.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-2750252347667364652010-03-05T18:55:00.002+01:002010-03-05T22:21:00.522+01:00Kom igång med XML-RPC och Loopias API<b>UPPDATERING</b>: Efter att jag skrivit detta inlägg upptäckte jag att <a href="http://ptz0n.se/">Erik Petterson</a> har skrivit en wrapper-klass till Loopias API så att man slipper tänka på XML-RPC. <a href="http://github.com/ptz0n/phpLoopia">Du hittar phpLoopia här</a>.<br />
<br />
<a href="http://www.loopia.se">Loopia </a>har släppt ett <a href="https://www.loopia.se/api/">API</a> som följer <a href="http://en.wikipedia.org/wiki/Xml-rpc">XML-RPC</a>-protokollet. Detta är första gången jag använder ett XML-RPC-api, nästan alla web-API:er man stöter på idag är av typen <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>. Därför tänkte jag skriva ned en snabb guide till hur man kommer igång med XML-RPC i PHP.<br />
<br />
För att komma åt Loopias API så måste du ha ett konto hos Loopia. Om du har det kan du skapa en API-användare under Kontoinställningar > LoopiaAPI.<br />
<br />
Vilka metoder som finns i API:t kan du se på <a href="https://www.loopia.se/api">https://www.loopia.se/api</a>. Den metod jag tänkte att vi skulle testa är <a href="https://www.loopia.se/api/domainisfree/">domainIsFree(username,password,domain)</a> som låter oss kontrollera om ett domännamn är ledigt eller upptaget.<br />
<br />
XML-RPC är inte inbyggt i PHP som standard så för att skapa en XML-RPC klient måste vi börja med att ladda ned ett bibliotek från <a href="http://phpxmlrpc.sourceforge.net/#download">phpxmlrpc.sourceforge.net</a>. Ladda ned 3.0.0Beta och packa upp. Filen vi behöver ligger i "lib" katalogen och heter xmlrpc.inc.<br />
<br />
<pre class="php" name="code">include "xmlrpc.inc";
$username = 'användare@loopiaapi';
$password = 'MittHemligaLösenord';
$domain = "kodkodkod.se";
$xmlrpcClient = new xmlrpc_client('RPCSERV','api.loopia.se',443);
$xmlrpcMsg = new xmlrpcmsg('domainIsFree',
array(new xmlrpcval($username,'string'),
new xmlrpcval($password,'string'),
new xmlrpcval($domain,'string')));
$xmlrpcResponse = $xmlrpcClient->send($xmlrpcMsg,0,'https');
if (!$xmlrpcResponse->faultCode()) {
if ($xmlrpcResponse->value()->scalarVal()=="OK"){
echo "Domänen ".$domain." är ledig";
}else if($xmlrpcResponse->value()->scalarVal()=="DOMAIN_OCCUPIED"){
echo "Domänen ".$domain." är upptagen";
}else{
echo "Ett oväntat fel inträffade";
}
}
</pre><br />
Koden är förhoppningsvis självförklarande. Vi skapar ett klientobjekt och vi skapar ett xmlrpc-meddelande (ett anrop till domainIsFree) som vi skickar till servern med klienten. Om vi inte får en felkod till svar så kollar vi om svaret är "OK" eller "DOMAIN_OCCUPIED". <br />
<br />
Dokumentationen till XML-RPC for PHP hittar du <a href="http://phpxmlrpc.sourceforge.net/doc-2/">här</a>.<br />
<br />
Om du bygger något med Loopias API har du just nu chansen att <a href="http://blogg.loopia.se/2010/02/25/vinn-en-ipad-%E2%80%93-skriv-den-smartaste-funktionen-for-loopiaapi/">vinna en iPad</a>.Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-6660278393504469407.post-2738707916903817342010-03-02T23:28:00.004+01:002010-03-02T23:50:00.792+01:00Anpassa koden för cacheminnenSka redovisa en gammal labb-rest i en kurs i Datorteknik på fredag. Labben handlar om cacheminnen så jag är ganska insnöad på det ämnet just nu.<br />
<br />
Något jag lärt mig av labben är att väldigt små skillnader i kod kan ge enorma skillnader i körtid. Jämför t.ex. dessa två olika sätt att addera två matriser:<br />
<br />
<pre class="cpp" name="code">for(j=0; j < MATRIX_SIZE; ++j){
for(i=0; i < MATRIX_SIZE; ++i){
res[i][j] = a[i][j]+b[i][j];
}
}
</pre><br />
<pre class="cpp" name="code">for(i=0; i < MATRIX_SIZE; ++i){
for(j=0; j < MATRIX_SIZE; ++j){
res[i][j] = a[i][j]+b[i][j];
}
}
</pre><br />
Enda skillnaden här är att exempel 1 loopar igenom matriserna kolumn för kolumn medan man i exempel 2 går igenom matriserna rad för rad. Båda exemplen ger exakt samma resultat men exempel nummer 2 är överlägset snabbare med vissa cacheminnen. Detta beror på att matriser lagras radvis i RAM-minnet (enligt C-standarden och många andra språkdefinitioner). När ett program refererar till en variabel som inte finns i cacheminnet så hämtas variabeln in från RAM-minnet. Dessutom hämtas närliggande data in eftersom man förmodligen kommer vilja använda närliggande data. I exempel 2 tjänar man mycket på detta eftersom man där läser i den ordning som matriserna ligger lagrade och alltså förhoppningsvis får ganska många träffar efter varje miss. I exempel nummer 1 kan det extra datat som hämtats in ha hunnit skrivas över innan man får användning av det.<br />
<br />
Jag kodade ett snabbt test i Java där jag adderar två matriser i storleken 1000x1000 på de två olika sätten. Här är exekveringstiderna: <br />
<br />
<pre>radvis kolumnvis
8.0ms 27.0ms
8.0ms 30.0ms
8.0ms 27.0ms
10.0ms 28.0ms
8.0ms 28.0ms
9.0ms 27.0ms
8.0ms 29.0ms
8.0ms 27.0ms
9.0ms 27.0ms
8.0ms 27.0ms
--------------------------------
8.4ms 27.7ms
</pre><br />
Att loopa igenom matriserna radvis är alltså i snitt mer än 3 gånger så snabbt som att göra det kolumnvis.<br />
<br />
För den som vill lära sig mer har KTH en omfattande PDF om <a href="http://www.ict.kth.se/courses/IS1200/2006-2007/komp-cmmu/cmmu.pdf" target="_blank">Cacheminnen och adressöversättning</a>.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6660278393504469407.post-85736155172079944362010-03-02T11:38:00.012+01:002010-03-02T15:26:00.127+01:00Posta på Twitter med PHPOm du vill göra en statusuppdatering på twitter med php så går det alldeles utmärkt med <a href="http://apiwiki.twitter.com/Twitter-API-Documentation">Twitters REST API</a>.<br />
<br />
Här är en enkel funktion som använder <a href="http://php.net/manual/en/book.curl.php">cURL</a> i php:<br />
<br />
<pre class="php" name="code"><?php
function tweet($twitterUser,$twitterPass,$tweet){
$url = "http://twitter.com/statuses/update.xml";
$data = "status=".urlencode(utf8_encode($tweet));
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERPWD, $twitterUser.":".$twitterPass);
curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpcode == 200) {
return true;
}else{
return false;
}
}
?>
</pre><br />
Och du anropar funktionen såhär:<br />
<br />
<pre class="php" name="code"><?php
tweet("MittTwitterNamn",
"MittHemligaTwitterLösen",
"Missa inte mitt inlägg på http://kodkodkod.se");
?>
</pre><br />
Om du inte har stöd för <a href="http://php.net/manual/en/book.curl.php">cURL</a> på ditt webbhotell borde det vara ganska enkelt att skriva om funktionen så att den använder <a href="http://php.net/manual/en/function.fopen.php">fopen</a> istället.<br />
<br />
På <a href="http://www.pusha.se/">Pusha</a> använder vi detta sätt för att posta heta länkar till @<a href="http://twitter.com/PushaHett">PushaHett</a> på twitter. Observera att denna funktion är lämpligast att använda om du vill posta statusuppdateringar på konton som du ansvarar för. Om du vill låta dina användare posta statusuppdateringar på sina egna twittersidor från din sajt bör du implementera <a href="http://apiwiki.twitter.com/Authentication">OAuth</a> istället för att fråga användarna efter deras lösenord.Unknownnoreply@blogger.com7