[PHP] Note : substr et UTF-8

Substr vous fait chier avec les caractères unicode ?

Genre

substr('août', 0, 3)
substr('février', 0, 3)

Vous sortent respectivement ao� et ?

C’est parce que les caractères Unicode font 1 octet partout, sauf là ils ne font pas partie des caractères de base (ascii). Le « fé » correspond donc à 1+2 = 3 octets et le « aoû » correspond à 4 octets, où en fait 3 octets correspondent à 2,5 lettres, d’où l’erreur.

Solution : utiliser la version « multi-bytes » (mb_) des fonctions de traitement de texte de PHP. Il faut déclarer un peu plus tôt dans le code :

mb_internal_encoding('UTF-8');

Puis utiliser mb_substr(), qui s’utilise exactement comme substr() :

mb_substr('août', 0, 3)
mb_substr('février', 0, 3)

Vous sortiront respectivement aoû et fév.

Autrement, si mb_encoding n’est pas disponible, vous pouvez toujours transformer le texte en version non accentuée avec ça (le $text doit être converti de UTF8 en ISO avant) :

preg_replace('#&(.)(acute|grave|circ|uml|cedil|tilde|ring|slash|caron);#', '$1', $text)

.

Et le tour est joué plus de problèmes d’encodage :D

PHP 5.6 est désormais disponible sur les Pages Perso Free

Cool ! La dernière version datait de 2005 je crois, il était temps.

Note : PHP upload de fichiers

"post_max_size" doit être supérieur à "upload_max_filesize" pour envoyer des fichiers.

La taille de "post" contient en effet la taille des fichiers ET les autres données (dans les champs textes par exemple), du même formulaire.

C’est logique, mais ça m’était sorti de la tête.

phanan/htaccess · GitHub

Un bon mémo .htaccess à garder sous le coude.

(via)

Note : buffer, ob_flush(), zlib

Dites les gens, est-ce que quelqu’un a une idée d’où peuvent venir des problèmes avec AJAX ?

J’essaie d’envoyer les données au fur et à mesure où elles sont générées par PHP, mais en ligne ça ne marche tout simplement pas.
Ça ne vient pas de mon navigateur : en local, le script marche très bien (installation par défaut de PHP/Apache).

— J’ai essayé comme suggéré sur les forums de désactiver ZLib, Deflate, que ce soit via ini_set() ou dans un .htaccess,
— j’ai mis des ob_start(), ob_flush() en plus de flush(), ça ne marche pas (où que je mette tout ça).
— J’ai désactivé mon VPN, ça ne marche pas.
— J’ai testé dans un autre navigateur, changé les entêtes pour refuser les réponses en deflate, changé ma version de PHP… rien ne marche non plus.

Le seul truc qui marche (mal) c’est de faire un str_pad(' ', 5000), ce qui permet de générer 5ko de données histoire de faire déborder les buffers et forcer un envoie au navigateur. Mais ceci est du bricolage et je n’aime pas ça : je n’utilise pas AJAX pour générer des données en trop pour que ça marche, mais justement pour économiser des transferts réseaux inutiles.
ÉDIT : à priori, les buffers seraient d’environ 64ko. :O

Mon hébergeur n’arrive pas à voir non plus.

À mon avis il y a des buffers d’une taille assez importante quelque part ailleurs sur le serveur ou le réseau. Mais où et comment les changer ?

ÉDIT : merci à iM@n, mais c’est loupé : cette astuce n’a pas marché chez moi : http://sebsauvage.net/links/?xCmoQw :/

Les joies du code - quand je check mes e-mails pendant les vacances

Euh, non ça veut dire qu’il a été fait en Côte d’Ivoire (ivoire, élephpant… tout ça… je suis déjà dehors oui).

[PHP] Faire plusieurs requêtes HTTP simultanées avec cURL - Le Hollandais Volant

Heu bon.

Mon astuce fonctionne sous Linux Mint 17 (ou Ubuntu 14.04), mais j’avais trouvé un truc un peu plus complexe dans la doc, avec des tests un peu plus poussés que le simple sleep(), qui ne marche pas du tout (proc à 100%, rien de téléchargé et un fatal_error de timeout après 30 secondes).

Dans LM17, j’ai PHP 5.5.9 et cUrl 7.35.0.

M’enfin…

Note : PHP curl-multi

Comme je l’ai indiqué sur mon article dédié, Curl Multi est la solution en PHP pour faire plein de requêtes HTTP simultanées.

Je viens de voir que si on fait 150 requêtes, il y en a toujours certaines qui plantent et ne renvoient pas de réponse (code de retour 0 : pas de requête).
Du coup, il convient peut-être mieux de faire une boucle et de faire les requêtes 20 par 20 ou 50 par 50.

Bon à savoir~

PHP CURL Error - curl: (56) Recv failure: Connection reset by peer - Stack Overflow

Oh putain, ça me gave parfois ça aussi…

Perdre une soirée à cause de conneries de ce genre. Rhaaaaa.
Surtout que c’est PHP lui même qui décone : le trim() avant de foutre ça dans le curl() ne devrait même pas être nécessaire : je le fais déjà avant de stocker l’URL dans la BDD.
(car oui, l’ajout d’un trim() me résout une bonne partie des problèmes.)

Et désactiver le VPN fait aussi des miracles (visiblement Apache/PHP/Curl et tout ça n’aiment pas trop les proxys et les VPN).

