Nom de l’auteur/autrice :yvonh

Linux ajouter un hôte connu au fichier known_hosts

Lorsque vous vous connectez pour la première fois sur un serveur en ssh, il peut vous arriver le message suivant : « WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED ».

En fait le client ne reconnait pas le site distant, qui n’est pas dans un fichier noté known_hosts, ce dernier se trouve dans le répertoire invisible .ssh.

Pour ajouter manuellement le site distant dans ce fichier, allez d’abord dans le site distant si vous avez accès (autrement veuillez contacter l’administrateur du site distant.) et tapez la commande :

$ ssh-keyscan -t rsa server_ip
# 115.22.8.17 SSH-2.0-OpenSSH_6.7p1 Debian-5+deb8u4
115.22.8.17 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB....

Ouvrez le fichier known_hosts de votre client, et collez la chaine affichée commençant par « 115.22.8.17 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB… »

Connectez vous à présent.

 

node JS

Générer un projet Javascript avec NPM

Imaginez que vous ayez un projet front end, par exemple personnalisation d’un thème d’une boutique Magento, cela ne concerne que le CSS et HTML (voire du javascript), les fichiers sont gros, pouvant faire dix milles lignes en CSS, hors de question de le faire directement en CSS, il y a beaucoup mieux le Sass. Le Sass est un « langage » qui va se compiler en CSS, l’avantage est qu’il est facilement  compréhensible, car sa syntaxe est structurée.

/* Sass */
div > p {
  color:blue;
  a {
    color : red;
  }
}

/* converti en CSS */

div > p {
  color: blue;
}
div > p a {
  color: red;
}

L’exemple ci-dessus illustre la lisibilité de la notation en Sass, hiérachisée mais pas forcément plus concise, en revanche très lisible, la syntaxe Sass est beaucoup plus riche et plus puissante que ne le montre l’exemple ci-dessus. En comparaison, la notation CSS est plus plate et répétitive, et bien sûr moins lisible.

NPM va nous permettre d’installer les dépendances, et dans le cas du Sass, on va installer node-sass pour compiler le Sass en CSS à chaque fois qu’on enregistre le fichier Sass (extension .scss).

Initialisation d’un projet NPM

npm init

Après cette commande vous devez répondre à un tas de questions comme le nom du projet, le propriétaire, la licence, pas mal de champs sont optionnels rassurez-vous etc.

Un fichier package.json est généré.

Ensuite installons le paquet node-sass. Ce dernier permet de surveiller les modifications d’un fichier Sass et de compiler en CSS automatiquement.

$ npm install -D node-sass nodemon
#le D signifie une dev dependency

Dans votre package.json, ajoutez ces lignes

“scripts”: {
  “build-css”: “node-sass --include-path scss scss/main.scss   public/css/main.css”
}

#Pour lancer la compilation
$ npm run build-css

Mieux encore watcher pour automatiquement compiler au moindre changement puis sauvegarde du fichier sass.

“scripts”: {
 “build-css”: “node-sass --include-path scss scss/main.scss public/css/main.css”,
 “watch-css”: “nodemon -e scss -x \”npm run build-css\””
},

lien : https://medium.com/@brianhan/watch-compile-your-sass-with-npm-9ba2b878415b

bit torrent linux

Transmission un client léger bitTorrent pour Linux

 

Installation de transmission

apt-get install transmission-cli
#je suppose que vous n'avez pas d'interface graphique, on fait tout en ligne de commande.

apt-get install transmission-daemon

 

 

Configuration du fichier settings.json

Le fichier de configuration se trouve dans /var/lib/transmission-daemon/info/

N’arrêtez pas votre démon Transmission, éditez le fichier json mais ne faites pas un redémarrage, car les données vont être écrasée, à la place, faites un reload :

service transmission-daemon reload

Les sections à configurer : la vistesse en upload et download, le répertoire des téléchargements incomplets et complets.

    "rpc-authentication-required": true, // Activer l'authentification par mot de passe
    "rpc-enabled": true,                 // On active l'interface, optionnel on fera l'impasse de l'interface web qui nécessite un virtual host Apache
    "rpc-password": "Password",          // Tapez votre mot de passe en clair, il sera chiffré à l'enregistrement
    "rpc-port": 9091,                    // Port d'accès à l'interface
    "rpc-url": "/transmission/",         // Url d'accès à l'interface
    "rpc-username": "Utilisateur",       // Le nom d'utilisateur pour l'authentification

#ici modifier le rpc-username/rpc-password par transmission/transmission, pour la suite c'est ce qui est supposé

Par la suite les commande se feront avec transmission-remote.

Commandes Transmission-remote

Pour ajouter un torrent : téléchargez ou uploadez un fichier avec extension torrent, modifier le nom pour le rendre plus court, perso je download sur Windows modifie le nom et uploade vers le serveur.

transmission-remote -n 'transmission:transmission' -a lefichier.torrent
localhost:9091/transmission/rpc/ responded: "success"

La paire ‘transmission:transmission’ correspond au login/mot de passe.

Si la réponse à la commande correspond à la seconde ligne, c’est réussi, faites immédiatement la commande suivante pour connaitre l’état du téléchargement. Si vous avez une erreur du type 401 ou Unexpected response: <h1>401: Unauthorized</h1>Unauthorized User: deflate, gzip , vérifiez que vous avez bien mis le username et le mot de passe du fichier json, c’est une des causes.

pour connaitre l’état de téléchargement

transmission-remote -n 'transmission:transmission' -st

Autres commandes :

Start all torrents:

    transmission-remote -s all  << transmission-remote -n transmission:transmission -s all

Stop all torrents:

    transmission-remote -S all

Start a specific torrent:

    transmission-remote -s [hash]

Stop a specific torrent:

    transmission-remote -S [hash]

Remove all torrents (-t désigne le torrent courant,all après -t spécifie tous les torrents):

    transmission-remote -t all -r  

Remove a specific torrent:

    transmission-remote -r [hash]

Get hashes for all torrents:

    transmission-remote -i

List all torrents with status:

    transmission-remote -l

Quit the daemon:

    transmission-remote -q

source des commandes.

Dans certaines commande ci-dessus, vous voyez un argument [hash], c’est le has sha1 du torrent. Mais comment voir ce hash? C’est avec la commande transmission-show nom-du-torrent.torrent que vous allez voir le hash.

Liens : Configuration fichier json

 

 

debian

Linux SSH sélectionner une clé publique

Récemment j’ai eu un problème, je n’arrivais pas à faire en sorte de ne pas avoir à me logger à un hôte distant que je me connectais en ssh ou avec rsync.

Un utilisateur peut avoir plusieurs clés SSH

Vous pouvez pour un utilisateur plusieurs clés SSH. Le problème est donc de sélectionner la bonne clé SSH à utiliser. Le problème que j’ai eu était que j’avais généré une seconde clé SSH pour l’utilisateur root sans savoir qu’il en avait déjà une. Comme j’avais besoin d’avoir un accès sur un autre serveur sans avoir à m’authentifier (pour faire du Rsync ou du ssh par exemple).  J’ai vais déposé la clé publique que je venais de généré, mais l’authentification était quand même demandé ! Grâce à l’étude d’un service qui marchait, j’ai pu constater que a clé n’était pas la même.

Il existe un fichier de configuration pour une utilisation avancée

 

Ne regardant de nouveau dans le répertoire j’ai vu qu’il y avait deux fichiers avec l’extension .pub, donc deux clés. Il y avait aussi un fichier config (droit 644), qui est le fichier de configuration des clé. Ce fichier vous permet de spécifier quelle clé utiliser pour quel hôte.

Host myshortname realname.example.com
    HostName realname.example.com
    IdentityFile ~/.ssh/realname_rsa # la clé privée
    User remoteusername

Host myother realname2.example.org
    HostName realname2.example.org
    IdentityFile ~/.ssh/realname2_rsa
    User remoteusername

Mais on peut tout simplement avoir seulement la directive IdentityFile

IdentityFile /root/.ssh/id_ns666817

où id_ns666817 est la clé privée. C’est ce cas de figure que j’ai eu, et explique pourquoi il n’y avait qu’une clé SSH qui était opérationnelle.

Plus d’info : Question sur StackOverflow

 

 

Apache la directive AllowOverride

Surchargez vos réglages avec htaccess

Lorsqu’un site web utilise un fichier .htaccess on voit cette directive (Donc cette directive n’est pas à utiliser dans le fichier htaccess qu’on soit d’accord !). Vous allez voir que le fichier htaccess n’est rien d’autre qu’une configuration d’Apache sans redémarrage du serveur. En effet dès qu’httpd.conf est modifié il faut recharger ou redémarrer Apache pour appliquer les modifications.

Attention : AllowOverride ne peut être utilisé que dans une section <Directory>

Directives impactées par AllowOverride

AllowOverride va dire ce que le fichier htaccess peut réécrire pour surcharger les directives plus générales dans le fichier httpd.conf. Il y a cependant un  nombre limité de directives qui peuvent être surchargées. Les classes de directives sensibles à la surcharge sont :

  1. Indexes
  2. Options
  3. Limit
  4. FileInfo
  5. AuthConfig

