Archives de catégorie : Développement

WordPress : WP_Query avec un tableau de « post__in » vide retourne des résultats !

La fonction WP_Query de wordpress qui permet de récupérer des posts en fonction d’une liste de critères contient une incohérence au niveau de l’argument « post__in ».
Cet argument permet de passer un tableau de posts (liste d’identifiants) afin de limiter la requête à ces posts. Pourtant si on lui passe un tableau vide, la recherche se fera sur tous les posts et on aura donc des résultats, alors qu’on s’attend à ne rien avoir.
Cela peut être gênant si notre tableau d’identifiants et généré dynamiquement et que l’on ne sait pas à l’avance si il va être vide.
Il faut donc penser à cette subtilité lors du développement afin de retrouver un comportement cohérent.
Une des solution est de toujours donner un identifiant inexistant (0) au tableau.

//!! va retourner des résultats !!
$listingIDs = array();
$args = array('post_type' => $type, 'post__in' => $listingIDs);
$my_query = new WP_Query($args);
//Ne retournera rien//
$listingIDs = array(0);
$args = array('post_type' => $type, 'post__in' => $listingIDs);
$my_query = new WP_Query($args);

Sortie de Bootstrap 4 (beta)

Après plusieurs mois (années) de développement en version alpha, le framework CSS Bootstrap qui c’est imposé comme référence pour le développement responsive sort en version 4 (beta). La page d’accueil de l’outil ne dirige plus vers la version précédente et toute la documentation pour la nouvelle version est disponible. Il est temps de s’y mettre.

WordPress : Réécriture d’un paramètre dans une URL

Exemple de code wordpress permettant de transformer une url avec un paramètre du type « ?param=slug-param » en une url réécrite plus « propre »

Grace à ce code on va transformer
« https://numa-bord.com/custom-slug/slug-post/?param=slug-autre-post »
en
« https://numa-bord.com/custom-slug/slug-post/slug-autre-post »

add_action('init', 'yoursite_init');

function yoursite_init() {
    global $wp, $wp_rewrite;
    $wp->add_query_var('custom_param');
    $wp_rewrite->add_rule('custom-slug/([^/]+)/([^/]+)', 'index.php?custom_param=$matches[2]&post_type=custom-type&name=$matches[1]', 'top');

    // activer seulement la première fois
    //$wp_rewrite->flush_rules(false);
}

Dans le template, on peux récupérer notre paramètre de la façon suivante :

$param = get_query_var('custom_param');

C’est une technique qui permet de faire pas mal de chose, l’exemple ci dessus pourrait permettre de comparer deux « post ».
Plus concrètement sur un site ayant des véhicules en « custom post type », permettre de comparer les caractéristiques de deux d’entre eux avec une url de ce type :
https://numa-bord.com/comparateur/vehicule1/vehicule2

Snippet PHP : Uploader une image en provenance d’un formulaire

Exemple d’une fonction permettant de gérer l’upload d’une image en provenance d’un formulaire. Permet de la renommer et de la placer dans le répertoire voulus en fonctions des paramètres passés. Attention ici on contrôle uniquement le fait que ce soit une image, si on à des contraintes sur la taille du fichier ou les extensions autorisées il faudra rajouter des vérifications.

Comme pour le snippet précédent on imagine cette fonction dans une class « Misc » qui pourrait contenir d’autre fonctions utilitaires variées.

class Misc {
    /**
     * uploade le fichier image en provenance du input "file" ayant pour nom $fieldName et donne le nom $imgName à l'image
     * retourne le nouveau dossier/nom.ext de l'image si upload ok, sinon false
     */

    public static function uploadImg($fieldName, $imgName, $target_dir = "../images/") {
        if (isset($_FILES[$fieldName]) && $_FILES[$fieldName]["name"] != "") {
            $ext = pathinfo($_FILES[$fieldName]["name"], PATHINFO_EXTENSION);
            $target_file = $target_dir . $imgName . '.' . $ext;
            //contrôle si c'est bien une image
            $check = getimagesize($_FILES[$fieldName]["tmp_name"]);
            if ($check !== false) {
                if (move_uploaded_file($_FILES[$fieldName]["tmp_name"], $target_file)) {
                    return $target_file;
                }
            }
        }
        return false;
    }
}

Utilisation (après l’envoi d’un formulaire ayant un input de type « file » ayant pour attribut « name » la valeur « logo ») :

Misc::uploadImg('logo', 'logo');//retourne le nouveau chemin et nom de l'image uploadé (ex : "../images/logo.png") ou false en cas d'erreur.

PHP : Importer les données dans une base depuis un fichiers .sql

