Catégorie : Développement

PostgreSQL : Utiliser ON CONFLICT et RETURNING

Dans le cadre de l'utilisation d'une query postgre INSERT ON CONFLICT vous avez peut-être tenté d'utiliser RETURNING afin de par exemple retourner l'id original de l'élément qui créer le conflict.

Prenons la table "customers" suivante :

id	name	email	        date
1	Maxime	maxime@test.fr	2022/08/11
2	Goodie	goodie@test.fr	2022/08/11

Nous avons évidement une contrainte unique sur l'email customers. Si l'on souhaite jouer cette requête nous allons avoir une erreur :

INSERT INTO customers (email) VALUES ('maxime@test.fr');
ERROR:  duplicate KEY value violates UNIQUE constraint "customers_email_key"
DETAIL:  KEY (email)=(maxime@test.fr) already EXISTS.

Nous utilisons donc la clause "ON CONFLICT" pour éviter d'avoir cette erreur et souhaitons retourner l'id du customer.

Notre première id serait d'utiliser cette requête :

INSERT INTO customers (email) VALUES ('maxime@test.fr') ON CONFLICT (email) DO NOTHING RETURNING id;
 id 
----
(0 rows)

Seulement comme vous le voyez nous n'avons aucun résultat.

La solution : il faut bien utiliser un DO UPDATE SET en n'effectuant aucune modification pour avoir nos résultats.

INSERT INTO customers (email) VALUES ('maxime@test.fr') ON CONFLICT (username) DO UPDATE SET email=EXCLUDED.email RETURNING id;
 id 
----
   1
(1 row)

Vous noterez l'utilisation de EXCLUDED qui est la valeur originale de l'insert, donc pas de modification et nos récupérons bien notre id smile

Récupérer le discriminator lors de l'utilisation d'un groupe avec JMS Serializer

Il existe actuellement un cas particulier avec JMS Serializer : si vous souhaitez récupérer vos attributs en spécifiant un groupe, vous perdrez le discriminator.

http://www.maraumax.fr/medias/Billets/jms-discriminator.png
Pour palier à ce problème vous devez ajouter le groupe Default en plus de vos / votre groupe(s). Notez que les attributs sans groupe se retrouvent automatiquement dans Default, vous pouvez dans ce cas leurs attribuer un groupe vide.

Merci à Micael pour le bug et la capture smile

Source : Github

Prestahop : import d'images sur un hébergement mutualisé OVH

http://www.maraumax.fr/medias/Billets/prestashop_web_design.pngAprès avoir passé de nombreuses minutes heures sur l'import prestashop et en consultant les différents forums j'ai faillit désespérer ! Mais finalement en allant voir un peu le code source et à coup de var_dump j'ai compris l'origine de mon soucis d'import. Enfin...

A chaque import j'avais l'erreur suivante :

Erreur lors de la copie de l'image: ../import/toto.jpg

Avant toute chose je suis sur la version 1.6 de prestahop donc faites attention à la votre car le problème est peut-être différent. Pensez lors de vos tentatives d'import à avoir qu'un seul produit et image dans votre CSV dans un premier temps afin de gagnez en vitesse wink Surtout quand vous effectuez une bonne dizaine voir centaine de tentatives.

En regardant dans le fichier classes/Tools.php avec la fonction static copy() je me suis rendu compte que Prestashop ajoutait un slash en début de chaine source si il n'y en avait pas. Si bien que mes dossiers relatifs n'étaient pas correcte. Par exemple ../images/toto.jpg était transformé en /../images/toto.jpg et forcément ça fonctionne moins bien...

J'en suis arrivé à la conclusion suivante : il faut partir de la racine de l'hébergement. Ainsi chez OVH pour obtenir le chemin complet, voici la structure à respecter :

/home/prestashop/www/imgs/toto.jpg
prestashop = votre login FTP OVH
imgs = un dossier crée à la racine du répertoire FTP

Il vous suffit ensuite de reprendre ce chemin complet dans votre fichier d'import et vos images fonctionnerons parfaitement !

Merci a la communauté prestashop pour leurs différentes pistes.

Utiliser Font Awesome avec Assetic sous Symfony2

Je me suis récement mis à développer avec Symfony2 qui utilise Assetic pour gérer les ressources. J'ai un peu galéré pour mettre en place Font-Awesome dans mon projet à cause d'un bug d'Assetic en dev qui ne génère pas correctement l'url des fichiers importés. Concrètement lors de l'utilisation d'un @import css dans votre projet, le système de ré-écriture permettant de "fixer" les urls ne fonctionne pas.

Après quelques recherches je suis tombé sur le bundle https://github.com/fkrauthan/FkrCssURLRewriteBundle qui est censé corriger ce bug mais ça n'a rien changé chez moi... J'ai fini par utiliser un CDN !

Mais je suis finalement tombé sur une solution toute simple qui consiste à utiliser l'option output de Assetic pour générer les urls que l'on souhaite à savoir "fonts/*.ext"