Ainsi Indexes regroupes un ensemble de directives telles : DirectoryIndex (le plus important) mais aussi des moins connues AddIcon, AddDescription.

Pour Options : Options entre autres.

Pour Limit : Allow, Deny, Order

FileInfo :

1er groupe : directive contrôlant les types de documents : ErrorDocument (par exemple erreur 404, 401, 500. SetHandler (spécifie qui exécute les scripts php par exemple),

2eme groupe : les méta données des documents : Header, SetEnvIf (définit des variables d’environnement de façon conditionnel en PHP retrouvez les variables d’environnement dans $_SERVER, utile pour distinguer l’environnement de développement de la production)

3ème groupe : le module mod_rewrite : RewriteEngine, RewriteBase, RewriteCond, RewriteOptions, RewriteRule, ça je pense que ça vous est familier !

4ème groupe : le module mod_alias : RedirectPermanent (pour faire les 301), Redirect (Pour les 302), RedirectMatch entre autre.

5ème groupe : le module mod_actions : Action(utilisé lorsque vous exécutez les fichier php non pas avec un module apache, mais avec un script CGI comme quasiment tous les serveur Apache actuels). Action est utilisé avec AddHandler, en effet ce dernier spécifie le type de fichier, leur mime-type.

6ème groupe : le module mod_mime : AddHandler, RemoveHandler etc.

Valeurs possibles de AllowOverride : None, All et options spécifiques

AllowOverride None

Dans ce cas votre fichier htaccess sera sans effet, il ne pourra pas modifier ce qui a déjà été défini dans le fichier httpd.conf ou tout autre fichier de configuration de virtual host.

AllowOverride All

Là tout est permis, c’est à dire ce qui a été listé (les 5 points)

AllowOverride Options=Multiviews, Indexes

Si vous essayez de surcharger une directive non définie dans l’exemple ci-dessus provoquera « Internal Server Error », autant dire, ce message d’erreur ne va pas vous aider beaucoup, dans ce cas allez dans les logs d’Apache.

Au fait savez vous comment on définit le fait que c’est le fichier .htaccess qui contient les directives? C’est Grâce à une autre directive AccessFileName qui spécifie le nom du fichier qui comporte tous les réglages ! Vous pouvez donc le modifier !

Une chose à laquelle il faut prêter particulièrement attention, ce sont les valeurs par défaut des directives, suivant les versions d’Apache. Par exemple, à partir d’Apache 2.3.9, AllowOverride est à None, alors qu’avant c’était à All !!

Dépannage erreurs courantes de Apache en lien avec AllowOverride

Pourquoi AllowOverride provoque-t-il une Internal Server Error ?

Une erreur 500 Internal Server Error apparaît souvent lorsqu’une directive présente dans le fichier .htaccess n’est pas autorisée par la configuration AllowOverride. Par exemple, si AllowOverride autorise uniquement FileInfo et qu’une directive relevant d’Options est utilisée, Apache retourne une erreur sans forcément fournir beaucoup d’informations à l’utilisateur. La meilleure approche consiste à consulter le fichier error.log relatif à votre virtualhost (cf dnas le fichier de votre vhost vous le trouverez)afin d’identifier la directive fautive. Vérifiez également la syntaxe du fichier .htaccess, la présence de modules nécessaires comme mod_rewrite et la compatibilité des directives utilisées avec votre version d’Apache.

Comment savoir si Apache lit réellement mon fichier .htaccess ?

Il est parfois difficile de déterminer si Apache prend réellement en compte un fichier .htaccess. Une méthode simple consiste à ajouter volontairement une directive invalide dans le fichier. Si Apache retourne immédiatement une erreur 500 Internal Server Error, cela signifie que le fichier est bien lu. À l’inverse, si le site continue de fonctionner normalement, il est probable que le fichier soit ignoré. Vérifiez alors la valeur de la directive AllowOverride dans votre configuration Apache. Assurez-vous également que le fichier se trouve dans le bon répertoire et qu’il est correctement nommé .htaccess. Les journaux d’erreurs Apache constituent également une source précieuse d’informations pour confirmer le chargement du fichier. Le fichiet htaccess permet de donner la main à des utilisateurs n’ayant pas accès au httpd.conf originel le droit de faire quelques réglages.

RewriteEngine ou RewriteRule ne fonctionne pas

Lorsque RewriteEngine On ou une règle RewriteRule semble sans effet, il faut d’abord vérifier que le module mod_rewrite est activé sur le serveur Apache. Sous Debian ou Ubuntu, la commande a2enmod rewrite permet généralement de l’activer. Ensuite, la directive AllowOverride doit autoriser la catégorie FileInfo, car les règles de réécriture en dépendent. Vérifiez également que RewriteEngine On est présent avant les règles et que les expressions régulières utilisées sont correctes. Enfin, après toute modification de configuration Apache, n’oubliez pas de recharger ou redémarrer le serveur afin que les changements soient effectivement appliqués. Comme règle que je conseille de suivre, c’est d’y aller progressivement, en partant de quelquechose de simple , et d’incrémenter les instructions.

AllowOverride All est souvent utilisé en pratique lors du débogage pour écarter d’emblée tout problème de permission, avant d’affiner.

Point de vigilance : RewriteBase est une source fréquente d’erreur silencieuse (chemins relatifs mal résolus), surtout en sous-répertoire

Pourquoi mon fichier .htaccess ne fonctionne pas ?

Lorsqu’un fichier .htaccess semble ignoré par Apache, la cause la plus fréquente est une mauvaise configuration de la directive AllowOverride (AllowOverride définit quelles directives d’un .htaccess Apache est autorisé à prendre en compte pour le répertoire concerné) . Si celle-ci est définie à None dans le bloc Directory correspondant, Apache lit le fichier mais n’applique aucune de ses directives. Vérifiez également que le fichier est bien nommé .htaccess, qu’il se trouve dans le bon répertoire et que les permissions sont correctes. Une autre erreur fréquente consiste à modifier le mauvais VirtualHost. En cas de doute, consultez les journaux d’erreurs Apache qui indiquent généralement pourquoi le fichier .htaccess n’est pas pris en compte.

Le module mod_rewrite doit être activé (a2enmod rewrite) si le .htaccess contient des règles de réécriture.

La directive AllowOverride doit se trouver dans le bon bloc <Directory> — celui qui correspond au chemin physique réel du fichier, pas forcément le VirtualHost.

debian

SecurityException in Application.cpp:511: Unknown Interpreter Configuration de SuPHP 0.7 attention les guillemets !

Configuration de SuPHP 0.7 attention les guillemets !

 

J’ai reçu ce message dans les logs erreur d’apache du virtualhost concerné:

SecurityException in Application.cpp:511: Unknown Interpreter: php

D’après ce que j’ai lu, dans la version 0.7 de SuPHP il faut mettre les guillemets dans certaines directives:

[handlers]
;Handler for php-scripts
x-httpd-php="php:/usr/bin/php-cgi"

;Handler for CGI-scripts
x-suphp-cgi="execute:!self"

Car dans les versions précédentes (et pas mal de tuto sur le web, c’est affiché sans les guillemets.

 

https://blog.yacoubi.fr/?post/2009/10/16/suPHP-0.7.1-SecurityException-in-Application.cpp_511

image magick

Comment Installer la bibliothèque ImageMagick pour WAMP 3

Je mets la méthode là qui marche car je me suis pas mal emmerdé pour l’installer.

ImageMagick c’est quoi?

C’est un bibliothèque de fonction pour manipuler les images, en gros tout ce que vous pouvez faire avec Photoshop, vous pouvez le faire avec ImageMagick. Cette bibliothèque est écrite en C/C++, elle est très répandue et vous la trouverez sur toutes les plateformes Windows, Linux et Mac.

Elle est aussi disponible dans tous les langages majeurs, dont le PHP. Elle est installable dans un environnement de production comme en développement. Pour la majorité d’entre nous, pour la production c’est souvent un serveur Linux, et pour le développement c’est en majorité un PC sous Windows.

Et comme solution de développement, sur Windows j’utilise WAMP. Télécharger sur Sourceforge gratuitement.

Pour cerner encore plus le cas de figure que je vais traiter, c’est sous PHP 5.6 et 7, mais il reste encore à vérifier deux choses : votre installation WAMP est elle en 32 ou 64 bits? et est elle installée en Thread Safe ou Non Thread Safe?

Pour le Thread Safe ou non, reportez vous au lien, pour ce qui est du 32 ou 64 bits, rien de spécial à savoir sur la technologie, mais vous devez savoir si votre installation WAMP est en 64 ou 32 bits.

Comment Installer Imagemagick, les fichiers binaires

Ce sont les fichiers qui vont vraiment faire les manipulation des images, la bibliothèque Php va faire appel à eux. Il consiste en un fichier .exe à télécharger sur ce site.

Cliquez pour installer sur votre ordinateur, et allez voir les variables d’environnement (dans Windows tapez touche « WINDOWS » à côté de la touche controle, et « PATH »pour voir où c’est installé). Si PATH contient le chemin de ImgeMagick, normalement WAMP doit les voir.

Après l’installation de ImageMagick pour Windows, ouvrez une console DOS, tapez convert -version, vous avez normalement un message sur la version de convert. Cette manipulation sert à vérifier que c’est bien installé.

Installer la bibliothèque PHP qui va faire appel à ces exécutables

Télécharger  sur le site officiel, c’est là où il va falloir savoir si c’est en 32 ou 64 bits, et surtout si c’est en Thread Safe ou non en Thread Safe (voir le lien précédent pour le savoir)

Dézippez et copier le fichier vers le répertoire c:/wamp64/bin/php/ext et modifier votre fichier php.ini en ajoutant ces deux lignes :

[Imagick]
extension=php_imagick.dll

Redémarrez WAMP. Faites un phpinfo() et vous devriez voir cette portion d’information :

Si vous voyez ça bingo ! A noter que le menu de WAMP ci dessous ne l’affiche pas, ce n’est pas grave, ce qui compte c’est le phpinfo().

image magick

Je vous le dis car j’ai perdu des heures en essayant de me baser dessus !

Autre tuto plus ancien

Supplément :

Pour connaitre en ligne de commande la liste des modules chargés

$ php -m
Note : vous ne verrez pas Imagemagick

Utilisation de ImageMagick dans vos scripts PHP

Installer correctement la DLL pour en configurant dans le php.ini est u vrai challenge (je n’ai pas réussi pour ma configuration), cependant, pas de panique vous pouvez très bien utiliser dans vos scripts php  (après avoir redémarré votre ordinateur), en utilisant la fonction exec(), qui exécute les commande shell.

Exemple pour exécuter une conversion d’image d’un format à un autre :

exec('convert   image.gif  -negate  output.gif');

 

 

dropbox

Utiliser Dropbox sur votre serveur dédié et sauvegarder vos dump

Sauvegardez vos archives serveur dédié dans Dropbox

 

Dropbox est une sauvegarde sur le cloud qui peut s’avérer économique et très fiables pour vos dumps de base de données.

J’ai une formule pour 1 Téra que je n’utilise pas entièrement (et ce pour 99€/an), donc si je pouvais créer un répertoire pour sauvegarder les archives serveur ce serait bien, mais à ces conditions suivantes :

-je ne dois pas voir ces sauvegardes sur mon ordinateur personnel

-Dropbox ne doit sauvegarder que les dumps sur le serveur dédié

On va voir comment on va créer un répertoire que j’appelle SAVDEDIE que je crée dans le répertoire /root, y mettre toutes les sauvegardes de base de données, et ne pas les voir sur mon ordinateur personnel.

Installer Dropbox sur le serveur dédié sous Linux

On va utiliser wget, il y a deux versions, la 32 et la 64bit, à vous de voir quelle est votre distribution Linux. Vous allez installer Dropbox dans votre répertoire /root, l’utilisateur root normalement n’a pas de quota, si c’est le cas, veuillez à lui donner un quota infini dans votre panel de gestion de dédié (pour mois c’est Webmin).

Ouvrez une session ssh avec Putty. Copiez ces commandes dans le presse papier et allez dans Putty puis clic droit de la souris, cela va coller la commande.

wget -O dropbox.tar.gz "http://www.dropbox.com/download/?plat=lnx.x86_64"

ou

wget -O dropbox.tar.gz "http://www.dropbox.com/download/?plat=lnx.x86"


puis faites la décompression

tar -xvzf dropbox.tar.gz

Démarrez le démon Dropbox

~/.dropbox-dist/dropboxd

Le caractère tilde ~ signifie aller au répertoire home de l’utilisateur courant, dans notre cas, on est en root (c’est obligatoire pour installer Dropbox), donc on va au répertoire /root.

Après avoir lancé le démon, vous allez avoir un message qui tourne en boucle régulièrement

This client is not linked to any account... Please visit https://www.dropbox.com/cli_link?host_id=7d44a557aa58f285f2da0x67334d02c1 to link this machine.

Activer le compte en copiant un lien sur votre navigateur

Linux n’ayant pas d’interface graphique, il vous faut vous authentifier votre installation Dropbox via votre navigateur

Surlignez avec la souris le lien https://www.dropbox.com….  ça va le copier dans le presse-papier. Ensuite ouvrez un navigateur et collez y l’url. Vous devrez vous authentifier sur votre navigateur, si c’est ok l’opération de liaison de votre serveur Linux et de votre compte Dropbox à réussis, Dropbox va créer un répertoire Dropbox et commencer à synchroniser les fichiers.

 

 

Installer l’outil en python en ligne de commande

Pour faire ce que vous faites avec Dropbox sur votre ordinateur avec interface graphique, (créer des répertoires, exclure des répertoire de la synchronisation) il ya un outil en ligne de commande officiel fait par Dropbox à télécharger et installer.

$ mkdir -p ~/bin  
$ wget -O ~/bin/dropbox.py "http://www.dropbox.com/download?dl=packages/dropbox.py"  
$ chmod 755 ~/bin/dropbox.py  
$ ~/bin/dropbox.py help

 

Muni de cet outil CLi (ligne de commande) vous pouvez exclure les répertoires que vous ne voulez pas voir sur votre dédié comme vos photos de vacance, on va se limiter au strict nécessaire, les sauvegardes de base de données.

Tout d’abord utilisez l’outil CLi pour voir le status de Dropbox

$~/bin/dropbox.py start

$~/bin/dropbox.py status

Vous vous apercevez que le processus de synchronisation a déjà commencé, il faut donc exclure les répertoires et les fichiers

$~/bin/dropbox.py exclude add fichier1 fichier2 fichier3

pour exclure un répertoire

$~/bin/dropbox.py exclude add folder1 folder2

pour les noms avec espace comme photos vacances

$~/bin/dropbox.py exclude add photos\ vacances

le slash sert à échapper les caractères spéciaux

Une fois que vous avez exclu des répertoire, vérifiez ce qui a été exclu

$~/bin/dropbox.py exclude list

 

Créer un répertoire pour la sauvegarde et ne l’excluez pas de la sauvegarde !

Il se peut que au bout d’un certain temps la synchronisation ne marche plus, en effet il m’est arrivé qu’au bout d’environ 35000 fichiers, la synchronisation soit stoppée. La raison est que le programme Dropbox par défaut ne peut gérer qu’un certains nombre de fichiers, il faut lever cette limite,d’ailleurs vous aurez un message de ce type si vous tentez de redémarrer Dropbox en faisant stop et start.

Unable to monitor entire Dropbox folder hierarchy. Please run "echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf; sudo sysctl -p" and restart Dropbox to fix the problem.

Il suffit de faire la commande préconisée

echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf; sudo sysctl -p

Et ensuite redémarrez Dropbox.

Voilà j’espère que vous apprécierez cette astuce pour avoir des sauvegarde fiables de vos données sur vos serveurs web sans débourser un centimes de plus si vous avez déjà Dropbox. En effet on peut considérer que c’est gratuit puisque de toute façon vous avez déjà un compte Dropbox. Inutile de pense à du C14 ou du Amazon Glacier, ces solution peuvent paraitre pas cher mais vous êtes facturé à la bande passante. De plus ce sont des sauvegarde-sauvegarde, vous êtes sensé les utiliser comme recours lorsque vous perdez des données, avec Dropbox, ce sont des données vivantes que vouspouvez sauvegarder, comme des banques d’images, des répertoires entier.

Pour aller plus loin, je me suis inspiré de ces deux liens pour faire ce que je vous ai décris dans ce billet :

http://www.dropboxwiki.com/tips-and-tricks/install-dropbox-in-an-entirely-text-based-linux-environment

http://www.dropboxwiki.com/tips-and-tricks/using-the-official-dropbox-command-line-interface-cli

php

Module PHP quelle version utiliser ? Thread Safe ou Non Thread Safe?

Tout pour bien sélectionner la version du module pour PHP

Le contexte technique fondamental en HTTP

 

Différents serveurs web mettent en œuvre différentes techniques pour traiter les requêtes HTTP entrantes en parallèle. Une technique assez populaire est d’utiliser des threads — c’est-à-dire, le serveur web va créer/dédier un thread unique pour chaque requête entrante. Le serveur web Apache HTTP supporte de multiples modèles pour traiter les requêtes, dont l’un (appelé MPM ouvrier) utilise des threads. Mais il supporte un autre modèle de simultanéité appelé MPM prefork qui utilise des processus — c’est-à-dire que le serveur web créera/dédiera un seul processus pour chaque requête.

Il existe également d’autres modèles de concurrence complètement différents (utilisant des connecteurs asynchrones et des E/S), ainsi que d’autres qui combinent deux ou même trois modèles. Pour répondre à cette question, nous ne nous intéressons qu’aux deux modèles ci-dessus, en prenant l’exemple du serveur HTTP Apache.

Connaissance nécessaire sur la façon dont PHP « s’intègre » avec les serveurs web

PHP lui-même ne répond pas aux requêtes HTTP réelles — c’est le travail du serveur web. Nous configurons donc le serveur web pour transférer les requêtes vers PHP pour traitement, puis nous recevons le résultat et le renvoyons à l’utilisateur. Il y a plusieurs façons de chaîner le serveur web avec PHP. Pour Apache HTTP Server, le plus populaire est « mod_php ». Ce module est en fait PHP lui-même, mais compilé comme un module pour le serveur web, et donc il est chargé directement à l’intérieur.

Il existe d’autres méthodes pour enchaîner PHP avec Apache et d’autres serveurs web, mais mod_php est le plus populaire et servira aussi à répondre à votre question.

Vous n’aviez peut-être pas besoin de comprendre ces détails auparavant, parce que les sociétés d’hébergement et les distributions GNU/Linux viennent avec tout ce qui est préparé pour nous.
Maintenant, quelle différence entre Thread Safe et non Thread Safe?!

Comme avec mod_php, PHP est chargé directement dans Apache, si Apache va gérer la simultanéité en utilisant son Worker MPM (c’est-à-dire, en utilisant Threads) alors PHP doit être capable d’opérer dans ce même environnement multi-thread — ce qui veut dire que PHP doit être thread-safe pour pouvoir jouer correctement avec Apache!

A ce stade, vous devriez penser « OK, donc si j’utilise un serveur web multi-threadé et que je vais intégrer PHP directement, alors je dois utiliser la version thread-safe de PHP ». Et ce serait une bonne idée. Cependant, il se trouve que la sécurité des threads de PHP est très contestée. C’est un terrain d’utilisation pour les initiés, si vous savez vraiment ce que vous faites.

Conclusion

Quand votre PHP est installé en CGI ou FastCGI, utilisez le Non Thread Safe, si c’est installé en tant que Module Apache, utilisez le Thread Safe

Au cas où vous vous poseriez la question, mon conseil personnel serait de ne pas utiliser PHP dans un environnement multi-threads si vous avez le choix!

Parlant seulement des environnements Unix, je dirais que heureusement, vous n’avez qu’ à penser à cela si vous allez utiliser PHP avec le serveur web Apache, auquel cas il vous est conseillé d’aller avec le MPM de préfork d’Apache (qui n’utilise pas de threads, et donc, thread-safe n’a pas d’importance) et toutes les distributions GNU/Linux que je connais prendront cette décision pour vous quand vous êtes Si vous allez utiliser d’autres serveurs web tels que nginx ou lighttpd, vous n’aurez pas la possibilité d’y intégrer PHP de toute façon. Vous allez voir comment utiliser FastCGI ou quelque chose d’égal qui fonctionne dans un modèle différent où PHP est totalement en dehors du serveur web avec plusieurs processus PHP utilisés pour répondre aux demandes à travers par exemple FastCGI. Dans ce cas, la sécurité des fils n’ a pas d’importance.

Quelles différences en thread safe et non thread safe?

Thread safe

La sécurité des threads est utilisée pour éviter les conflits lorsque des données partagées sont manipulées par différents threads. Elle est particulièrement importante lorsque des threads sont utilisés pour gérer des requêtes sur un serveur Web. Les versions « Thread Safe » permettent aux fichiers binaires de fonctionner correctement dans un environnement de serveur Web multi-thread en créant une copie locale de stockage pour chaque thread, ainsi les données ne se heurtent pas à un autre thread. En général lorsque PHP est installé en tant que module de Apache (vous le savez car vous touchez au fichier httpd.conf)

dans le contexte du multithreading, on doit garantir que différents threads ne touchent pas indépendemment aux données, ce qui mettrait sens dessus dessous les données. Par exemple un client A peut commander et payer le total du client B si ce n’est pas fait correctement.

Non thread safe

Les versions « non-thread safe » ne garantissent pas la sécurité des threads, ce qui les rend plus rapides à exécuter mais plus instables et sujettes aux blocages fréquents. Ces versions ne prennent en compte qu’un seul thread. Les fichiers binaires « non-thread safe » sont souvent utilisés lorsqu’il n’y a pas de besoin d’utiliser le multi-threading, comme dans le cas d’une interaction avec un serveur Web via le protocole FastCGI. Donc quand vous voyez fast CGI, c’est du non thread safe.

Comment savoir si PHP est installé en CGI ou en Module?

Pour voir quelle version de votre site web utilise, mettez un fichier contenant <? php phpinfo ();? > sur votre site et recherchez l’entrée API du serveur. Cela pourrait dire quelque chose comme CGI/FastCGI ou Apache 2.0 Handler.

fast CGI

Si vous regardez aussi la version en ligne de commande de PHP — la sécurité du thread n’a pas d’importance.

Enfin, si la sécurité du theading n’ a pas d’importance, quelle version devez-vous utiliser — Thread Safe ou Non Thread Safe? Je suppose que la version non-thread-safe est plus rapide et moins buggy, ou sinon ils auraient juste offert la version thread-safe et ne se seraient pas donné la peine de proposer ces deux alternatives !

 Supplément

Comment savoir si son installation php est Thread Safe ou non Thread Safe?

sur Linux
$ php -i | grep Thread

Sur Windows

$ php -i | find "Thread"
javascript

Sélectionner des éléments HTML en Javascript pur

Sur ce blog, quand je parle de Javascript, je parle de Javascript pur, et non de JQuery, cette extension étant trop célèbre, sur les forums les gens ont même tendance à proposer une solution en JQuery alors que c’est en Javascript pur (Vanilla Javascript) que la question était posée.

Sélectionner des tags HTML en Vanilla Javascript

Supposons que vous avez une page HTML, vous agrémentez d’un script Javascript en fin de page, on va utiliser la méthode querySelectorAll, qui est une fonction très importante, car elle permet de sélectionner des tags HTML selon divers critères. Par exemple, si on veut les liens hypertextes présents sur la page courante :

var links = querySelectorAll("a")

Pour comprendre comme ça marche, le sélecteur est « a » comme ancre, c’est comme en CSS, si je veux que des div, je mets « div », si je veux les div et ancres :

var elem = document.querySelectorAll("a","div")

Maintenant on va faire un peu plus compliqué :). Supposons que nous voulions seulement les liens nofollow, sur une page HTML un lien nofollow est spécifié avec l’attribut « rel » :

<a href="https://www.google.fr" rel="nofollow" />Lien</a>

Pour sélectionner ce lien, on fera :

var links = document.querySelectorAll("a[rel=nofollow]")

querySelectorAll pour sélectionner dans un sous ensemble de HTML

Parfois on a besoin de faire une sélection sur un ensemble plus petit, parce que la page est complexe, on veut dégrossir le travail. On peut dans ce cas sélectionner un élément HTML d’ordre supérieur, et faire un querySelectorAll sur ce sous ensemble.

var contenu = document.querySelectorAll("div[id=main]")
var links = contenu.querySelectorAll("a")

Ceci est rendu possible par le mécanisme d’héritage de type prototypal (pas un héritage classique au sens classe).

querySelector pour ne sélectionner que le premier

Il peut arrive qu’on n’a besoin que d’un élément (quand on est sûr), et cela pour éviter d’avoir à itérer sur un tableau, on utiliser alors QuerySelector, qui nous retourne alors un seul élément. Dans le jargon, on parle d’un node retourné, là où querySelectorAll retourne un nodeList.

WPF

Les boites de dialogue en WPF : MessageBox

Boite de dialogue en WPF avec MessageBox

 

Ah les boites de dialogue ! Elles sont incontournables en informatique, elles permettent à l’application de … dialoguez avec l’utilisateur. Ce peut être un simple message avec un seul bouton pour fermer le fenêtre, ou une demande de confirmation avec deux boutons Ok ou Annuler, mais ça peut être plus élaboré.

Une premier exemple de MessageBox simple

On va supposer que la boite de dialogue apparait suite à un clic droit de la souris sur une cellule, donc on va mettre le code suivant dans une méthode :

private void TextBlock_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    MessageBoxResult result = MessageBox.Show("Voulez vous effacer cet enregistrement?", "Ask for delete", MessageBoxButton.YesNoCancel, MessageBoxImage.Question, MessageBoxResult.No);
    switch (result)
    {
        case MessageBoxResult.Yes:
        statusText.Text = "Suppression acceptée !";
            break;

        case MessageBoxResult.No:
            statusText.Text = "Suppression refusée !";
            break;

        case MessageBoxResult.Cancel:
            statusText.Text = "Suppression annulée!";
            break;
    }
}