Ci-dessous un script PHP permettant d’importer dans une base les données d’un fichier « export.sql ». Cela permet de créer les tables et d’insérer les données dans la base directement en PHP sans passer par l’import du fichier via le PhpMyAdmin

Ça peut être utile par exemple dans un « installeur » de site, dans la même idée de l’article précédent qui permettait de Créer une fichier de configuration en PHP

//effectuer la connexion à la base de données
$mysqli = new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
//fichier contenant le sql
$lines = 'export.sql';
//initialisation des variables
$req = "";
$finRequete = false;
//pour chaque ligne du fichier
foreach ($lines as $line) {
    //on saute les commentaires
    if (
substr($line, 0, 2) == '--' || $line == '') {
        continue;
    }
    //on ajoute la ligne à la requête
    $req .= $line;
    //Permet de repérer quand il faut envoyer l'ordre SQL...
    if (substr(trim($line), -1, 1) == ';') {
        $finRequete = true;
    }
    //si requête terminé, on l'exécute et on recommence le traitement à partir de la ligne suivante
    if ($finRequete) {
        if (!$mysqli->query($req)) {
            echo "<div class='alert alert-danger'>Erreur : " . $mysqli->error . "<br>" . $req . "</div>";
        }
        $req = "";
        $finRequete = false;
    }
}

PHP : Créer un fichier et écrire dedans

Exemple de code permettant de créer et d’écrire dans un fichier en PHP. Un des cas courant de ce besoins est la création de fichiers de configuration. Le code suivant permet de créer le fichier « config.db.php » qui comme son nom l’indiquer contiendra les constantes PHP permettant la connexion à la base de données.

Imaginons qu’il s’agit d’une partie d’un installeur de site. On demande de remplir les informations de connexion à l’utilisateur dans un formulaire classique. Une fois soumis on contrôle les champs, on vérifie que la connexion fonctionne et dans ce cas, on créer le fichier de configuration.

Dans le code est utilisé le tableau $fields sensé contenir les informations envoyé par le formulaire (et préalablement contrôlé)

<?php
/*...traitement du formulaire posté retournant le tableau $fields...*/
//nom du fichier à créer.
$filename = 'config.db.php';
//creation du fichier si il n'existe pas et ouverture en écriture
$conf_file = fopen($filename, 'w');
//on écrit dans le fichier ligne par ligne
fwrite($conf_file, '<?php' . "\r\n");
fwrite($conf_file, 'define("DB_HOST","' . $fields['host'] . '");' . "\r\n");
fwrite($conf_file, 'define("DB_USERNAME","' . $fields['username'] . '");' . "\r\n");
fwrite($conf_file, 'define("DB_PASSWORD","' . $fields['password'] . '");' . "\r\n");
fwrite($conf_file, 'define("DB_NAME","' . $fields['name'] . '");' . "\r\n");
//fermeture du fichier
fclose($conf_file);

Snippet PHP : Générer une chaine aléatoirement

Exemple d’une fonction permettant de générer une chaine aléatoire, avec le nombre de caractères et les caractères utilisés paramétrable.

On imagine cette fonction dans une class « Misc » qui pourrait contenir d’autre fonctions utilitaires variées.

class Misc {

    /**
     * Générer une chaine aléatoire de $lenght caractères, utilisant les $characters
     */

    public static function randomString($length = 20, $characters = 'abcdefghijklmnopqrstuvwxyz0123456789') {
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }

}

Utilisation :

Misc::randomString();//retourne une chaine du type "8iplqu8fkz4d4ffn83sy"

PHP : Travailler avec les dates

PHP fournit les classe DateTime, DateTimeImmutable et DateInterval qui permettent de travailler et faire des calculs facilement sur les dates

On peux par exemple facilement trouver la date qu’il sera dans X jours de la façon suivante :

$start = new DateTimeImmutable('2017-06-25 09:00');//date de départ (25 jun 2017)
$end = $start->modify('+10 day');//10 jours plus tard
$end->setTime(0,0,0);//on passe l'horaire a 00:00:00
echo $end->format('d/m/Y H:i:s');//affiche : 05/07/2017 09:00:00

On peux aussi connaitre la différence (nombre de jours, mois) entre 2 dates

$start = new DateTimeImmutable('2017-06-25');//date de départ (25 juin 2017)
$end = new DateTimeImmutable('2017-08-31');//date de départ (31 aout 2017)
$interval = $start->diff($end);//on récupère la différence entre ces 2 dates
echo $interval->format('%a jours');//affiche : 67 jours
echo $interval->format('%m mois et %d jours');//affiche : 2 mois et 6 jours

Beaucoup de chose sont possible, ci-dessous on récupère le dernier jour du mois en cours, et le nombre de jours qui nous sépare de cette date