Il suffit juste de rajouter les quelques lignes suivantes dans le assets de Assetic :

        font-awesome-otf:
            inputs: '%kernel.root_dir%/../vendor/fortawesome/font-awesome/fonts/FontAwesome.otf'
            output: 'fonts/FontAwesome.otf'
        font-awesome-eot:
            inputs: '%kernel.root_dir%/../vendor/fortawesome/font-awesome/fonts/fontawesome-webfont.eot'
            output: 'fonts/fontawesome-webfont.eot'
        font-awesome-svg:
            inputs: '%kernel.root_dir%/../vendor/fortawesome/font-awesome/fonts/fontawesome-webfont.svg'
            output: 'fonts/fontawesome-webfont.svg'
        font-awesome-ttf:
            inputs: '%kernel.root_dir%/../vendor/fortawesome/font-awesome/fonts/fontawesome-webfont.ttf'
            output: 'fonts/fontawesome-webfont.ttf'
        font-awesome-woff:
            inputs: '%kernel.root_dir%/../vendor/fortawesome/font-awesome/fonts/fontawesome-webfont.woff'
            output: 'fonts/fontawesome-webfont.woff'

Les ressources sont désormais disponibles via le chemin défini dans output et ça fonctionne enfin correctement !

Source

Mettre à jour un dépôt SVN avec un tag / une branche

Depuis peu je me suis mis à créer des tags svn pour les différentes versions d'un site internet. C'est très pratique et ça permet de revenir facilement en arrière et / ou d'apporter une modification précise à une version sans avoir à créer des patchs.

Après avoir crée une branche dans le répertoire tags de votre svn, il vous suffit d'exécuter la commande suivante :
svn switch http://svn.votre-site.fr/monprojet/tags/v1.2.3 /home/www/monprojet

Le dernière paramètre, si vous est dans le dossier du projet n'est pas obligatoire. La version de votre dépot est automatiquement mise à jour avec les bonnes révisions.

Petit point important si vous créer votre branche en utilisant la révision 150 alors que vous êtes actuellement à la révision 180 alors la révision de votre tag seras la 181. Le résultat de svn info seras donc 181. Pour obtenir la révision correspondante utilisez la commande suivante :
svn log --verbose --stop-on-copy http://svn.votre-site.fr/monprojet/tags/v1.2.3/

Le résultat seras le suivant :

Chemins modifiés :
   A /tags/v1.2.3 (de /trunk/www:150)

Pour plus de détails, n'hésitez pas à faire un tour sur la documentation de svn switch.

Créer des miniatures de vidéos à la volée

Pour un projet qui devrait voir le jour dans les prochaines semaines / mois j'ai eu besoin de réaliser un script permettant de générer des vidéos à la volée.

J'ai donc travaillé sur un script qui est assez simple au final. Pour l'utiliser vous devez disposer de ffmpeg sur votre serveur.

Pour l'installer lancez simplement la commande suivante :

apt-get update
apt-get install ffmpeg

Et voici le script, nommez la captures.sh par exemple :

#! /bin/bash
 
#--- Paramètres
 
videowaitdir=/home/www/videos/
capturedir=/home/www/videos/screens/
 
numberscreens=10
 
#--- Traitement des vidéos
 
for video in `ls $videowaitdir`; do
	if [ -f $videowaitdir$video ]; then
		duration=`ffmpeg -i $videowaitdir$video 2>&1 | grep "Duration:" | awk '{print $2}' | tr -d , | cut -d . -f 1`
 
		if [ -z "$duration" ] || [ "$duration" = "00:00:00" ]
		then
			continue
		fi
 
		h=`echo $duration | cut -d : -f 1`
		m=`echo $duration | cut -d : -f 2`
		s=`echo $duration | cut -d : -f 3`
 
		totaltime=$(($h+$m+$s))
 
		time=$(($totaltime/$numberscreens))
 
		for((i=0;i<=$numberscreens;i++))
		do
			t=$(($time*$i+$time))
 
			ffmpeg -y -i $videowaitdir$video -f mjpeg -ss $t -vframes 1 -s 640x480 -an $capturedir$video.$i.jpg
		done
	fi
done

Modifiez simplement les deux premières variables qui sont :
videowaitdir : répertoire des vidéos
capturedir : répertoire des miniatures

Vous avez aussi une variable numberscreens qui détermine le nombre de screens à faire de la vidéo.

N'oubliez pas de modifier les permissions pour exécuter le bash :
chmod +x captures.sh
Le script est assez simple à comprendre, on liste les vidéos du dossier, on utilise ffmpeg pour récupérer le temps de la vidéo et on détermine à quels moments on doit faire les screens.

N'hésitez pas si vous avez des suggestions.

Créer des onglets personnalisés sur Android

http://www.maraumax.fr/medias/Billets/tutoriels/preview-onglets.pngVous souhaitez créer des onglets personnalisés dans votre application Android ? Je viens de créer un tutoriel permettant de modifier l'aspect par défaut des onglets afin de créer des onglets plus esthétiques et moins importants en taille.