Nous avons la boite de dialogue suivante assez complète :

WPF MessageBox

En effet, la méthode MessageBox.Show (qui est une méthode static) prend dans l’exemple 5 arguments. Le minimum est de un argument. Voici par ordre de décroissance les possibilité de personnalisation de la MessageBox

     
MessageBoxResult result = MessageBox.Show("Voulez vous effacer cet enregistrement?", "Ask for delete", MessageBoxButton.YesNoCancel, MessageBoxImage.Question, MessageBoxResult.No);

MessageBoxResult result = MessageBox.Show("Voulez vous effacer cet enregistrement?", "Ask for delete", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);

MessageBoxResult result = MessageBox.Show("Voulez vous effacer cet enregistrement?", "Ask for delete", MessageBoxButton.YesNoCancel);
         
MessageBoxResult result = MessageBox.Show("Voulez vous effacer cet enregistrement?", "Ask for delete");

MessageBoxResult result = MessageBox.Show("Voulez vous effacer cet enregistrement?");

 

WPF

Premiers pas avec WPF dotNet

WPF est un framework pour développer des application Windows en client lourd. Donc si vous venez du monde du web, ça va vous changer, en effet ici, il n’est plus question de faire une application web, on est dans le traditionnel desktop. Même si le web a le vent en poupe, il ne faut pas oublier les application lourdes, et puis si vous êtes un programmeur digne du nom, vous serez assez curieux de voir comment on fait des application qui « tournent » sous Windows !

