28
Tags:
ajax
php
jquery
Skrevet af
Bruger #8773
@ 28.05.2012
Mere avanceret brug
Et sted AJAX bliver brugt rigtigt meget, er på facebook. På facebook bruges AJAX når man laver en statusopdatering, til at hente de seneste nyheder på ens væg, til at hente kommentarer, til chatten, til at skrive kommentarer - ja faktisk mere eller mindre over alt på facebook. Det er netop dette der gør, at brugeroplevelsen bliver bedre da man ikke skal vente på at en form submittes for derefter at blive sendt tilbage til den side man lige kom fra.
I det følgende afsnit her vil jeg prøve at give et eksempel på tag-wall der fungerer udelukkende ved brug af AJAX.
Denne tag-wall skal fungere ved, at nye tags automatisk dukker op på væggen efterhånden som folk skriver dem. Når man selv skriver et nyt tag, skal dette også dukke op med det samme.
Med andre ord skal det hele altså køre dynamisk på denne tag-wall.
Der er dog et par overvejelser inden vi går i gang. Når vi skal hente det indhold andre personer skriver, er der et par forskellige måder at gøre dette på. En af de lidt ældre fremgangsmåder var, at have en timer der automatisk tjekkede for nyt indhold en gang i sekundet. Dette bliver dog utroligt ressourcekrævende hvis man f.eks. går ind på siden og så forlader denne en halv time for derefter at komme tilbage.
På den halve time vil man altså have lavet 30 minutter x 60 opdatering - altså 1800 forespørgsler - som er fuldstændigt ubrugelige når brugeren alligevel ikke har været aktiv på siden. En måde at gøre det på - som vist nok også er måden facebook håndterer det på - er, at hente indhold når man bevæger musen på siden. Når en bruger har bevæget musen på siden ved man, at denne person er aktiv. Man kan så have en timer der sætter brugeren som inaktiv hvis denne ikke har bevæget musen i 30 sekunder el.lign og derefter stopper hentning af data igen.
En anden måde at gøre det på, som godt nok er meget krævende for serveren i stedet, er, at sende en forespørgsel via AJAX til et PHP script. Dette PHP-script vil så køre en løkke indtil der bliver postet noget nyt i databasen. Dette gør at "success" funktionen ikke bliver kaldt i AJAX førend PHP-scriptet har fundet noget nyt data der skal vises. Dette kræver dog at der ikke er sat noget timeout i php-opsætningen på serveren og jeg kunne heller ikke forestille mig at det er specielt sundt for serveren hvis der er mange simultane brugere på siden. Denne metode kaldes long-poll, og skal nok gennemgås i en artikel for sig selv.
Jeg vil benytte mig af den første metode - altså den hvor vi henter indhold når en bruger er aktiv på siden i form af bevægelse med musen.
Databasen
Aller først vil jeg starte med at lave min database til tag-wall'en. Jeg har tænkt mig at det skal være en utrolig simpel tag-wall, og det skal derfor kun være navn, besked og et timestamp i databasen.
I vores database opretter vi derfor en tabel som vi kalder "ajax_tagwall" med følgende kolonner:
- CREATE TABLE `ajax_tagwall` (
- `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
- `thename` TINYTEXT NOT NULL ,
- `message` TEXT NOT NULL ,
- `timestamp` TINYTEXT NOT NULL
- )
Nogen vil måske undre sig over at jeg vælger at bruge typen TINYTEXT til timestamp i stedet for at bruge DATETIME, men det gør jeg da jeg synes det er lettere at arbejde med
PHP's time() funktion.
Håndtere forbindelsen til databasen
Da vi skal arbejde med forbindelse til databasen flere steder på siden, vil jeg anvende en klasse jeg har skrevet til formålet. Denne klasser har som sådan ingen relation til denne artikel, og jeg vil derfor ikke gennemgå i detaljer hvordan den fungerer. Hvis nogen har interesse i dette, skal I være velkommen til at kontakte mig eller foreslå at jeg skriver en artikel om dette på et senere tidspunkt.
Klassen er her:
- <?php
- /** This is a PHP class to access a MySql database and use
- * methods to access data.\n
- * For licence questions, contact: simon@rosmi.dk
- * @author Simon Smith (simon@rosmi.dk)
- */
- class Database{
- /** PRIVATE: The last result ressource of a query()
- */
- private $result;
- /** PUBLIC: connect to a MySql database to be able to use class methods.
- * @param $host the host
- * @param $user the MySql username
- * @param $pass the MySql password
- * @param $db the database to connect to
- */
- public function __construct($host,$user,$pass,$db) {
- $this->result=null;
- mysql_connect($host, $user, $pass);
- mysql_select_db($db);
- mysql_set_charset("UTF-8");
- }
- /** PUBLIC: Query the database.
- *
- * @param $query The query
- * @return The result of the Query to use with the fetchNextObject() method
- */
- public function query($query){
- $this->result = mysql_query($query);
- return $this->result;
- }
- /** PUBLIC: Fetch the next database object
- * @param $result The ressource returned by query().\n If null, the last returned query() will be used.
- * @return returns an object representing a data row
- */
- public function fetchNextObject($result = null){
- if($result == null)
- $result = $this->result;
- if($result == null || mysql_num_rows($result)<1)
- return null;
- else
- return mysql_fetch_object ($result);
- }
- /** PUBLIC: Get the number of rows in a query
- * @param $result The ressource returned by query().\n If null, the last returned query() will be used.
- */
- public function numRows($result = null){
- if($result == null)
- return mysql_num_rows ($this->result);
- else
- return mysql_num_rows ($result);
- }
- /** PUBLIC: The same as query() but only returns one unique object (automaticaly adds "LIMIT 1" to the query).
- * @param $query The query. NOTE: Do not put LIMIT 1 in the query as this is added automaticaly
- * @return Returns an object representing a data row (or null if the result is empty)
- */
- public function queryUniqueObject($query){
- $query = "$query LIMIT 1";
- $result = mysql_query($query);
- return mysql_fetch_object($result);
- }
- /** PUBLIC: The same as queryUniqueObject but only returns a unique cell
- * @param $query The query. NOTE: Do not put LIMIT 1 in the query as this is added automaticaly
- * @return Returns a value representing a data cell (or null if the result is empty)
- */
- public function queryUniqueValue($query){
- $query = "$query LIMIT 1";
- $result = mysql_query($query);
- $line = mysql_fetch_row($result);
- return $line[0];
- }
- /** PUBLIC: Counts the number of rows in a table given a condition
- *
- * @param $table The table from which to count number of rows
- * @param $where The condition to forfill before counting rows.\n NOTE: If no condition needed, use CountOfAll() in stead.
- * @return Returns the number of rows in a table given a condition.
- */
- public function countOf($table,$where){
- return $this->queryUniqueValue("SELECT COUNT(*) FROM $table WHERE $where");
- }
- /** PUBLIC: The same as countOf except it doesn't take any conditions.
- *
- * @param $table The table from thich to count the number of rows
- * @return Returns the number of rows in the given table
- */
- public function countOfAll($table){
- return $this->queryUniqueValue("SELECT COUNT(*) FROM $table");
- }
- /** PUBLIC: Gets the last inserted ID in the database (not a specific table)
- *
- * @return The id of the last inserted row in any table in the database
- */
- public function lastInsertedId(){
- return mysql_insert_id();
- }
- /** PUBLIC: for executing querys that don't need any return statement.\n Use this for actions like INSERT, UPDATE, DELETE ...
- *
- * @param $query The query - use only querys that don't return anything
- */
- public function execute($query){
- mysql_query($query);
- }
- /** PUBLIC: class destructor.\n
- * close MySql connection using mysql_close()
- */
- public function __destruct() {
- mysql_close();
- }
- }
- ?>
Ovenstående klasse kopierer vi ind i en fil vi kalder
db.class.phpSom sagt vil jeg ikke berøre denne nærmere lige nu - brugen af den kommer vi til senere.
Opsætning
For ikke at skulle indtaste vores information om databasen mange forskellige steder på siden, laver vi også lige en konfigurationsfil.
Denne fil egentligt blot indeholde login-information til databasen:
- <?php
-
- define("DB_USER","my_user");
- define("DB_PASSWORD","my_password");
- define("DB_HOST","my_host");
- define("DB_NAME","my_database_name");
-
- ?>
Ovenstående konfiguration ligger vi en "config.php" fil.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (4)
Du mangler at afslutte index.html
Michael:
Nu er artiklen ikke en begynder-artikel, så går ud fra at folk godt ved hvordan et simpelt html-dokument skal startes og sluttes :-)
Super god artikel på trods af alderen på den
Et forslag kunne være at lave en opfølgning, hvor du går mere i dybden med nogle af de emner, hvor du skraber overfladen.
Du skal være
logget ind for at skrive en kommentar.