Ça expliquait pourquoi mon script fonctionnait très bien sur mon serveur mais pas bien en local…


Bon bonne nuit…

TechnoSophos: PHP and curl_multi_exec

Comprendre le casse-tête de curl_multi_exec() qui semble bien bordélique.

Voir aussi : http://www.adrianworlddesign.com/Knowledge-Base/php/Download-content-with-cURL/Doing-curlmultiexec-the-right-way (2)

En fait, la fonction de Curl utilise un drapeau (flag) pour annoncer à PHP qu’il est encore occupé à recevoir des données (alors que les fonctions normales annoncent seulement un « j’ai fini » à PHP quand la fonction est terminée).

Les boucles do/while qu’on retrouve donc tout le temps servent à demander à Curl s’il a terminé ou pas (on lui demande constamment : t’en est où ? t’en est où ? t’en est où ? t’en est où ?). Il n’y a pas d’autres moyens, vu que Curl travaille sous PHP.

Le problème (lien (2)) c’est le do/while est très rapide et PHP fait alors des demandes bien trop vite, ce qui alourdi énormément la charge CPU. L’idée est de ne faire une boucle que si un autre flag est changé, et pour ce flag là, il n’est pas nécessaire de lancer une fonction lourde : on regarde juste le flag.

Perso j’ai plutôt opté pour un usleep(10000), qui dit à PHP d’attendre 10 millisecondes (10'000 µs) entre chaque demande de « t’en est où ? ».
Ça évite d’avoir un do/while dans un if dans un while, après un premier while.

PHP Parallel curl requests - Stack Overflow

\o/

Php et Curl : pour faire des requêtes HTTP parallèles, ce que ne permet pas file_get_contents().
Prenez l’exemple d’ici aussi : http://www.php.net/manual/en/function.curl-multi-init.php

C’est bien plus rapide que de boucler sur plein de file_get_contents(), car ça réduit les temps perdu aux accès réseau.

php - Retrieving RSS feed with tag <content:encoded> - Stack Overflow

Mh…
Voilà une solution bourrin pour récupérer les tags <content:encoded> dans les fichiers RSS : faire un str_replace et transformer le "content:encoded" en "contentencoded".
On récupère alors le contenu via :
$item->contentencoded;

Autrement, si on ne fait ça ça, il faut faire
$item->children('content', true)->encoded;
(alors qu’un tag <content> aurait été $item->content;)

Exemple de flux qui posait problème : http://feeds.feedburner.com/Memebase


@Bronco : du coup j’ai fait un pull-request là : https://github.com/broncowdd/feed2array
[ÉDIT 3 secondes 2/10 plus tard ] : t’es rapide pour merger, dis donc ! :O

Optimizing HTTP headers for ‘ajax’ webapps | Mibbit blog

Ceci aurait pu être une très bonne astuce, mais ça marche pas !

Dans mon lecteur RSS lors de la mise à jour des flux, je veux que le navigateur regarde à quel flux il en est : j’ai 160 flux et la mise à jour, même en réduisant le timeout à 1 seconde (en PHP), ça prend alors 160 secondes, soit 2min40 : l’utilisateur doit savoir combien de temps ça va durer, sinon il risque de croire que la page a plantée, et il recharge la page et re-clique dessus et ça c’est mal au serveur…

Du coup, je fais une requête en Ajax pour récupérer uniquement le nombre de flux déjà traités, sous la forme « 42/160 », toutes les 5 secondes (le nombre est mis dans un fichier à part, pour éviter que PHP se mette en route avec des echo() ou des variables sessions très lourds).
Autrement dit, ça ne sont que 6 ou 7 octets qui m’intéressent.

Problème : le navigateur envoie des entêtes HTTP… qui sont lourde (referer, user-agent, accept-encoding…) le tout dépasse 1000 voire 2000 octets… C’est un peu bête.

Ajax permet de modifier les entêtes, mais certaines sont impossibles à réduire à une chaîne vide ou même à modifie (osef du user-agent sur ces requêtes Ajax !!)

Du coup tant pis pour les headers…

(Oui, je sais que le chargement d’une page n’est pas sale, mais si ça dure 5 minutes, l’utilisateur doit en être informé…)

Using PHP's SimpleXML to display OPML - Recently. A (We)Blog

Et ma version un peu aménagée (simplifiée) :

function displayChildrenRecursive($xmlObj) {
// si c’est un sous dossier avec d’autres flux à l’intérieur : note le nom du dossier
$folder = $xmlObj->attributes()->text;
foreach($xmlObj->children() as $child) {
if (isset($child['xmlUrl'])) {
echo "\t".'<li><a href="'.htmlentities($child['xmlUrl']).'">'.htmlentities($child['text']).'</a> - ('.$folder.')</li>'."\n";
}
displayChildrenRecursive($child);
}
}
$opmlFile = new SimpleXMLElement($opml_content);
echo '<ul>'."\n";
displayChildrenRecursive($opmlFile->body);
echo '</ul>'."\n";

(SOLUTION) [PHP] [MySQL] Stocker UTF-8 avant MySQL 5.5 (sans utf8mb4) ? - Forums - Olissea.com - Liens en vrac de JeromeJ

Un peu l’équivalent de mon précédent problème en PHP, adapté pour MySQL : stocker et récupérer des caractères unicodes qui sont encodés sur 2, 3, 4 bits, dans un environnement qui ne dispose pas du module MySQL destiné à ça.