WPF c’est quoi?

WPF Windows Presentation Foundation est un framework pour faire des applications graphique. Il contient des objets pour faire des fenêtres, des boutons, des scroll, bref tout ce qui est visuel. En plus de cela il contient les éléments pour associer des données et les afficher dans les éléments visuel, et enfin tout ce qu’il faut pour détecter des actions quand on clique sur certains éléments comme des boutons.

Anatomie d’une application WPF

Lorsqu’on crée un application WPF dans VisualStudio (il n’y a pas d’autres éditeurs en dehors, sauf celui de Jetbrain), on a une série de fichiers créés, dont deux notable, le fichier par défaut MainWindow.xaml et MainWindow.xaml.cs.

MainWindow.xaml est un fichier xml spécifique à WPF qui détaille le visuel et aussi le fonctionnel (pour l’heure on se suffira du visuel) de l’application. Une hiérarchie sous forme d’arbre pour visualiser le déroulé des composants, un peu à la manière du DOM d’un navigateur web.

<Window x:Class="LearnWPF.ItemsControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="ItemsControlPanelSample" Height="150" Width="250">
        <Grid Margin="10">
        </Grid>
</Window>

Puis voici le fichier MainWindow.xaml.cs qui est un fichier de code C#, appelé code behind, c’est le code métier en back office qui va faire fonctionner l’application WPF.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace LearnWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class myItemsControl : Window
    {
        public myItemsControl()
        {
            InitializeComponent();
        }
    }
}