Le tutoriel est assez simple et consiste à créer une vue à partir d'un fichier xml pour chaque onglet. Dans mon exemple j'ai simplement ajouté du texte dans cette vue, mais vous pouvez évidemment ajouter "ce que vous souhaitez" mais si c'est pour mettre un texte et une image autant ne pas vous embêter et utiliser le layout de base d'Android.

Vous pouvez télécharger les sources du tutoriel à la fin, n'hésitez pas à montrer le résultat de vos modifications et pourquoi les différents fichiers XML afin de donner des exemples pour les autres visiteurs.

Créer des onglets personnalisés sur Android

Trouver une adresse à partir de coodonnées GPS en PHP

Pour ma prochaine application Android, j'ai souhaité retrouver l'adresse correspondant aux coordonnées du téléphone en php. La plupart des cas, quand on parle de cartographie il suffit de faire un tour dans les documentations du géant du web : Google.

Voici une petite fonction permettant de récupérer l'adresse correspondant à des coordonnées GPS:

function getAdresseFromCoords($lat, $lng)
{
	$content = file_get_contents('http://maps.googleapis.com/maps/api/geocode/json?latlng='.$lat.','.$lng.'&sensor=false');
 
	if(!$content)
		return false;
 
	$json = json_decode($content, true);
 
	if(!$json || $json['status'] != 'OK')
		return false;
 
	if(!isset($json['results'][0]['formatted_address']) && empty($json['results'][0]['formatted_address']))
		return false;
 
	return $json['results'][0]['formatted_address'];
}

Rien de bien compliqué, on appelle l'api google en lui envoyant nos coordonnées. Ca nous retourne un flux json avec nos informations si elles existent.

Voici un petit exemple d'utilisation :

// République, 35000 Rennes, France
if($adresse = getAdresseFromCoords('48.10968399999999', '-1.679257600000028'))
	echo $adresse;

Et voilà c'est tout simple ! N'hésitez pas à aller consulter la documentation de l'API Geocoding de Google si vous avez des interrogations !

[Android] Alterner les couleurs dans une liste

Les listview sur Android sont par défaut assez tristes. Voici un exemple vous permettant d'alterner les couleurs dans votre vue, en utilisant un adapter. Dans l'exemple j'utilise un SimpleAdapter mais vous pouvez évidement reproduire l'effet sur les BaseAdapter, ArrayAdapter et les autres wink

Voici le résultat
http://www.maraumax.fr/medias/Billets/listview-couleur-alterne.jpg

La mise en place est assez simple, vous pouvez télécharger les sources à la fin du billet si jamais vous voulez plus de détail.

Créer une nouvelle classe ListViewAdapter avec le code suivant :

import java.util.HashMap;
import java.util.List;
 
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleAdapter;
 
public class ListViewAdapter extends SimpleAdapter {
	private int color1 = 0xaaFF5F5F;
	private int color2 = 0xaa2F67FF;
 
	public ListViewAdapter(Context context, List<HashMap<String, String>> items, int resource, String[] from, int[] to) {
		super(context, items, resource, from, to);
	}
 
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
	  View view = super.getView(position, convertView, parent);
 
	  if(position % 2 == 0)
		  view.setBackgroundColor(color1);
	  else
		  view.setBackgroundColor(color2);
 
	  return view;
	}
}

Pour l'exemple j'ai mis les couleurs dans le code java, l'idéal étant de les mettrent dans un fichier colors.xml du dossier values pour par exemple changer la couleur en fonction d'un thème.

Il vous suffit ensuite de lier cette adapter à votre ListView en ajout la ligne suivante dans votre Activity :

// A ajouter dans l'Activity
list.setAdapter(new ListViewAdapter(this, listContent, R.layout.item, from, to));

Vous pouvez télécharger l'exemple complet à cette adresse et n'hésitez pas en cas de questions !

Tutoriel pour créer un widget Android

http://www.maraumax.fr/medias/Billets/android-widget-preview.jpgJ'ai récement mis en place un widget dans l'application Bonjour Android et j'ai été étonné de voir qu'il y avait peu de tutoriel complet pour créer cette fonctionnalité.

J'ai donc décidé de partager mon expérience afin de vous permettre de créer un widget de A à Z. Je n'explique les étapes de base du développement Android donc je vous conseille très forcement d'avoir installé tout le tralala (Eclipse, Avd...) et de connaitre le langage Java.

Plusieurs notions d'Android sont utilisés, libre à vous de consulter la documentation officielle qui est vraiment très bien détaillé pour avoir plus de détails. Vous avez peut-être remarqué que le widget n'est pas des plus jolis, je n'ai pas travaillé ce point mais si vous souhaitez me partager vos xml je modifirais le tutoriel avec plaisirs.

Il n'y a pas de système de commentaires à la suite de tutoriel, mais n'hésitez pas à poster sur ce billet en cas de question, remarque et pourquoi pas pour présenter votre application !

Voilà j'espère avoir tout dit, manque juste le lien pour consulter et en bas de page télécharger les sources...

Créer un widget sur Android