jeudi, mars 28, 2024
Nom d'utilisateur : Mot de passe :
[NEWS]
Envoyé par unreal
Si vous avez un téléphone mobile qui prend des photos, vous avez peut-être déjà voulu envoyer ses photos directement sur votre site Web. Ce petit tutorial vous explique comment faire.

La galerie

Si vous choisissez d'utiliser une galerie (parce qu'il est tout à fait possible d'afficher les photos via une banale page avec les index activés), il faut utiliser une galerie qui supporte les uploads sans passer par l'interface d'admin. Zen Photo en est un bon choix.

Le script magique

Le script nécessite ripmime pour extraire les images de l'email encodé ; commencez donc par l'installer.

Après cela, vous pouvez sauvez le script suivant sur le disque, par exemple : /usr/local/bin/photoimport.sh


#!/bin/bash

COPYTO=/chemin/vers/galerie
TMPDIR=/tmp


cat > $TMPDIR/stdin.$$

if [ ! -d $TMPDIR/ripmime ]; then
        mkdir $TMPDIR/ripmime
fi


cat $TMPDIR/stdin.$$ | /usr/local/bin/ripmime --no-nameless --prefix -i - -d $TMPDIR/ripmime
rm -f $TMPDIR/stdin.$$

TIMESTAMP=`date +%Y%m%d%H%M%S`

cd $TMPDIR/ripmime

JPGCOPY=`ls *.jpg *.JPG 2>/dev/null | sed 's/ /@@@/g'`

for ONEJPG in $JPGCOPY; do

        ONEJPGSP=`echo -n $ONEJPG | sed 's/@@@/ /g'`
        ONEJPG_=`echo -n $ONEJPG | sed 's/@@@/_/g'`

        mv "$TMPDIR/ripmime/$ONEJPGSP" $COPYTO/$TIMESTAMP-$ONEJPG_ 2>/dev/null

done