Il est important de voir la correspondance entre le fichier xaml et le fichier C#.

Le namespace qui est ici LearnWPF, que l’on peut voir dans le xaml, avec la notation pointée suivi du nom de la classe, LearnWPF.myItemsControl.

Dans le fichier code behind, on retouve ces références :

namespace LearnWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class myItemsControl : Window
    {
        public myItemsControl()
        {
            InitializeComponent();
        }
    }
}

On retrouve le namespace, la classe myItemsControl qui hérite de Window pour bénéficier de propriétés et méhodes, et aussi le constructeur.

Je poursuis l’exemple en enrichissant le fichier XAML afin d’expliquer certaines notions dans WPF.

Les ItemsControls dans WPF

C’est une notion fondamentale, ce sont les listbox, treeview, et les classes filles des ItemsControl sont les status bar, toolbar, menu.

Les ControlsPanel : qui dit panel dit layout

Ce sont les controls qui vont placer les autres éléments dans la fenêtre,autrement dit ils servent à faire le layout de l’application : Stackpanel (souvent utilisés), wrapPanel, Grid,TabPanel, Canvas.

La notation pointée dans le XAML

On peut faire beaucoup de choses dans le fichier XAML et j’ai mis un peu de temps à comprendre la notation pointée dans certains tags. Exemple ci-dessous :

<ItemsControl>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button Content="{Binding}" Margin="0,0,5,5" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <system:String>Item #1</system:String>
                <system:String>Item #2</system:String>
                <system:String>Item #3</system:String>
                <system:String>Item #4</system:String>
                <system:String>Item #5</system:String>
            </ItemsControl>

Notez la notation pointée ItemsControl.ItemsPanel,  il faut faire le parallèle avec une classe, ici ItemsPanel est une propriété de la classe ItemsControl, et c’est comme ça qu’on sette une propriété en XAML !

Pour vous en convaincre, allons faire un tour dans la classe myItemsControl et faire travailler l’auto-complétion de code :

WPF itemspanel

Au passage servez vous de l’auto-complétion pour en apprendre plus sur les membre d’une classe c’est très intéressant !

Donc pour setter une propriété en XAML, on y met du XML logique même si ce n’est pas évident (on aurait pu penser à des attributs).

<ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
                <StackPanel /> 
        </ItemsPanelTemplate> 
 </ItemsControl.ItemsPanel> 

Dans le XAML ci-dessus, on définit le template de ItemsControl avec un Stackpanel.

WPF

WPF Ajouter un popup pour confirmer une action

Les popups (à ne pas confondre avec les Dialog Box) sont utiles pour confirmer qu’une action s’est déroulée bien ou non. Vous avez juste à cliquer pour que la popup se ferme.

Commençons par construire une application WPF de façon classique.

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication3"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
<Popup Margin="10,10,0,13" Name="Popup1" HorizontalAlignment="Left"   
 VerticalAlignment="Top" Width="194" Height="200" IsOpen="True">  
       <TextBlock Name="MonTextBlock"   
             Background="LightBlue" >  
        texte de popup   
       </TextBlock>  
</Popup>

    </Grid>
</Window>

La valeur de l’attribut IsOpen à True veut dire qu’il est visible. Ce que l’on veut faire par exemple c’est de rendre la popup visible avec un bouton et de mettre un bouton dans le popup pour fermer le popup, donc on va jouer sur la propriété IsOpen. Quand on lance l’application ça donne ça:

WPF popup

Vous aurez remarqué que j’ai mis les attributs HorizontalOffset et VerticalOffset, donnés en valeur relatives, sinon la popup est en bas à gauche de la fenêtre de l’application.

Popup offset WPF

Je vous invite à jouer sur les différents attribut. Mais celui qui nous intéresse le plus est l’attribut IsOpen. En effet je m’en sers pour des confirmation d’insertion de données dans une table, j’ai besoin d’être informé quand l’insertion s’est fait avec succès. Quitte à cliquer un bouton supplémentaire pour fermer la popup.

Utiliser le code behind pour ouvrir/fermer la popup

//le nom de la popup est popup1
// pour ouvrir le popup
popup1.IsOpen = True;

//pour fermer le popup
popup1.Isopen = False;

A ne pas confondre avec la propriété popup1.IsVisible qui est en fait un simple getter.

Vou saimeriez aussi savoir comment faire une boite de dialogue

javascript

Comment créer un bookmarklet?

Créer le bookmarklet le plus simple du monde en 10 secondes

<a href="javascript: alert('Un bookmarklet !');">Fav moi</a>

Cela va créer lien Fav moi, que vous allez glisser déposer sur la barre des favoris.

En fait ce n’est rien de plus qu’une ligne de javascript que vous auriez fait de façon classique, sauf que c’est mis dans un lien, et que vous avez mis en favori ce lien, astucieux comme concept non?

Pour c’est super intéressant de savoir faire un bookmarklet? C’est plus simple que de faire faire un addon pour Firefox ou Chrome, par exemple, et c’est presque croos browser de nos jours aux différences d’implémentation de Javascript près.

Parce que ça augmente les fonctionnalité du browser, donc de faire des trucs super intéressant sur les pages web, comme par exemple surligner les liens hypertexte, ou remplacer le logo de Google par celui de Bing ! et vice versa.

Pour les SEO cela peut être intéressant, faites travailler votre imagination.

Les différents degrés de sophistication de conception des bookmarklet

Nous avons vu que la première et plus simple manière de faire un bookmarklet est de mettre directement le Javascript dans un lien hypertexte. Ok c’est cool mais si le code Javascript est plus conséquent?

Un bookmarklet est un code qui va s’exécuter sur la page courante. Vous pouvez définir une fonction anonyme dans la section script et l’appeler dans le lien hypertexte.

  1. Le javascript dans le lien directement (voir ci-dessus)
  2. Le javascript dans une fonction anonyme quand le code est plus conséquent
  3. Le javascript dans un fichier externe (on fait une inclusion avec <link>)
  4. Plus badass, incluez AngularJS ou VueJS ou toute autre librairie
