Kamelot Blog

Aller au contenu | Aller au menu | Aller à la recherche

mercredi 8 septembre 2010

mer
08
sep '10

Forum PHP Paris 2010 : 15 ans de PHP et des 10 ans de l'Afup.

Forum PHP Paris 2010 organisé par l'AFUP avec les meilleurs experts PHP français et internationaux

Le Forum PHP 2010 est officiellement annoncé pour les 09 et 10 novembre 2010 à la Cité des Sciences de Paris la Villette (France).

C'est le seul évènement professionnel en France consacré à la plate-forme PHP et aux technologies Web. Il rassemble les différents acteurs de la profession et valorise le dynamisme français en terme de technologies de pointe sur Internet.

Il sera placé sous le signe des 15 ans de PHP et des 10 ans de l'Afup.

mardi 7 septembre 2010

mar
07
sep '10

Colonnes Virtuelles pour MariaDb

Un petit post pour dire que dans la 5.2 de MariaDB on aura droit a des colonnes virtuelles

Fonctionnalité disponible dans oracle depuis sa version 11 et inexistante chez Mysql.

[sql]
 create table table1 (
    a int not null,
    b varchar(32),
    c int as (a mod 10) virtual,
    d varchar(5) as (left(b,5)) persistent);

Les colonnes C et D sont virtuelles, et ne représentent que des calculs (à la volée pour C à l'insertion pour D).

Les PERSISTENT peuvent même être utilisées pour des index (pas primary)

samedi 4 septembre 2010

sam
04
sep '10

Sphinx : j'en dit un peu plus sur ce moteur de recherche

Je parlais il y a 2 jours de sphinx en expédiant une explication en 2 secondes.

Le lendemain, je vois sur Planet Mysql que Shlomi Noach publiait un article pour remettre les pendules à l'heure sur ce qu'est sphinx

Je vais donc en dire un peu plus.

Sphinx est un moteur d'indexation/recherche open-source sous GPLv2.

On utilise indexer pour scanner ce qu'il faut indexer, cela génère des fichiers que searchd rend consultables.

Pour attaquer searchd, on a search en ligne de commande.

Mais on a aussi

  • SphinxSE: un engine mysql, il sera inclus directement dans les prochaines versions de mariaDb
  • SphinxAPI: que l'on peut utiliser en php avec un package pecl dedié mais aussi avec les apis officielles Php, Python, Java, Ruby, pur C, fournies avec sphinx, ou bien encore Riddle pour Ruby, Sphinx::Search pour perl, C++ Sphinx client, Haskell Sphinx client, C# .NET client, ...
  • SphinxQL: une syntaxe sql adaptée

Recherche

Pour la recherche elle même on a les syntaxes avancées sur le texte ...

  • et, ou , mais pas,
"hello world" @title "example program"~5 @body python -(php|perl) @* code
  • les quorum (je donne 7 mots et je veux qu'il y en aie au moins 4 dans chaque résultats)
  • la pertinence (ce mot là a plus de poids dans le titre, celui ci partout, ... )
  • la distance dans le texte : ces 2 mots là doivent être séparés par moins de n mots
  • Des remplacements
    • de caractères pour les problèmes de charset
    • les remplacements magiques (si je cherche email, je trouve aussi les contenus avec le mot courriel) sur base de vos listes (voir exemple en bas)
    • Morphologie linguistique, stemming (gestion des pluriels),
    • listes de mots interdits
    • listes de dictionnaires personnels pour la correction magique
  • ...

.. Les critères de filtre et tri annexe

  • groupes (avec decompte par groupe)
  • temporels
  • géographiques
  • ...

J'en passe bien sur.

Le service searchd est consultable via réseau (donc si vous utilisez SphinxSE il n'est pas embarqué dans la DB il peut/ils peuvent être ailleurs) avec ssl et tout le brol.

Indexation

La première chose à distinguer c'est qu'il n'est pas limité à mysql ni même à des bases de données. On peut indexer tout ce qui peut être parsé, moyennant une conversion vers un fichier xml.

On peut indexer des sources hétérogènes les mélanger comme on peut indexer partiellement une source monolithique.

On peut indexer "sur le coté" pendant que l'index précédent reste actif et swapper à la fin (très difficile à faire : il faut ajouter un --rotate)

On peut indexer par petit morceaux et exploiter les partitions ou les merger

On peut répartir les indexs sur plusieurs serveurs

Brefs il y a moyen de distribuer la recherche et l'indexation.

Il y a des techniques de RealTime indexing mais c'est dans la 1.10-beta

Lire la suite...

vendredi 3 septembre 2010

ven
03
sep '10

Chuck Norris et l'éléphpant

Après E_Chuck_Norris, le package Chuck Norris pour Drupal.

On a de l'humour dans la communauté PHP.

mercredi 1 septembre 2010

mer
01
sep '10

Nombre de résultats d'une recherche SphinxSe

Logo Sphinx Sphinx est un moteur de recherche full-text

On peut l'interroger au travers de son api, SphinxQL, en ligne de commande ou avec l'engine MySql SphinxSE

J'utilise MySqlSE;

SELECT * from INFORMATION_SCHEMA.ENGINES;

ENGINE SUPPORT COMMENT                     TRANSACTIONS  XA      SAVEPOINTS
------ ------- --------------------------- ------------  ------  ----------
...
SPHINX YES     Sphinx storage engine 0.9.9 NO            NO      NO        

La question du jour était : Y a-t-il un moyen de connaître le nombre total de résultats quand on utilise un limit ?

En Mysql simple, il y a SQL_CALC_FOUND_ROWS

mysql> SELECT SQL_CALC_FOUND_ROWS * 
    -> FROM tbl_name
    -> WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();

Le second SELECT retourne un nombre indiquant combien de lignes le premier SELECT aurait retourné s'il n'avait pas été écrit avec une clause LIMIT.

Mais avec avec SPHINX

En testant sur ma table tbl_name_sphinx qui contient 2410 rows.

select SQL_CALC_FOUND_ROWS * from tbl_name_sphinx WHERE query='' LIMIT 10;
SELECT FOUND_ROWS();
Résultat
FOUND_ROWS()
------------
          20

20 parce que c'est la valeur par défaut du limit de sphinx

# limit - amount of matches to retrieve from result set, default is 20; (ref)

En effet si je force ce limit à 10

select SQL_CALC_FOUND_ROWS *
 from tbl_name_sphinx 
 WHERE query=';limit=10';

SELECT FOUND_ROWS();
Résultat

FOUND_ROWS() -> 10

Pourquoi ? parce que c'est sphinx qui fait la vraie recherche et remonte son résultat à MySql

Donc quand je fait

select SQL_CALC_FOUND_ROWS * 
 from tbl_name_sphinx 
 WHERE query=';limit=1000' 
 LIMIT 10;

Je reçois 10 résultats sur 2410 réels et sur les 1000 que sphinx a remonté

Donc

SELECT FOUND_ROWS(); -> affiche 1000 et pas 2410.

Donc je vais monter mon limit à 1000000.

Gloups, je viens de demander à Sphinx de me préparer en résultat de 100K rows, tout renvoyer à mysql dans une table temporaire qui me retournera uniquement les 10 premiers.... Fameux gaspillage

Quand on sait que sphinx ne me retourne que les id et que donc il faut faire un join avec la table de données, ca fait mal.

la solution

SHOW ENGINE SPHINX STATUS;

On oublie le 'SQL_CALC_FOUND_ROWS'

Et on remplace FOUND_ROWS() par SHOW ENGINE SPHINX STATUS;

On remet le limit 10 au niveau de sphinx;

select  * 
 from tbl_name_sphinx 
 WHERE query=';limit=10';

SHOW ENGINE SPHINX STATUS;

Type    Name    Status                                           
------  ------  -------------------------------------------------
SPHINX  stats   total: 1000, total found: 2410, time: 0, words: 0

Bingo j'ai mon info, planquée dans une "chaine" mais je l'ai.

re bingo

 SHOW STATUS LIKE 'sphinx_%';

Mais je préfère INFORMATION_SCHEMA.

SELECT *
 from information_schema.GLOBAL_STATUS
 WHERE VARIABLE_NAME like 'SPHINX%';
VARIABLE_NAME       VARIABLE_VALUE
------------------  --------------
SPHINX_ERROR        208409        
SPHINX_TIME         0             
SPHINX_TOTAL        1000          
SPHINX_TOTAL_FOUND  2410          
SPHINX_WORD_COUNT   0             
SPHINX_WORDS                      

Et je suis un heureux.

Si vous êtes intéressés par Sphinx, voici un bon article pour l'installer.

Si vous vous êtes déjà intéressé à Zend_Search_Lucene, (bien décrit ici) il me semble avoir que celui-ci peut utiliser Sphinx comme backend. je corrigerai si je retrouve la source.

jeudi 19 août 2010

jeu
19
aoû '10

Clipart dans openOffice

J'avais besoin d'une petite illustration pour un texte que j'écris avec openOffice.

Alors j'ai cheché à ajouter des clipart.

Voici ce que j'ai trouvé.

Sur le site des extentions

mercredi 18 août 2010

mer
18
aoû '10

Pop Corn

Cette page est incomplète merci de m'aider à la compléter. Voici mes sources :

1969

1972

First Moog Quartet Popcorn

Jean-Michel Jarre

la vraie

Hot Butter Popcorn

Fresh Cream

infos - mp3

Anarchic System

version chantée

Les paroles - mp3 (vocal)

version instrumentale

mp3

1992

Aphex Twin

Caustic Window - Pop Corn Joyrex J4 EP Rephlex Records mp3

1987

M & H Band

Souvent attribuée à Jean-Michel Jarre. à tort ? à raison ? Reste à vérifier. En fait c'est le sont légèrement vocal du départ qui rappelle le style Zoolook, mais qui rappelle aussi le style Kraftwerk. Si vous en savez plus ... Commentez

1988

T.I.C

1998

Michel Simon

2002

Monroes 2002 DJ Pete Daley

2003

Pengo/Desert Planet

Marsheaux - Popcorn

2006

Medieval Version

2008

Marsheaux - Pop Corn (live in Athens - A.D.W. - 18/10/2008)

Decus - Glitch Mix

2009

MirK.O Tears progressive house rmx

Trance Claschen - Popcorn 2009 (Tronix DJ Remix)

2010

Muppet Version

By DJ MAchin brol

Dj Pixel

Koruption

eskimo vs dynamic - the popcorn trinitix remix mycel

DJ Porifet

Crazy Frog

KlubFiller

The Rezidents

Prodigy Popcorn Techno Dance 99 Remix 1

Gabry Ponte

HardTrance

Eskimo

Rock ?

Muse

Emission Taratata

Guitare maltraitée

Guitare flangée

ordi & consoles

Nintendo DS

Zx Spectrum

Funny version ... qui a parfois du mal :)

Commodore 64

GMC

à Classer

"The Electro Funk" by the Space Penguins

(et non J-M Jarre comme l'affiche la vidéo).

Shadmehr aghili

Surprenante version iranienne. En savoir plus

dimanche 15 août 2010

dim
15
aoû '10

PHP TestFest 2010 à Lille le 21 août 2010

La TestFest 2010 française aura lieu le samedi 21 août 2010 à partir de 13 h 30dans les locaux de la société No Parking, située sur le site de l'Euratechnologies au 165 avenue de Bretagne à Lille, dans le bâtiment Leblanc au troisième étage.

C'est gratuit, allez y avec votre ordinateur portable.

samedi 14 août 2010

sam
14
aoû '10

Recherche sur un champs indexé, qui n'utilise pas l'index

Petite anti-astuce :Utiliser des fonctions dans les conditions sur un champs indexé, annule l'utilisation de l'index

mysql> EXPLAIN SELECT * FROM film WHERE title LIKE 'Tr%'\\G 
*************************** 1. row *************************** 
id: 1 
select_type: SIMPLE 
table: film 
type: range 
possible_keys: idx_title 
key: idx_title 
key_len: 767 
ref: NULL 
rows: 15 
Extra: Using where

Une stratégie d'accès rapide à un range est choisi par l'optimiseur, et l'index sur le titre est utilisé pour réduire la quantité d'enregistrements à examiner (ici 15)

mysql> EXPLAIN SELECT * FROM film WHERE LEFT(title,2) = 'Tr' \\G 
*************************** 1. row *************************** 
id: 1 
select_type: SIMPLE 
table: film type: ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 951 
Extra: Using where

Une analyse complète des enregistrement, donc lente, (c'est la stratégie d'accès ALL) est utilisée car une fonction (LEFT) opére sur la colonne de titre dans la condition.


source Join-fu: The Art of SQL Tuning for MySQL

lundi 9 août 2010

lun
09
aoû '10

Vous avez un Wiki intéressant ? référencez le.

http://wikiindex.org/ est un projet d'annuaire des wikis

Vous pouvez y ajouter le votre

Cet annuaire est basé sur mediawiki mais il n'est pas raciste voyez la listes des moteurs connus

mardi 3 août 2010

mar
03
aoû '10

Récupération des données d'un formulaire

Voici un petit formulaire:

[php]
<form>
  <input type="radio" name="BT.123" value="actif" />
  <input type="radio" name="BT.123" value="inactif" />
  <input type="submit" value="Submit" />
</form>

<?php
  echo "GET: ", $_GET['BT.123'];
  echo "POST: ", $_POST['BT.123'];
  echo "REQUEST: ", $_REQUEST['BT.123'];
?>

Qu'est ce qui s'affichera si on choisi "inactif" et qu'on soumet le formulaire ?


réponse dans le 1er commentaire

jeudi 29 juillet 2010

jeu
29
juil '10

PHP-FPM (FastCGI Process Manager)

PHP-FPM est disponible dans le dernier php (5.3)... mais qu'est-ce-que c'est ?

PHP-FPM (FastCGI Process Manager) est une alternative à PHP FastCGI avec toute une série d'amélioration.

Principalement utile pour les sites à fort taux d'utilisation.

Plusieurs VHosts avec un UID/GID différent et des PHP.ini différents.

FPM permet de faire tourner plusieurs VHosts avec un UID/GID différent et des PHP.ini différents.

Support de l'upload accéléré

Statistique de base

similaire à mod_status d'apache.

Redémarrage de secours en cas de destruction accidentelle de l'opcode

Un header d'erreur

une config style

[ini]
 fastcgi.error_header = "HTTP/1.0 550 Server Made Big Boo"

... provoquera l'envoi de cette erreur au lieu d'en "200 tout va bien" avec une page blanche.

amélioration de la gestion des processus en cas de graceful stop/start

En pratique ca permet de prendre en compte une nouvelle config qui nécessite un redémarrage sans interrompre ce qui avait commencé avec l'ancienne configuration.

Journalisation des scripts lents

avec

[xml]
    <value name="request_slowlog_timeout">5s</value>
    <value name="slowlog">logs/slow.log</value>

donnera

[log]
 Sep 21 16:22:19.399162 pid 29715 (pool default)
 script_filename = /local/www/stable/www/catalogue.php 
 [0x00007fff23618120] mysql_query() /srv/stable/common/Database/class.MySQLRequest.php:20 
 [0x00007fff23618560] getResult() /srv/stable/common/Database/class.Facade.php:106 
 [0x00007fff23618aa0] query() /srv/stable/common/mysite.com/ORM/class.UsersMapper.php:99 

Journalisation de Stdout & stderr

fastcgi_finish_request()

une fonction spéciale pour clôturer la connexion avec le client, mais continuer un traitement php à découvrir en détail ici

Autres points

  • PHP-FPM est compatible avec ZendOptimizer

à lire aussi

Notes

[1] Qui, le temps de rédiger et publier cet article, a déjà été retravaillée. C'est la magie wikipedia

mercredi 28 juillet 2010

mer
28
juil '10

Utiliser Zend_Log

Allez on va essayer d'utiliser Zend_log convenablement.

L'idée c'est de découper les moments de décisions.

  1. J'écris mon code je décide de journaliser un message ou des infos
  2. Je gère mes journaux, je décide où va tel ou tel message.
  3. Je gère plusieurs staging, je change le comportement des mes dispatching
  4. Je change le format de stockage de mon journal, je décide comment disposer des informations reçues
  5. Je décide où je lis/récupère mes messages.

Julien débroussaille Zend_log dans sa Présentation du Zend Framework et une liste de tuto permet de compléter

J'écris mon code je décide de journaliser un message ou des infos

Pendant que je code ma réflexion doit se limiter à

  1. quel message envoyer
  2. quelles infos complémentaire envoyer
  3. quelle gravité/sévérité/catégoriser de message j'envoie.
<?php 
$log->info('Hello log');
?>

ajoutons une info

<?php 
$log->info('Hello log je suis à la ligne ' . __LINE__);
?>

Bon là on a envoyé le message

Je gère mes journaux, je décide où vont les messages.

Ca se passe plutôt dans le script. On prépare un objet ($log). qui sera utilisé par la suite dans le code mais on va commencer à lui dire que faire de ces messages qui remontent.

<?php 
$log = new Zend_Log();
?>

Première chose (évidente) assigner les writers (les scribes).

<?php 
$redacteur = new Zend_Log_Writer_Stream('/repository/des/ficher.log');
$log ->addWriter($redacteur);
?>

là c'est dans un un fichier mais "stream" permet aussi un accès plus large,

<?php 
$redacteur = new Zend_Log_Writer_Stream('php://output');
?>

Et on a pas que "stream", ca peut-être aussi

  • dans une base de donnée -> Zend_Log_Writer_Db,
  • dans firebug -> Zend_Log_Writer_Firebug,
  • dans un email -> Zend_Log_Writer_Mail,
  • dans un mock -> Zend_Log_Writer_Mock
  • dans syslog -> Zend_Log_Writer_Syslog
  • dans le néant ... (si le temps du développement ou de tests intensifs, vous ne voulez pas polluer vos logs, redirigez les un temps dans null -> Zend_Log_Writer_Null

//php <?php

$redacteur = new Zend_Log_Writer_Null;

?> ///

et si ca ne me plait pas je peux faire mon scribe en partant de Zend_Log_Writer_Abstract

je décide où va tel ou tel message.

Si c'est pour mettre la même chose partout ce n'est pas spécialement intéressant.

On va donc filtrer les messages à envoyer à chaque scribe. (rédacteur dans la doc)

Pour ca on a 4 outils

  • Zend_Log_Filter_Interface
  • Zend_Log_Filter_Message
  • Zend_Log_Filter_Priority
  • Zend_Log_Filter_Suppress

Je change le format de stockage de mon journal, je décide comment disposer des informations reçues

La façon dont on écrit chaque message est un format "par défaut" mais il peut être redéfini

  • Zend_Log_Formatter_Firebug
  • Zend_Log_Formatter_Interface
  • Zend_Log_Formatter_Simple
  • Zend_Log_Formatter_Xml

En utilisant cela vos pourrez

samedi 24 juillet 2010

sam
24
juil '10

Batch : Attention à la mémoire vive et au reste ...

Olivier Hoareau nous rappelle de faire attention à la mémoire vive dans les batch.

Je viens juste en remettre un couche par rapport à des petits bugs identifiés récemment dans différentes relecture de vieux code.

boucle environementée

Il ne faut pas voir un batch comme une application, mais comme un environnement à reseter à chaque itérations.

C'est à dire que la consommation de vos ressources doivent être le même en fin de chaque loop. Et il ne faut qu'un loop.

Classiquement on a lecture - traitement - écriture.

Il faut éviter le réflexe de "tout lire" -> boucler sur ce qu'on a lu -> "tout écrire"

Il faut envisager le processus "lecture - traitement - écriture." au niveau de la ligne.

Un exemple, avec un fichier CSV à transformer en tableau HTML.

Premier réflexe, on découpe traitement et affichage.

<?php
 $arrayContenuDuCsv = readCsvFile(); 
 // contient une boucle qui "lit" toutes les lignes
 
$arrayResultat = traitementDesDonnees($arrayContenuDuCsv);
 // contient une boucle effectue les traitements sur chaque ligne
 
 $stringHtml = arrayToHtmlTable($arrayResultat); 
 // contient une boucle effectue les traitements sur chaque ligne
 
 // traitement fini, j'affiche
 echo $stringHtml;

le problème c'est que

<?php
 $arrayContenuDuCsv = readCsvFile(); 
 // contient une boucle qui "lit" toutes les lignes
 
 // ici $arrayContenuDuCsv est de taille non maitrisée, dépendant de la taille du fichier
 
 $arrayResultat = traitementDesDonnees($arrayContenuDuCsv);
 // contient une boucle effectue les traitements sur chaque ligne
 
 // ici $arrayResultat est de taille non maitrisée, dépendant de la taille du fichier
 // pire, comme on a pas encore fait de "unset" de $arrayContenuDuCsv on a le csv en double en mémoire!!!!
 
 $stringHtml = arrayToHtmlTable($arrayResultat); 
 // contient une boucle qui éffectue les traitements sur chaque ligne
 
 
 //ici $stringHtml est de taille non maitrisée, dépendant de la taille du fichier
 // pire, comme on a pas encore fait de "unset" de $arrayResultat on a le csv en double, 
 // et si on a à faire a un très mauvais codeur, il n'a même pas fait de unset($arrayContenuDuCsv)
 // et on a le fichier en triple
 
 // traitement fini, j'affiche
 echo $stringHtml;

Il faut donc voir l'application au niveau du traitement de la ligne

<?php
 $arrayContenuCsv = readCsvRow(); // <- contient une boucle qui "lit" UNE ligne
 
 //ici $arrayContenuCsv est de taille maitrisée, 1 ligne
 
 $arrayResultatLigne = traitementDesDonnees($arrayContenuCsv);
 // contient un traitement identique pour chaque ligne
 
 //ici $arrayResultat est de taille maitrisée, 1 ligne
 
 $stringHtml = arrayToHtmlRowTable($arrayResultat);  //ici $stringHtml est de taille maitrisée, 1 ligne
 // traitement fini de ligne, j'affiche
 echo $stringHtml;

Bien entendu il faut mettre tout ceci dans une boucle, ajouter le header et le footer de ma table, mais ca reste du traitement unique.

Initialiser ses variables.

Voici un autre cas de mauvaise écriture que j'ai rencontré.

[php]
<?php
$arrayData = array();
$arrListedeListes = getListeDeListe();
foreach ($arrListedeListes as $arrListe )
{
     foreach ($arrListe as $ligne)
     {
           $arrayData[]=getResultatDuTraitementDeLaLigne($ligne);
     }
     $result= ecritureDesDatas($arrayData);
}

Le développeur a vu qu'en faisant cela au deuxième passage le traitement des données incluait le nouvelles mais aussi celle de la passe d'avant.

Solution appliquée par le développeur

[php]
<?php
$arrayData = array();
$arrListedeListes = getListeDeListe();
foreach ($arrListedeListes as $arrListe )
{
     $i=0; // <- il a réinitialisé son compteur
     foreach ($arrListe as $ligne)
     {
           $arrayData[$i]=getResultatDuTraitementDeLaLigne($ligne);
           $i++;
     }
     $result= ecritureDesDatas($arrayData);
}

Très mauvaise idée parce qu'en fait ce n'est qu'une version aussi erronée que la précédente mais en masquant un peu le problème.

En effet, en écrasant sans effacer la liste précédente, il se fait que dés qu'une liste était plus courte que la précédente, les lignes en surplus était reconsidérées à nouveau.

[php]
<?php
$arrListedeListes = getListeDeListe();
foreach ($arrListedeListes as $arrListe )
{
     $arrayData = array();

     foreach ($arrListe as $ligne)
     {
           $arrayData[$i]=getResultatDuTraitementDeLaLigne($ligne);
           
     }
     $result= ecritureDesDatas($arrayData);
}

Autres outils

Avec Zend_Framework il existe un outil qui permet de gérer le traitement gourmands en entrée et surtout en sortie c'est Zend_Memory.

Il va permettre de gérer des grosses entités de données en plaçant hors de la mémoire vive ce qu'on n'utilise pas.

Il place l'inutilisé dans un des backends Zend_Cache.

Pensez aussi à lire l'article d'Olivier Hoareau : attention à la mémoire vive.

mercredi 14 juillet 2010

mer
14
juil '10

Contrer les CSRF avec Zend_Form

Je n'avais pas repéré cet élément qui me semble bien pratique. l'élément hash Il permet de contrer les CSRF.

class Mon_Form_que_je_protege extends Zend_Form {
  public function init() {
    $this->setMethod('post');
    $this->addElement( 'submit'
                     , 'submit'
                     , array( 'ignore'   => true
                     , 'label'    => 'Submit'
                     ,)
                     );
    $form->addElement( 'hash'
                       , 'evite_csrf_foo'
                       , array( 'salt' => 'unique')
                       );
 
}

On demande à Zend_Form de créer une clé unique à la publication du formulaire et d'ensuite s'assurer que la clé à bien été fournie dans la soumission.

Je pourrais en raconter plus... sauf que quelqu'un l'a déjà fait

à lire aussi : doc API

Tags