$now = new DateTime();//aujourd'hui
$end = new DateTime($now->format('Y-m-t'));//fin du mois
$interval = $now->diff($end);//on récupére la différence entre ces 2 dates
echo $interval->format('%a jours');//on affiche le nombre de jour entre ajourd'hui et la fin du mois

Pour plus d’informations il suffit de se reporter à la documentation PHP

WordPress : Création d’un plugin permettant d’ajouter un shortcode

Voici ci-dessous le code très simple d’un plugin wordpress.
Celui-ci permet d’utiliser un nouveau shortcode dans le système wordpress.
Dans le cas présent il va simplement afficher la liste des xx derniers utilisateurs inscrit sur le site.

Pour l’exemple le plugin s’appelle « Mon shortcode ». Il suffit de créer le fichier php « mon-shortcode.php » avec le code ci dessous.
La pratique veut que l’on place ce fichier dans un dossier du même nom « mon-shortcode », dossier à placer bien entendu dans le dossier des plugins de wordpress.
La dernière fonction présenté permet d’ajouter une fichier de mise en page et de traitement javascript. Il faut bien sur les ajouter dans ce même dossier pour qu’il soient correctement appelés.

/*
  Plugin Name: Mon shortcode
  Description: Shortcode permettant d'afficher les derniers utilisateurs inscrits. Shortcode à utiliser sur une page : [mon-shortcode nbusers="xx"]
  Version: 0.1
  Author: Numa BORD
 */


class MonShortcode {

    public function __construct() {
        add_shortcode('mon-shortcode', array($this, 'shortcode_mon_shortcode'));
        add_action('wp_enqueue_scripts', array($this, 'mon_shortcode_scripts'));
    }

    /**
     * Fonction de traitement du shortcode, à utiliser comme ci-dessous
     *
     * [mon-shortcode nbusers="xx"]
     */

    public function shortcode_mon_shortcode($atts) {
        //init
        $default = array();
        $default['nbusers'] = 10;
        //controle des parametres passé dans le shortcode
        if (isset($atts['nbusers'])) {
            $atts['nbusers'] = (int) $atts['nbusers'];
        }
        //configuration definis par les parametre par defaut et ceux passé dans le shortcode
        $config = shortcode_atts($default, $atts);
        //
        $list = '<div class="mon-shortcode">';
        $users = get_users(array('number' => $config['nbusers'], 'orderby' => 'registered', 'order' => 'DESC'));
        foreach ($users as $user) {
            $list .= '<div class="single-user">';
            //avatar
            $list .= '<div class="avatar-glob">';
            $list .= get_avatar($user->user_email, 60);
            $list .= '</div>'; //avatar-glob
            $list .= '<div class="info-glob">';
            //pseudo
            $list .= '<div class="title">';
            $list .= $user->display_name;
            $list .= '</div>'; //title
            //date d'inscription
            $list .= '<div class="date">';
            $registrered = new \DateTime($user->user_registered);
            $list .= $registrered->format('d/m/Y H:i:s');
            $list .= '</div>'; //date
            //
            $list .= '</div>'; //info glob
            $list .= '</div>'; //single user
        }
        $list .= '</div>';
        return $list;
    }

    /**
     * Appel des fichiers js/css necessaires (facultatif)
     */

    public function mon_shortcode_scripts() {
        global $post;
        if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'mon-shortcode')) {
            wp_enqueue_style('mon-shortcode-style', plugins_url('/mon-shortcode/style.css'));
            wp_enqueue_script('mon-shortcode-js', plugins_url('/mon-shortcode/script.js'), array('jquery'));
        }
    }

}

new MonShortcode();

Avec quelques améliorations, on peux obtenir un shortcode permettant d’afficher les derniers inscrits en popup comme sur cette page de démonstration

Symfony : modifier les champs d’un formulaire en fonction de son objet ou d’options

Depuis le controller, c’est un appel du formulaire classique, on ajoute juste les éventuelles options si besoins

$form = $this->createForm(ExampleFormType::class, $example, array('custom' => true));

Dans « ExampleFormType » définition de l’option « custom » et utilisation des « Form Events » pour adapter les champs

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class ExampleFormType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use($options) {
            $example = $event->getData(); //recuperation de l'objet sur lequel le formulaire se base
            $form = $event->getForm(); //recuperation du formulaire
            //en fonction du type de l'utilisateur les champs sont différents
            if ($example->getStatus() == 1 && $options['custom']) {
                $form->add('firstName', null, array('label' => 'Prénom'));
                //....
            } else {
                $form->add('lastName', null, array('label' => 'Nom'));
                //....
            }
        });
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Example',
            'custom' => false
        ));
    }

}

Savoir si un champs est définis dans twig

{% if form.firstName is defined %}
    {{form_row(form.firstName)}}
{% endif %}