javascript:(function(){// code javascript })();

Voici un exemple de bookmarklet que j’ai fait pour remplir le champ « Legende », »Alt » et « Description » dans l’interface d’ajout d’image.

<a href="javascript:(function(){var t=document.querySelectorAll('div.media-sidebar label input');var a=t[2];var u=document.querySelectorAll('div.media-sidebar textarea');var b=u[0];var v=document.querySelectorAll('div.media-sidebar label input');var c=u[1];b.innerHTML=c.innerHTML=a.value;this.stop;})()">copy</a>

Inclure une feuille de Javascript externe quand vraiment le code est trop volumineux. Dans ce cas il vous placer le script dans une url accessible sur le web.

javascript: (function () { 
   var jsCode = document.createElement('script'); 
   jsCode.setAttribute('src', 'http://domaine.com/file.js');                  
 document.body.appendChild(jsCode); 
}());

Souvenez vous que votre bookmarklet ne doit pas avoir de collission avec le JS de la page sur laquelle elle sera utilisée. Dans l’exemple ci-dessus c’est une fonction à invocation immédiate qui est utilisée, évitant justement la collision de variable.

Si vous chargez un script et que vous voulez être sûr  qu’il soit chargé, voici un tuto sur un site https://idiallo.com/javascript/async-jquery

Element de langage en javascript utile pour les bookmarklets

Les bookmarklets font beaucoup de traversing de DOM ou de sélection de DOM, vous devez en général le faire en Javascript pure voici quelques commandes pour vous simplifier le travail

querySelectorAll

Cette fonction est très utilisée pour matcher des éléments du DOM, elle va vous retourner un objet de type NodeList. NodeList n’est pas un tableau, vous ne pouvez pas le traverser avec une boucle for traditionnelle, ni map(), filter() ou slice(), il faut le convertir en tableau avant.

#sélection des liens 
var a=document.querySelectorAll('a') // NodeList
#sélection des div avec la classe 'primary'
var a = document.querySelectorAll('div.primary')

Convertir un NodeList en tableau

# Array.from()
var array = Array.from(a)

#spread operator
var array = [...a] // rendu possible car a est iterable
javascript

A bookmarklet to let you easily test javascript snippets

A shell for executing javascript in a bookmarklet !

A shell in a bookmarklet

Can you believe that? a bookmarklet is a short javascript code snippet (usually shorter than 1024 characters), that performs various tasks, and you can bookmark them = execute them by clicking on the bookmark, neat huh? For example if you are a member of the social bookmarking site Delicious, there is a bookmarklet that let you bookmark a site without copy pasting a url into the form, all you need to do is click on the bookmarklet, it’s (almost) done !

With the bookmarklet that I am talking, you have a console like a Unix shell, type you javascript command or script, press enter and the code is executed. Go fetch the shell bookmarklet.

Once you are on the webpage, drag the « Shell » bookmarklet in your bookmark area, that’s all. Just clik on the bookmark to open a popup window (the console) and start playing with javascript !

WPF

Faire une application météo WPF Windows Presentation Framework

 

WPF pour créer des applications Windows Desktop

WPF en gros pour faire court c’est une application desktop avec des fenêtres. WPF est le successeur de Winform, personnellement je ne connais pas du tout Winform, disons que c’est la génération avant WPF. On va faire avec WPF, c’est une façon de programmer MVVM (Model-View-ViewModel). En gros ça veut dire qu’il y a une liaison entre le visuel et le modèle de données (les données elles-même appelé ViewModel), si vous modifiez une valeur sur l’interface graphique, cela va se répercuter dans la variable. Cette dernière variable peut être modifiée programmatiquement.

La programmation MVVM existe aussi sur le web, j’en ai pas mal fait avec AngularJS. L’avantage est une simplification de la mise à jour des données entre l’interface et la base de données.

Création d’une application WPF dans VisualStudio

Pour tout projet C#, vous êtes obligé de passer par VisualStudio, je ne pense pas qu’il y ait d’autres alternatives, c’est tant mieux ainsi, on va se concentrer mieux.

Concevoir une fenêtre en WPF

La différence avec une application est la présence d’une interface graphique, qui dit interface graphique de nos jour dit langage xml, dans le cas de WP, Microsoft a pondu une version de xml qui s’appelle le XAML.

A partir de là vous avez le choix de concevoir votre interface de manière graphique avec la souris, ou d’écrire directement en XAML, pour avoir un controle plus fin, mais les deux sont équivalent. Vous devez jongler entre les deux pour voir de quoi il retourne. A terme le design graphique vous permettra d’aller plus vite, mais la programmation en XAML va vous permettre de caler les éléments au pixel près.

xaml

Avec VisualStudio, les deux fenêtres graphique et textuelle se mettent à jour automatiquement dès qu’on modifie un élément d’une des deux fenêtres. Donc si vous êtes débutant, c’est un bon moyen d’apprendre.

Comment faire vivre l’interface graphique?

C’est bien beau de faire une belle interface graphique, quoique vous aurez des surprises car avec le glisser déplacer ce n’est pas si évident, en plus il y a énormément de composants, mais comment allons nous attacher du code à un bouton par exemple?

Il y a deux fichiers, MainWindow.xaml et MainWindow.xaml.cs, celui qui a l’extension cs correspond au code C#, donc vous y écrirez toutes les fonctions, on appelle le code derrière un bouton un code-behind tout simplement. Regardez comment le XAML et le code C# sont liés.

A chaque élément est attaché une fonction, par exemple, pour un bouton :

<Button x:Name="button1" Content="Meteo Toulouse" HorizontalAlignment="Center" Margin="10,10,10,0" VerticalAlignment="Top" Width="75" Click="GetMeteoToulouse_Click" />

On a un attribut Click dont la valeur est égale à GetMeteoToulouse_Click. et dans le code-behind, dans le fichier MainWindow.xaml.cs est automatiquement inséré un code du type :

  private void GetMeteoToulouse_Click(object sender, RoutedEventArgs e)
 { 
   //.......
   // code c# ici
 }

Cette fonction prend en argument deux paramètres. En WPF, il y a la notion très importante d’événement (RoutedEvent, mais en fait c’est un event), un click sur un bouton est un événement, une mise à jour d’une valeur est un événement, il faut donc bien comprendre comment les événements sont gérés.

Si le bouton est cliqué, c’est la méthode ci-dessus qui va s’exécuter.

Pour faire simple voici le code du XAML:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication3"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <WrapPanel x:Name="wrapPanel1" Height="100" Width="100"/>
        <Label x:Name="label" 
               HorizontalAlignment="Stretch" 
               Margin="10,202,37,10" 
               FontSize="20"
               Padding="5"
               Loaded="label_Loaded" 
               VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Height="107">
        </Label>

        <ScrollViewer HorizontalAlignment="Left" Height="195" Margin="10,80,0,0" VerticalAlignment="Top" Width="497">
            <StackPanel Grid.Row="0" Height="110" Orientation="Horizontal" RenderTransformOrigin="0.5,0.5">
                <StackPanel.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform Y="-30"/>
                    </TransformGroup>
                </StackPanel.RenderTransform>
                <Button x:Name="button" ToolTip="Un café?" Content="Shrink Label Text" HorizontalAlignment="Center" Margin="10,10,0,60" VerticalAlignment="Top" Width="100" Click="button_Click_1"/>
                <Button x:Name="button1" Content="Meteo Toulouse" HorizontalAlignment="Center" Margin="10,10,10,0" VerticalAlignment="Top" Width="75" Click="GetMeteoToulouse_Click" />
            </StackPanel>
        </ScrollViewer>

    </Grid>
</Window>

et le code behind :

using System;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.Windows.Media.Imaging;

namespace WpfApplication3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }

        private void label_Loaded(object sender, RoutedEventArgs e)
        {
            var label = sender as Label;

        }


        /// <summary>
        /// demande le temps qu'il fait pour Toulouse
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GetMeteoToulouse_Click(object sender, RoutedEventArgs e)
        {
            //get weather !
            var url = "http://api.openweathermap.org/data/2.5/weather?q=Toulouse&APPID=ici-la-cle-api";
            var webrequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);

            using (var response = webrequest.GetResponse())
            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                var result = reader.ReadToEnd();

                var jObject = Newtonsoft.Json.Linq.JObject.Parse(result);
                this.label.Content = ((string)jObject["weather"][0]["main"]);
                //Console.WriteLine((string)jObject["weather"][0]["icon"]);
                //Console.WriteLine(Convert.ToString(Math.Round((float)jObject["main"]["temp"] - 273.15)));

                //on va chercher l'image sur le serveur de l'api
                var image = new Image();
                var fullFilePath = @"http://openweathermap.org/img/w/"+ (string)jObject["weather"][0]["icon"] + ".png";

                BitmapImage bitmap = new BitmapImage();
                bitmap.BeginInit();
                bitmap.UriSource = new Uri(fullFilePath, UriKind.Absolute);
                bitmap.EndInit();

                image.Source = bitmap;
                wrapPanel1.Children.Add(image);

            }
        }

    }
}

Cette application est un peu codé à la rache, mais est fonctionnelle, il y a juste la clé API de OpenWeather qu’il faut créer pour avoir accès aux informations.

Linux

Convertir l’encodage d’un fichier en ligne de commande sous Linux

Je sais que nombre d’entre vous avez rencontrés d’énorme difficulté avec les page web qui ne s’affichent pas bien,on n’est pas gâté en France avec autant de lettres accentuées ! Et quand on a trouvé la formule qui affiche correctement, on ne touche plus à rien !

En attendant je vous donne une technique qui permet de convertir en ligne de commande sous Linux (oui oui), avec iconv (ça vous dit rien cette fonction sous php?)

iconv -f ISO-8859-1 -t UTF-8 nom_du_fichier_source -o fichier_encode

Pour l’occasion on a créé un autre fichier, histoire de garder une trace de l’ancien fichier au cas où.

csharp green logo

Introduction aux expression régulière en C#

J’ai fait beaucoup de regex dans ma vie avec le langage de programmation PHP, mais avec le C# je m’aventure dans de nouvelles contrées, le but est de scraper des pages web en C# (nouveau défi !) et de rester dans l’environnement .NET (SQLServer, IIS, WPF etc). Je suppose que vous avez déjà des connaissances élémentaires avec les expressions régulières.