chmod 755 $COPYTO/* 2>/dev/null


La configuration email

Les photos étant envoyées en pièce jointe par email, il est souhaitable de créer une adresse dédiée à la réception des photos, boitephoto@domaine.com par exemple. Toutefois il est faisable de créer un alias vers une autre boite, par exemple :

/etc/mail/aliases

boitephoto:    autrecompte


N'oubliez pas de régénérer le fichier d'alias binaire !

Dans tous les cas, nous utiliserons Procmail pour réceptionner les mails.

Editez ~/.procmailrc :

:0H
* ^TO.*boitephoto@domaine.com
|/usr/local/bin/photoimport.sh


Ces lignes permettent de piper le mail dans le script qui extrait et copie les images.

Action !

Prenez une photo et l'envoyez à l'adresse définie. Elle devrait apparaître après quelques instants dans la galerie.

Posté le 04/12/08 à 16:06 - 0 Commentaires...

[NEWS]
Envoyé par unreal
On dit souvent que MySQL est une base limitée fonctionnellement. Même si cette affirmation est juste, ce n'est pas une raison pour ne pas optimiser ses requêtes car MySQL reste une base très adaptée à l'usage pour lequel il a été conçu : stocker les données de sites Web dynamiques !

Alors, nous allons voir dans ce petit dossier comment optimiser ses requêtes en vue de faire des sites rapides qui exploitent au mieux MySQL.


1. Les préliminaires

Nous supposons que vous utilisez MySQL 4.0 au minimum. Certaines features ne sont pas disponibles dans les version précédentes.

Ensuite, soient t1 et t2 deux tables MySQL :

t1
----------
t1_id int(10)
t1_c1 varchar(20)
t1_c2 varchar(20)

t2
----------
t2_id int(10)
t2_refid int(10)
t2_c1 tinyint(1)


Règle d'or : bien réflechir à l'organisation de la base avant de commencer à développer. Ce n'est pas utile d'employer des varchar (200) si des (10) suffisent ! Evitez de fragmenter l'information en utilisant trop de tables, de dupliquer les mêmes informations dans plusieurs tables.


2. SELECT * : à éviter !

On le voit tout le temps, mais quand on n'a pas besoin de tous les champs, "select *" est à proscrire car il utilise du temps CPU et de la mémoire en plus pour rien.

L'exemple suivant ne renvoie que les champs t1_c1 et t1_c2 :

SELECT t1_c1, t1_c2 FROM t1 WHERE t1_id = 20



3. Utilisation de LIMIT

Quand la requête va renvoyer plusieurs résultats il est important de limiter le nombre d'éléments avec LIMIT. Supposons que t1 contienne 100 000 lignes et qu'on fasse :

SELECT t1_c1, t1_c2 FROM t1


Alors, MySQL va retourner 100 000 lignes que php (en supposant que le code soit en php) va essayer d'enregistrer dans un array ! Il y'a de fortes chances que cela prenne très longtemps ou que php arrête l'exécution si la mémoire nécessaire dépasse la valeur fixée par l'administrateur. Alors voilà comment faire :

SELECT t1_c1, t1_c2 FROM t1 LIMIT 0, 10


Cette requête n'enverra que 10 lignes, quelque soit le nombre total d'éléments dans la table.


4. Utilisation d'ORDER BY

La syntaxe habituelle est la suivante :

SELECT t1_c1, t1_c2 FROM t1 ORDER BY t1_id ASC LIMIT 0, 10


Le problème est qu'il effectue le classement avant de limiter le nombre de résultats avec LIMIT. Du coup, selon l'ordre ASC ou DESC, la base ne renvoie pas les mêmes résultats (en fait, elle va renvoyer 10 résultats en partant du haut ou du bas de la table selon l'ordre choisi). Evidemment, quand on souhaite afficher les mêmes résultats, avec seulement l'ordre qui change, il faut chercher ailleurs.

Plusieurs solutions existent (selon la version de MySQL) :

4.1. Solution avec MySQL 4.0 (ne fonctionne pas avec MySQL 4.1)

(SELECT t1_c1, t1_c2 FROM t1 LIMIT 0, 10) ORDER BY t1_id ASC


Les connaisseurs reconnaîtront une 1/2 d'UNION qui n'est pas officiellement supportée mais qui marche parfaitement avec MySQL 4.0. L'avantage de cette méthode est que la requête reste très rapide.

4.2. Solution avec MySQL 4.1 (ne fonctionne pas avec MySQL 4.0)

C'est la méthode des subqueries qui n'est présente qu'à partir de MySQL 4.1 :

SELECT * FROM (SELECT t1_c1, t1_c2 FROM t1 LIMIT 0, 10) AS tbl ORDER BY t1_id ASC


Avant d'utiliser les subqueries je vous conseille de vous assurer que vous n'aurez pas à garantir la compatibilité descendante. wink.gif

4.3. Solution avec les UNION (fonctionne avec MySQL 4.0 et 4.1)

(SELECT t1_c1, t1_c2 FROM t1 LIMIT 0, 10) UNION (SELECT t1_c1, t1_c2 FROM t1 LIMIT 0, 10) ORDER BY t1_id ASC


Inconvénient : l'UNION complète est un lente.


5. Les jointures

Introduisons maintenant la table t2. La table t2 contient des références sur la table t1 ; on souhaite réaliser une requête sur t2 pour récupérer la référence qui permettra de retrouver l'information souhaitée sur t1.

Il existe bien sûr la bonne et la mauvaise façon de procéder.

5.1. La boucle while : à éviter !!!

C'est probablement ce qu'on peut faire de pire en SQL.

SELECT t2_refid FROM t2 WHERE t2_id = 5 LIMIT 100


Ensuite, pour chaque valeur de t2_refid (jusqu'à 100 valeurs dans cet exemple), on réalise une nouvelle requête :

SELECT t1_c1, t1_c2 FROM t1 WHERE t1_id = <valeur t2_refid>


On réalise donc jusqu'à 101 (1 + 100) requêtes, ce qui est carrément catastrophique en termes de performances.
De façon générale, il ne faut pas placer des requêtes à l'intérieur de boucles.

5.2. La méthode LEFT JOIN

SELECT t1_c1, t1_c2 FROM t1 LEFT JOIN t2 ON t1_id = t2_refid WHERE t2_id = 5 LIMIT 100


On obtient exactement le même résultat que l'exemple précédent... avec une seule requête. Gain de performance considérable.

5.3. La méthode INNER JOIN

Cette méthode donne sensiblement le même résultat que la méthode précédente. Il semblerait que ce soit plus rapide sur des grosses tables, mais avec ma base MySQL, les temps de réponse sont identiques.

SELECT t1_c1, t1_c2 FROM t1, t2 WHERE t1_id = t2_refid AND t2_id = 5 LIMIT 100



6. Les fonctions MySQL

Voici quelques exemples d'utilisation des fonctions MySQL.

6.1. Count

SELECT count(t1_id) as total FROM t1


6.2. Rand

SELECT t1_c1, t1_c2 FROM t1 ORDER BY rand() LIMIT 10



7. Conclusion

Avec un peu de chance, ce petit guide vous aura servi pour optimiser vos requêtes SQL.

N'oubliez pas de consulter la documentation officielle pour la syntaxe exacte des requêtes et pour lire les commentaires.

Have fun. wink.gif

Posté le 01/06/05 à 04:56 - 1 Commentaires...

[NEWS]
Envoyé par unreal
Les expressions régulières ou "RegEx" permettent de localiser (et remplacer) des séquences contenant des valeurs inconnues, mais qui suivent une certaine logique.

Pour bien situer l'utilité, voici un problème qui pourrait être résolu grâce à des RegEx : vous avez une chaîne contenant une date au format US (YYYYMMDD) que vous voulez afficher au format européen (DD/MM/YYYY).


Les fonctions

Les 2 fonctions que vous allez le plus souvent utiliser sont ereg_replace (detection et remplacement des regex) et ereg (detection seulement).

Pour la syntaxe des fonctions, tout est expliqué en détail sur le site du php.


Les caractères spéciaux

Ci-dessous la liste des caractères spéciaux et leurs rôles :

  • . : n'importe quel caractère
  • ^ : début de chaîne
  • $ : fin de chaîne
  • * : >=0 occurrences des caractères
  • + : >0 occurrences des caractères
  • ? : 0 ou 1 occurrences des caractères
  • (...) : séquence de caractères
  • [...] : caractères à apparaître dans une séquence de caractères
  • {x} ou {x,y} : nombre d'occurrences de caractères
  • | : fonction logique "ou"
  • \ : caractère "escape", permet d'utiliser un caractère spécial littéralement



Reprenons l'exemple donné en introduction

Il s'agit de détecter des groupes de chiffres allant de 0 à 9, soit [0-9]. Il peut avoir 2 ou 4 chiffres dans chaque groupe, soit [0-9]{2} ou [0-9]{4}.

Donc [0-9]{4}[0-9]{2}[0-9]{2} permettrait de détecter la date.

Mais nous avons besoin de récupérer les séquences de chiffres de chaque groupe pour inverser l'ordre, soit ([0-9]{4})([0-9]{2})([0-9]{2}).

A partir de là prenons 2 cas de figure :

1/ La date est en fin de chaîne, après une partie connue, par exemple "date20050531". On pourrait donc détecter de cette manière :

"date([0-9]{4})([0-9]{2})([0-9]{2})$" <-- le $ indique la fin de chaîne

2/ La date a des lettres de chaque côté, par exemple "blabla20050531abc". Il faudrait alors procéder de cette manière :

".*([0-9]{4})([0-9]{2})([0-9]{2}).*" <-- les .* matchent n'importe quels caractères

Pour le remplacement, utilisons la fonction ereg_replace :

<?php
$str = 'blabla20050531abc';
$str = ereg_replace('.*([0-9]{4})([0-9]{2})([0-9]{2}).*', '\\3/\\2/\\1', $str);
echo ($str);
?>


Note : les \\1, \\2 et \\3 contiennent les séquences reconnues.


Conclusion

Il est important de ne pas abuser des RegEx qui sont puissantes mais lourdes en temps processeur. Quand vous n'avez besoin que de remplacer des chaînes connues, il convient d'utiliser la fonction str-replace qui est carrément plus rapide.

Voilà, je mettrai en ligne d'autres guides quand je les aurai fait. wink.gif

Posté le 01/06/05 à 02:23 - 1 Commentaires...