Expression régulière en C#

Globalement, c’est la même chose qu’en PHP, mais il y a des subtilités syntaxiques. L’objet de  ce post est plutôt montrer comment écrire une application console pour tester rapidement un script qui va parser des chaine avec du regex. On ne verra sans doute pas de différence vu que ce que je présente est assez élémentaire.

Utiliser IsMatch pour matcher une séquence

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace scraper
{
    class Program
    {
        // http://lgmorand.developpez.com/dotnet/regex/
        static void Main(string[] args)
        {
            // TODO : match, replace, capture
            
            String chaine = "numéro de téléphone est  06 55 32 22";
            String telephone = "06 88 95 31 22";



            Regex matchPhone = new Regex(@"^[\d]+$");

            
            var test = matchPhone.IsMatch(telephone);
            

            Console.WriteLine("le resultat du match est " + remplace);
            Console.ReadLine();
        }
    }
}

Si nous faisons F5 pour lancer cette application, nous aurons comme sortie d’écran :

le resultat du match est False

En effet la chaine telephone est composé d’espace. Pour avoir le résultat à True, il faut enlever les espaces dans le numéro de téléphone (à moins de matcher aussi les espaces).

Utiliser Replace pour remplacer une chaine de caractères

using System;
using System.Text.RegularExpressions;
namespace scraper
{
    class Program
    {
        // http://lgmorand.developpez.com/dotnet/regex/
        static void Main(string[] args)
        {
            // TODO : match, replace, capture

            String chaine = "numéro de téléphone est  06 55 32 22";
            String telephone = "06 88 95 31 22";



            Regex myRegex = new Regex("^[a-z]$");
            Regex matchPhone = new Regex(@"téléphone");

            var remplace = matchPhone.Replace(chaine, "mobile");

            Console.WriteLine("le remplacement regex a donné " + remplace);
            Console.ReadLine();
        }
    }
}

En jouant ce code vous aurez à al sortie le texte « téléphoneé remplacé par mobile.

le remplacement regex a donné : numéro de mobile est  06 55 32 22

La variable « remplace » contient la  nouvelle chaine.

Capturer une chaine

Nous allons maintenant faire ce pour quoi le rege est le plus utile : extraire une chaine satisfaisant une condition et la stocker éventuellement dans une variable.

using System;
using System.Text.RegularExpressions;
namespace scraper
{
    class Program
    {
        // http://lgmorand.developpez.com/dotnet/regex/
        static void Main(string[] args)
        {
            // TODO : match, replace, capture
              String input = "numéro de téléphone est  0655322288";

            Regex matchDigit = new Regex(@"[\d]+");

            // match
            Match match = matchDigit.Match(input);
            if (match.Success)
            {
                string s = match.Groups[1].Value;
                Console.WriteLine("le match regex a donné : " + match);

            } else
            {
                Console.WriteLine("Pas de match trouvé");
            }
            Console.ReadLine();
        }
    }
}

Vous avez en sortie :

le match regex a donné : 0655322288

Maintenant on sait capturer avec des parenthèses (un classique) une chaine, on va passer à l’autre volet du scraping, le téléchargement d’une page web, le tout en C# bien sûr !

PLUS : Capturer avec les groupes nommés

Il vous est possible d’attribuer u nom au groupe que vous avez capturé. C’est pratique. Voyons comment on peut réécrire l’expression régulière de tout à l’heure.

fgfg

 

Magento Comment créer une boutique en mode multiboutique

Je suppose que l’installation de Magento est terminée, et qu’il y a déjà la boutique de base. On va ajouter une nouvelle boutique.

Pour être plus précis, Magento fait la distinction entre le site web, la boutique et la vue. Pourquoi une telle distinction? C’est pour répondre à toutes les événtualités, tous les besoins, car Magento veut brosser large et être la solution pour beaucoup de commerçants.

{image magento multiboutique}

 

Créer le site web

System > Manage Stores, puis on va supposer que l’on va faire la totale, c’est à dire créer un site web, une boutique et une vue. Donc créer une site web, puis créez un Store, et enfin créez une vue.

ensuite la méthode rcommandée est de modificer le .htaccess et ajouter les lignes suivante :

SetEnvIf Host electronic\.domaine\.fr MAGE_RUN_CODE=electronic
SetEnvIf Host electronic\.domaine\.fr MAGE_RUN_TYPE=website

Ensuite allez dans la configuration de Magento, choisissez le scope dans la liste déroulante, une fois sur votre boutique nouvellement créée, General puis Web, changez l’url avec l’url dans Secure et Unsecure, par http://electronic.domaine.fr et https://electronic.domaine.fr.

 

Il vous faut créer un virtualhost dans le fichier de configuration d votre serveur (pour Apache c’est dnas httpd.conf).

Ensuite, par défaut il n’y a aucun produit dans votre nouvelle boutique, il faut brosser manuellement les produit que vous voulez voir figurer dnas votre nouvelle boutique, allez dans le produit, dans l’onglet website, cochez la case correspondant à votre boutique.

Comment régler des prix différents d’une boutique à l’autre dans Magento

PAr défaut les prix des produtis sont gérés de façon globalde. Pour gérer au niveau site, et permetre d’avoir des prix différents par site web, aller dans Configuration > Catalog > Price, mettre le Scope à website.

Comment cacher des catégories sans article dans le multiboutique?

Aller dans la catégorie pour la boutique en question, et mettre isActive à No.

 

 

php

Comprendre le paramétrage de SuPHP

SuPHP est un module qui permet de d’exécuter des script php avec les permissions de leur propriétaire.

Par défaut, c’est l’utilisateur Nobody qui exécute les scripts php.

Le problème c’est que pour que Nobody puisse exécuter un script, il faut que le script php ait les droits 777, c’est à dire que tout le monde peut modifier le fichier, ce qui pose des risques de sécurité.

Donc SuPHP va interdire l’exécution des scripts php par le user nobody, et l’assigner en général au propriétaire du fichier.

Mais cela veut dire que chaque site web doit avoir un propriétaire?

En effet. Les panels d’administrations comme Virtualmin, lorsque que vous créez un virtual host, se chargent de créer un utilisateur sous Linux et donc un espace home pour ce même utilisateur. La racine site web est en général sous le répertoire /home/utilisateur/www.

php

Un truc en PHP 5.3 que vous ne pouvez plus faire en PHP 5.4 multi define de la même constante

EN travaillant sur un script ecommerce ultra pourri mais qui est en prod et que je dois migrer vers un serveur avec une version PHP 5.4, je me suis aperçu qu’il y avait une erreur loggée dans error_log : il y avait deux définitions de la même constante. Et le scrit ne tournait donc pas sur le serveur, puisque après un test, avec un script php où je définissait deux fois la même constante, sur 5.3 ça tournait sans problème, la constante était aussi (presque) malléable qu’une variable, voici le script :

<?php
define('TO', "bonjour");
echo TO;
define('TO',"au revoir");
echo TO;
?>

sous PHP 5.3

$ php test.php
bonjourbonjour

Bien que la constante puisse être redéfinie, sa valeur  ne change pas.

sous PHP 5.4

$ php test.php
bonjourPHP Notice:  Constant TO already defined in /home/user/test.php on line 4
PHP Stack trace:
PHP   1. {main}() /home/user/test.php:0
PHP   2. define('TO', 'au revoir') /home/user/test.php:4

On voit que le premier echo est exécuté, mais que le second déclenche une notice (ça peut être une erreur fatale).

Je pense que c’est une bonne chose (absolument !), soyons logique une constante ne peut être changée alors pourquoi autoriser la redéclaration? Heureusement que ça a changé et que PHP soit un langage plus rigoureux.

Bonus :

En PHP 5.3 vous pouvez utiliser un index d’un tableau qui n’existe pas sans qu’il vous geule dessus,

ainsi :

<?php
echo $p[0];

ne vous avertira rien.

Google Analytics Measurement protocole ou Google analytics côté serveur

Introduction au Measurement Protocol ou comment faire du Google Analytics côté serveur

Google analytic est un outil pour mesurer le trafic Web sur votre site web. Il nécessite de mettre un bout de code pour traquer les visites des internautes

Mais il est aussi possible d’envoyer les informations vers google analytics sans passer par un navigateur. Vous pouvez donc depuis un script côté serveur envoyer des informations vers Google analytic pour qu’il enregistre des informations
Pour ce faire nous devons utiliser une API qui s’appelle Measurement Protocol. Le principe est simple, il faut faire une requête de type POST vers le serveur de Google Analytics point

Je vais vous expliquer pourquoi connaître cet aspect de Google Analytics avec important, c’est relatif au tracking des achats sur votre site web. Dans le cas où le paiement s’effectue sur le site de la banque, et que le client revient sur votre site web, l’achat et suivi. Mais dans le cas où le paiement se finit et que la personne ne reviens pas sur votre site web, vous ne pouvez pas suivre les conversions.

Measurement protocol nous permet donc d’envoyer l’information comme quoi là ça a été réussi même si l’internat ne reviens pas sur votre site web après avoir payé sur le site de la carte bancaire

Le principe est simple, vous allez envoyer une requête vers le serveur de Google Analytics avec des paramètres bien défini, les paramètres doivent être au complet, sinon la requête échoue. Mais Google vous fournit à d’outils pour simuler et valider vos requêtes. cet outil c’est le Hitbuilder.

Mais d’abord nous allons voir un exemple très simple pour simuler une première requête vers le serveur de Google Analytics.

 

Il y a énormément de paramètres à envoyer car vous pouvez construire les mêmes requêtes que le script de Google Analytics sur le site web
Il vous faut vous référer à la page de documentation sur les paramètres pour voir la liste complète
Mais sans plus attendre faisant de notre première requête vers le serveur de Google Analytics
Il y a 4 paramètres obligatoire le premier paramètre concerne la version vous pouvez mettre ça n’a pas d’importance, le deuxième paramètre et le paramètre qui concerne le type de requêtes que vous allez vous allez faire , le plus simple c’est la pageview.
Le troisième paramètre est l’identifiant de votre compte Google Analytics et le dernier paramètres concerne le type de campagne pour simplifier nous allons mettre direct.

Voyons d’abord dans le HitBuilder comment nous allons construire à cette requête, dans un premier temps on construit les paramètres, en fait c’est la chaîne de paramètres que vous avez envoyer, ensuite vous allez cliquer sur le bouton Valider pour valider l’intégrité de cette requête et si tout se passe bien vous pouvez envoyer grâce à un bouton vers google Analytics la requête.

Pour visualiser le résultat de cette requête, basculer dans la vue temps réel de Google Analytics, vous aurez un retour immédiatement

Construire requêtes dans le Hitbuiler et cliquer sur Validate Hit

Créer une visualisation d’une page

 

Google analytics Measurement protocol tutoriel

 

Allez ensuite sur votre interface Google Analytics dans le rapport temps réel pour voir le résultat.

 

Étant donné que vous avez envoyé vraiment une requête vers votre serveur Google Analytics, les données Google Analytics de votre site de production seront affectées. Mais en développement vous pouvez vous permettre d’envoyer quelques données de test sans vraiment polluer les données de votre analytique.

Maintenant que l’on a réussi à envoyer une requête et à la visualiser grâce au graphique trafic temps réel de Google Analytics, on va essayer de faire une requête maintenant avec un script côté serveur. Attention, il y a un paramètre qui ne faut pas omettre et qui est le paramètre dp comme document path, je ne l’ai pas fait la première fois et aucune donnée n’a été envoyée,  ce n’est pas évident car si vous en mettez ce paramètre dans le tuto le HitBuilder, il va dire que la chaîne de requête est valide alors que aucune donnée n’a été envoyée, alors que dans la documentation de référence il est bien dit que dp et dh sont obligatoires dh étant le Host (nom de domaine).

Envoyer un Hit de type événement

Cette fonction est intéressante car se déroule dans un cadre plus large. En effet un événement peut être général, comme un clic sur un bouton, un slider, une durée de visionnage. C’est applicable non seulement aux application web mais aussi toute application, comme une application pour smartphone ou une application Windows.

Event tracking Google Measurement protocol

Requêtes dans le Hitbuilder de type transactionnelle

Bien que cet exemple soit très simple, le plus simple possible, il nous faut quand même 6 paramètres pour compléter la requête. Avant d’aller plus loin vers les scripts côté serveur, regardons quand même comment est fait une requête de type e-commerce et transactionnelle puisque c’est le but de cet article c’est-à-dire qu’on voudrait identifier les transactions e-commerce grâce à un script côté serveur.

Je prendrai l’exemple du logiciel de e-commerce PrestaShop. dans le logiciel Prestashop les transactions sont identifiées par le numéro de commande (et non le numéro de panier), par exemple pour une commande dont le numéro de panier est 3012, le numéro de transaction est 3012.

Dans Google Analytics, vous pouvez voir les transaction dans Conversion > Transaction.

Envoi d’une transaction

ti : transaction id

ta : transaction affiliation, ou le nom de la boutique

tr : transaction revenue,

ts : transaction shipping, frais de port

tt : transaction tax

cu : currency

Envoi d’un item

ti : transaction id, bien sûr si vous voulez que l’on sache dans quelle transaction cet item a été acheté !

in : item name

ip: item price

iq : item quantity

ic : item code (la référence de l’article)

iv : item category

cu : currency

Lorsqu’on envoie vers google analytics un item, il faut spécifier bien sûr le numéro de la transaction à laquelle il est associé vous spécifiez un sous-total, mais attention il faut que lorsque vous envoyez les items du panier, le total des items doit être cohérent avec le montant de la transaction, je vous laisse faire ça à côté serveur, tout ceci pour vous dire que vous pouvez avoir une incohérence entre la transaction le montant de la transaction est le total des items du palier, le système vous le permet.

Measurement Protocol Validation Server

 

Url de validation :
https://www.google-analytics.com/debug/collect?tid=fake&v=1
Elle ne diffère de la véritable url que de /debug/
Url d'envoi de requêtes :
https://www.google-analytics.com/collect?tid=fake&v=1

Lorsque vous forger une requête et de vous envoyer vers le serveur de Google analytic même si elle échoue n’aurait pas de message d’erreur en retour.
C’est pour cela que Google Analytics vous propose une adresse pour tester vos requêtes.

Attention j’ai noté que même si une requête est bien formatée et qu’elle ne retourne pas d’erreur en mode débogage, ceci ne veut pas dire que vous avez réussi votre requête. J’ai eu le cas où j’ai essayé pour une première fois d’envoyer une requête transaction où je n’ai pas inclu tous les paramètres « optionnels » , la requête n’a rien donné, j’ai vérifié en mode débogage j’ai eu un retour ok mais je n’avais toujours rien dans le rapport de Google Analytics.

Finalement j’ai relu la documentation j’ai pris l’exemple et j’ai réussi ma requête comme quoi il faut toujours se reporter à la documentation et bien la lire.

 

Beaucoup d’exemples de la documentation officielle pour aide mémoire des différentes type de requêtes.

Measurement protocol n’est pas limité au web, les applications Android peuvent utiliser l’API de Measurement Protocol. Les requêtes en  POST ainsi que GET peuvent être utilisées.

J’espère vous avoir aidé dans votre quêtes du tracking intégrale de toutes les transactions, en particulier les transaction de clients pressé (souvent en BtoB) qui ne reviennent même pas vers le site d’origine, tellement ils ont confiance en leur fournisseur.

Il est absolument important de pouvoir tracker toutes les conversion afin de mesurer le retour sur investissement des campagnes de marketing. Sans mesure on ne peut rien améliorer.

 

Cliquer sur le bouton vert pour envoyer la requêteEnvoi d’une transactionEnvoi d’un item de transaction

CSS Grid introduction et tutoriel débutant

Aujourd’hui je vais vous présenter une technologie CSS émergence qu’on utilisera dans les années à venir pour faire du responsive design

La technologie s’appelle le CSS grid
Aujourd’hui pour faire du responsive design en a besoin d’un framework CSS
Le premier des frémoire CSS qui permet de faire du responsive design et bootstrap
Ensuite il y en a eu d’autres j’ai plus utilisé par exemple UIKIT et sémantiqueUI.

 

Mais le problème que je t’ai rencontré été que c’est vrai moi qui était en constante évolution, et passer de l’un à l’autre de ces framework était assez fastidieux, car j’ai utilisé pas la même syntaxe

Pourtant on peut faire du responsive design en CSS pure mais c’est assez fastidieux
il y a les media queries qui vous permettent de réaliser le responsive design.

Mais comme vous le savez le CSS c’est assez difficilement lisible.

 

Bien sûr il y a des solutions comme le sac que vous transpirer en CSS mais ce n’est pas encore la solution idéale

Sans parler que le CSS a beaucoup de hack il faut utiliser pour avoir le même design sur tout les navigateurs

Puis est apparu la technologie flexbox qui résout un peu le problème

Mais cette dernière technologie est unidimensionnel et notre page est à deux dimensions

C’est pour résoudre ses problèmes que le CSS grid a été inventé pour l’instant seulement Google Chrome et Firefox l’ont implémenté

magento

Magento comment mettre des catégories sur la Homepage

A la différence des autres logiciels de ecommerce, avec Magento vous allez avoir du mal à mettre votre produit en page d’accueil, sans faire une manipulation bien particulière.

Afficher des produits d’une catégorie sur la page d’accueil

Allez sur la catégorie qui vous intéresse et regardez son ID vous en aurez besoin pour la suite.

Allez dans CMS > Pages > Home

Allez dans l’onglet Content et collez le bout de code suivant :

{{block  type="catalog/product_list" category_id="4"  template="catalog/product/list.phtml"}}

Update  !

Due à une mise à jour de sécurité, vous ne pouvez plus adopter cette méthode (plus exactement la SUPEE-6788), il faut toucher au xml du layout directement, donc dans la section Design de la page CMS, vous collez le bout de code suivant :

<reference name="content">
<block type="catalog/product_list" name="home.catalog.product.list" category_id="7" template="catalog/product/list.phtml" />
</reference>

Il faut mettre ce code dans la page CMS de la HomePage, dans la section design.

Retour en haut