10.11 El Capitan Blocage en suivant tutoriel pour exécuter un fichier .php

stesz

Membre actif
7 Mars 2006
119
5
48
Salut tout le monde,

Je ne sais pas si je suis au bon endroit pour ma question mais ça me paraissait le moins illogique...
Je bloque dans un tutoriel qui consiste à extraire mes données personnelles de Facebook pour les transformer en fichier .gdf, afin d'ouvrir ce fichier dans l'application Gephi qui sert à construire des sociogrammes (schémas du réseau social).
Le tuto complet : http://datascholars.com/post/2013/03/10/facebook_gdf/
Je bloque à cette étape du tuto :
"
For those that don't want to program this themselves (or can't program this themselves) I have included a command line PHP program that does all this for you. It is called "fb_socialnetwork_1.php". "

--> Je télécharge le fichier : "fb_socialnetwork_1.php"

"You run it from the command line with a command like: php fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
An example of how the "fb_socialnetwork_1.php" PHP script is run from the command line to create a GDF file. Running it this way will create a GDF file called "fbsn_1.gdf". Note that this PHP script is NOT a meant to be run as (part of) a web-application; this is a command-line PHP script, and it needs to be run as such. NOTE that (the value for) your access token will be different."

--> je reproduis la ligne de code dans le Terminal (en mettant mon n° "access-token" à la place de AxR7oXeAAcEoAe4eeW9zzB2Wb), et là Terminal me met : "
Could not open input file: fb_socialnetwork_1.php"

Je ne sais pas si ce qu'il fallait faire était de lancer ça dans Terminal ou pas, quelqu'un a une idée ???
Merci d'avance...
Stesz

Sinon pour info, quand j'ouvre le fichier "fb_socialnetwork_1.php" avec TextEdit, ça donne ça :
<?php

/*

Copyright (c) 2013 Charles Iliya Krempeaux

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

*/php fb_socialnetwork_1.php --access_token=EAACEdEose0cBAB4dimaQsOS93YpOZBkmr8ZAZCymVmkXRbEskxNBGZAjAUCsbCwPLrDKEWUTaDkTndrGxzdgc4MWpeO6ugglTMLcnxsDZCGjsHU9yGuDqbzjn1Ymxy2rmspsLpmXokeBPZBGxWeG2tgvpjqMmtBbC3Ki7kc6ZCiOfmhPyiTqX9Lzp5cXmGZBWw4ZD


// References: http://datascholars.com/post/2013/03/10/facebook_gdf/
// http://changelog.ca/log/2013/03/10/facebook_gdf


// Author Info:
//
// Name: Charles Iliya Krempeaux
// E-mail: [email protected]
// Homepage: http://changelog.ca/
// Blog: http://changelog.ca/log
// Card: http://reiver.ca/
// Twitter: http://twitter.com/reiver
//



//
// M A I N
//

// Deal with args.
if ( !is_array($argv) ) {
/////////// EXIT
exit(1);
}

$args = Args::getInstance();

//DEBUG
//echo 'ARGS: ', var_export($args), "\n";


// See if user called --help switch.
if ( $args->getSwitch('help', false) || 1 == count($argv) ) {
echo_help();
/////////// EXIT
exit(0);
}



// Get access_token, via the user supplied --access_token switch.
$access_token = $args->getSwitch('access_token');

if ( !is_string($access_token) ) {
// Error.
fwrite(STDERR, 'ERROR: Missing Facebook access token. Use --access_token switch.'."\n");
echo_help();
/////////// EXIT
exit(1);
}

//DEBUG
if ( true === $args->getSwitch('verbose', false) || true === $args->getSwitch('debug', false) ) {
echo 'Access Token: ', $access_token, "\n";
}


// Get person's information. (The *person* is whomever the Facebook access token is for.)
$me_datum = fb_graph_get_decoded_json('/me', $access_token, $args->getSwitch('verbose', false), $args->getSwitch('debug', false));


// Get person's list of friends.
$friends_data = array();

$friends_result = fb_graph_get_decoded_json('/me/friends', $access_token, $args->getSwitch('verbose', false), $args->getSwitch('debug', false));

if ( isset($friends_result['data']) && is_array($friends_result['data']) && !empty($friends_result['data']) ) {
$friends_data = array_merge($friends_data, $friends_result['data']);
}

//DEBUG
if ( true === $args->getSwitch('verbose', false) || true === $args->getSwitch('debug', false) ) {
echo 'Paging Next URL: ', var_export(@$friends_result['paging']['next'],true), "\n";
}

if ( isset($friends_result['paging']) && is_array($friends_result['paging']) ) {
if ( isset($friends_result['paging']['next']) && is_string($friends_result['paging']['next']) ) {
$i=0;
do {
$next_href = $friends_result['paging']['next'];

//DEBUG
if ( true === $args->getSwitch('verbose', false) || true === $args->getSwitch('debug', false) ) {
echo '[LOOP][',$i,']: Next (Paging Next) URL: ', var_export($next_href,true), "\n";
}

$friends_result = file_get_decoded_json($next_href, $args->getSwitch('verbose', false), $args->getSwitch('debug', false));

//DEBUG
if ( true === $args->getSwitch('debug', false) ) {
echo '[LOOP][',$i,']: Results: ', var_export($friends_result,true), "\n";
}

if ( $friends_result['data'] ) {

//DEBUG
if ( true === $args->getSwitch('verbose', false) || true === $args->getSwitch('debug', false) ) {
echo '[LOOP][',$i,']: Num Data Merged: ', count($friends_result['data']), "\n";
}

$friends_data = array_merge($friends_data, $friends_result['data']);
} else {

//DEBUG
if ( true === $args->getSwitch('verbose', false) || true === $args->getSwitch('debug', false) ) {
echo '[LOOP][',$i,']: No Data To Merge.', "\n";
}
}

$i++;
} while ( isset($friends_result['data']) && is_array($friends_result['data']) && !empty($friends_result['data']) );
}
}


// Figure out the output file name.
$output_fn = $args->getSwitch('output', 'fbsn_1.gdf');

//DEBUG
if ( true === $args->getSwitch('verbose', false) || true === $args->getSwitch('debug', false) ) {
echo 'Output File Name: ', $output_fn, "\n";
}


// Output.
//DEBUG
if ( true === $args->getSwitch('debug', false) ) {
echo 'OUTPUT to ', var_export($output_fn,true) ,'....', "\n\n";
}

$output_fd = fopen($output_fn, 'w');

$s = "nodedef> name,label\n";
fwrite($output_fd, $s);
//DEBUG
if ( true === $args->getSwitch('debug', false) ) {
echo $s;
}

$s = 'n'. $me_datum['id'] .','.'"'. addslashes($me_datum['name']) ."\"\n";
fwrite($output_fd, $s);
//DEBUG
if ( true === $args->getSwitch('debug', false) ) {
echo $s;
}


if ( is_array($friends_data) && !empty($friends_data) ) {
foreach ($friends_data AS $k => $friend_datum) {

$s = 'n'. $friend_datum['id'] .','.'"'. addslashes($friend_datum['name']) ."\"\n";
fwrite($output_fd, $s);
//DEBUG
if ( true === $args->getSwitch('debug', false) ) {
echo $s;
}


} // foreach
}


$s = "edgedef> node1,node2\n";
fwrite($output_fd, $s);
//DEBUG
if ( true === $args->getSwitch('debug', false) ) {
echo $s;
}

if ( is_array($friends_data) && !empty($friends_data) ) {
foreach ($friends_data AS $k => $friend_datum) {

$s = 'n'. $me_datum['id'] .',n'. $friend_datum['id'] ."\n";
fwrite($output_fd, $s);
//DEBUG
if ( true === $args->getSwitch('debug', false) ) {
echo $s;
}

} // foreach
}


fclose($output_fd);


// Exit.
exit(0);


// P R O C E D U R E S //////////////////////////////////////////////////////////////////////////////////////////////////////
function fb_graph_get_decoded_json($path, $access_token, $verbose=false, $debugging=false)
{
$api_href = 'https://graph.facebook.com/';
$api_href .= $path;
if ( false === strpos($api_href, '?') ) {
$api_href .= '?';
} else {
$api_href .= '&';
}
$api_href .= 'access_token=';
$api_href .= urlencode($access_token);

//DEBUG
if ( $verbose || $debugging ) {
echo 'API HRef: ', $api_href, "\n";
}


return file_get_decoded_json($api_href, $verbose, $debugging);
}
//-------------------------------------------------------------------------------------------------------------------------//
function file_get_decoded_json($href, $verbose=false, $debugging=false)
{
$json = file_get_contents($href);

//DEBUG
if ( $debugging ) {
echo 'JSON: ', $json, "\n";
}



$result = json_decode($json, true);

//DEBUG
if ( $debugging ) {
echo 'Result: ', var_export($result,true), "\n";
}


return $result;
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=//

function echo_help()
{
global $argv;

$filename = $argv[0];
$pos = strrpos($filename, '/');
if ( false !== $pos ) {
$filename = substr($filename, 1+$pos);
}

echo "\n"
, 'Exports your Facebook social network to a GDF file.', "\n"
, "\n"
, "\n", 'switches:'
, "\n"
, "\t", '--access_token The Facebook access token.', "\n"
, "\t", '--help Shows this message.', "\n"
, "\t", '--output The name of the output GDF file. (Default: "fbsn_1.gdf").', "\n"
, "\t", '--verbose Shows progress messages.', "\n"
, "\t", '--debug Shows debug messages.', "\n"
, "\n"
, "\n", 'example:'
, "\n"
, "\t", 'php ', $filename, ' --access_token=12345AbCdE', "\n"
, "\n"
, "\n"
;
}

////////////////////////////////////////////////////////////////////////////////////////////////////// P R O C E D U R E S //



// C L A S S E S ////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Args
{
private $argv = null;
private $switches = array();
private $params = array();


public static function parseArgv($argv, $skip_item_zero = true)
{
// Initialize.
$switches = array();
$params = array();


// See if should skip first item. (This is because $argv[0] is the script file name, in general.)
if ( $skip_item_zero && isset($argv[0]) ) {
unset($argv[0]);
}


// Parse.
if ( is_array($argv) && !empty($argv) ) {
foreach ($argv AS $k => $v) {

$strlen = strlen($v);

if ( 2 < $strlen && '-' == $v{0} && '-' == $v{1} ) {
$pos_equal = strpos($v, '=');

if ( false === $pos_equal ) {
$name = substr($v, 2);

$switches[$name] = true;
} else {
$name = substr($v, 2, ($pos_equal-2) );
$value = substr($v, 1+$pos_equal);

$switches[$name] = $value;
}
} elseif ( '-' == $v{0} ) {
$name = substr($v, 1);

$switches[$name] = true;
} else {
$params[] = $v;
}

} // foreach
}


// Return.
$result = array();
$result['switches'] = $switches;
$result['params'] = $params;

return $result;
}


private function __construct($argv)
{
$this->init($argv);
}

private function init($argv)
{
// Set field(s).
$this->argv = $argv;


// Parse argv.
if ( is_array($this->argv) && !empty($this->argv) ) {

$parse_results = self::parseArgv($this->argv);
if ( is_array($parse_results) && !empty($parse_results) ) {

if ( isset($parse_results['switches']) ) {
$this->switches = $parse_results['switches'];
}
if ( isset($parse_results['params']) ) {
$this->params = $parse_results['params'];
}

}

}
}



public static function getInstance()
{
// Access globals.
global $argv;


// Make sure we are in an environment where we have the $argv global.
if ( !is_array($argv) ) {
// Error.
return null;
}


// Get instance.
static $singleton = null;

if ( ! $singleton instanceof self ) {

$singleton = new self($argv);
}


// Return.
return $singleton;
}



public function getParams()
{
return $this->params;
}

public function getSwitches()
{
return $this->switches;
}

public function getArgv()
{
return $this->argv;
}


public function getSwitch($name, $default = null)
{
// Initialize.
$result = $default;


//
if ( isset( $this->switches[$name] ) ) {
$result = $this->switches[$name];
}


// Return.
return $result;
}

}
//////////////////////////////////////////////////////////////////////////////////////////////////////////// C L A S S E S //
 
Salut stesz

Pour appliquer la commande modèle proposée par l'auteur du script :
Bloc de code:
php fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
tu ne dois pas te contenter de remplacer l'identifiant final AxR7oXeAAcEoAe4eeW9zzB2Wb par le tien propre en ayant copié-collé à l'identique tout ce qui précède comme si c'était une constante absolue ; tu dois mentionner le chemin au fichier script fb_socialnetwork_1.php afin que l'utilitaire php que tu appelles en premier puisse le trouver et en exécuter les instructions.

Car si tu laisses fb_socialnetwork_1.php tel quel > l'utilitaire php va chercher à l'emplacement-racine de ton dossier de compte et nulle part ailleurs sans trouver le fichier-script > et te retourne donc un :
Bloc de code:
Could not open input file: fb_socialnetwork_1.php
(impossible d'ouvrir le fichier-source : fb_socialnetwork_1.php - pour la raison qu'il n'a pas été trouvé).

Si l'utilitaire php (et c'est valable pour toute autre commande du «Terminal») cherche dans l'espace-racine de ton dossier de compte > pour tout objet mentionné tout court à un utilitaire sans chemin préalable > c'est que, si tu scrutes l'invite du commande du «Terminal» du type :
Bloc de code:
MacBook Pro:~ stesz$
tu t'aperçois que ton nom de compte stesz est précédé par ~ (esperluette) désignant en mode symbolique le dossier de compte /Users/stesz en chemin absolu. Lorsque tu ouvres une fenêtre du «Terminal» dans macOS > tu es en en effet à la fois loggé automatiquement en tant que stesz (= username) et à la localisation par défaut ~ (l'espace-racine de ton dossier de compte en chemin symbolique).

Tu déduis de ces aimables considérations que, si ton fichier fb_socialnetwork_1.php réside après décompression de l'archive sur ton Bureau > tu dois mentionner avant l'intitulé du fichier le chemin qui y conduit > ce qui donnerait une commande :
Bloc de code:
php Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
(où Desktop = le Bureau peut être parachuté directement > étant un des objets présents immédiatement dans l'espace désigné par ~ : ton dossier de compte). Sinon, une commande :
Bloc de code:
php ~/Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
serait également valide ; ou encore si tu préférais :
Bloc de code:
php ${HOME}/Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
et enfin > la commande en chemin absolu serait :
Bloc de code:
php /Users/stesz/Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb

----------

Voici dans la pratique comment tu peux t'y prendre pour saisir ta commande :

- tu saisis d'abord seulement dans la fenêtre du «Terminal» :
Bloc de code:
php
et tu sautes un espace avec la barre d'espacement du clavier.

- tu fais directement un glisser-déposer au pointeur de ton fichier fb_socialnetwork_1.php (où qu'il se trouve - supposons le Bureau) > dans la fenêtre du «Terminal» > ce qui renseigne automatiquement le chemin absolu au fichier et son intitulé --> du type :
Bloc de code:
php /Users/Desktop/fb_socialnetwork_1.php

- un saut d'espace a été généré automatiquement en sortie de glisser-déposer > tu complètes alors à la main la commande par : --access_token= > ce qui donne :
Bloc de code:
php /Users/Desktop/fb_socialnetwork_1.php --access_token=

- il ne te reste plus qu'à saisir à la main ou en copier-coller les 25 caractères alphanumériques xxxxxxxxxxxxxxxxxxxxxxxxx de l'identifiant > ce qui donne au total une commande de la forme
Bloc de code:
php /Users/Desktop/fb_socialnetwork_1.php --access_token=XXXXXXXXXXXXXXXXXXXXXXXXX

=> tu n'as plus qu'à presser la touche ↩︎ (= "Entrée") du clavier pour valider. Je ne garantis absolument pas que le script va faire ce que tu attends, bien sûr.
 
Dernière édition par un modérateur:
Salut stesz

Pour appliquer la commande modèle proposée par l'auteur du script :
Bloc de code:
php fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
tu ne dois pas te contenter de remplacer l'identifiant final AxR7oXeAAcEoAe4eeW9zzB2Wb par le tien propre en ayant copié-collé à l'identique tout ce qui précède comme si c'était une constante absolue ; tu dois mentionner le chemin au fichier script fb_socialnetwork_1.php afin que l'utilitaire php que tu appelles en premier puisse le trouver et en exécuter les instructions.

Car si tu laisses fb_socialnetwork_1.php tel quel > l'utilitaire php va chercher à l'emplacement-racine de ton dossier de compte et nulle part ailleurs sans trouver le fichier-script > et te retourne donc un :
Bloc de code:
Could not open input file: fb_socialnetwork_1.php
(impossible d'ouvrir le fichier-source : fb_socialnetwork_1.php - pour la raison qu'il n'a pas été trouvé).

Si l'utilitaire php (et c'est valable pour toute autre commande du «Terminal») cherche dans l'espace-racine de ton dossier de compte > pour tout objet mentionné tout court à un utilitaire sans chemin préalable > c'est que, si tu scrutes l'invite du commande du «Terminal» du type :
Bloc de code:
MacBook Pro:~ stesz$
tu t'aperçois que ton nom de compte stesz est précédé par ~ (esperluette) désignant en mode symbolique le dossier de compte /Users/stesz en chemin absolu. Lorsque tu ouvres une fenêtre du «Terminal» dans macOS > tu es en en effet à la fois loggé automatiquement en tant que stesz (= username) et à la localisation par défaut ~ (l'espace-racine de ton dossier de compte en chemin symbolique).

Tu déduis de ces aimables considérations que, si ton fichier fb_socialnetwork_1.php réside après décompression de l'archive sur ton Bureau > tu dois mentionner avant l'intitulé du fichier le chemin qui y conduit > ce qui donnerait une commande :
Bloc de code:
php Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
(où Desktop = le Bureau peut être parachuté directement > étant un des objets présents immédiatement dans l'espace désigné par ~ : ton dossier de compte). Sinon, une commande :
Bloc de code:
php ~/Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
serait également valide ; ou encore si tu préférais :
Bloc de code:
php ${HOME}/Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb
et enfin > la commande en chemin absolu serait :
Bloc de code:
php /Users/stesz/Desktop/fb_socialnetwork_1.php --access_token=AxR7oXeAAcEoAe4eeW9zzB2Wb

----------

Voici dans la pratique comment tu peux t'y prendre pour saisir ta commande :

- tu saisis d'abord seulement dans la fenêtre du «Terminal» :
Bloc de code:
php
et tu sautes un espace avec la barre d'espacement du clavier.

- tu fais directement un glisser-déposer au pointeur de ton fichier fb_socialnetwork_1.php (où qu'il se trouve - supposons le Bureau) > dans la fenêtre du «Terminal» > ce qui renseigne automatiquement le chemin absolu au fichier et son intitulé --> du type :
Bloc de code:
php /Users/Desktop/fb_socialnetwork_1.php

- un saut d'espace a été généré automatiquement en sortie de glisser-déposer > tu complètes alors à la main la commande par : --access_token= > ce qui donne :
Bloc de code:
php /Users/Desktop/fb_socialnetwork_1.php --access_token=

- il ne te reste plus qu'à saisir à la main ou en copier-coller les 25 caractères alphanumériques xxxxxxxxxxxxxxxxxxxxxxxxx de l'identifiant > ce qui donne au total une commande de la forme
Bloc de code:
php /Users/Desktop/fb_socialnetwork_1.php --access_token=XXXXXXXXXXXXXXXXXXXXXXXXX

=> tu n'as plus qu'à presser la touche ↩︎ (= "Entrée") du clavier pour valider. Je ne garantis absolument pas que le script va faire ce que tu attends, bien sûr.


Un GRAND merci pour toutes ces explications théoriques et pratiques dans le moindre détail !!!
J'ai suivi scrupuleusement ta ligne de commande (le token access est plus long que 25 caractères...), mais ça m'a donné un message d'erreur :

macbook-pro-de-stephane:~ Stesz$ php /Users/Stesz/Desktop/fb_socialnetwork_1.php --access_token=EAACEdEose0cBAJCupFxVdBeFbxN0gzkNNPkpzaTp6TUsJcZCZCz5GZB8Sx64maZBJmgbYzUIZCNZACDYLqmIX0q6sZAzKVdoYXGH8j31eqmg7eFhkB5PrmsApdofr0Vysxu72sjZCydcPeq6PcquDBcZAQmlnmcUDZCw8fCt9ogEbGZCnGA78znBhsZAiS8YMv0mWDwZD


Parse error: parse error in /Users/Stesz/Desktop/fb_socialnetwork_1.php on line 28

macbook-pro-de-stephane:~ Stesz$

Une idée ?
 
Un GRAND merci pour toutes ces explications théoriques et pratiques dans le moindre détail !!!
J'ai suivi scrupuleusement ta ligne de commande (le token access est plus long que 25 caractères...), mais ça m'a donné un message d'erreur :

macbook-pro-de-stephane:~ Stesz$ php /Users/Stesz/Desktop/fb_socialnetwork_1.php --access_token=EAACEdEose0cBAJCupFxVdBeFbxN0gzkNNPkpzaTp6TUsJcZCZCz5GZB8Sx64maZBJmgbYzUIZCNZACDYLqmIX0q6sZAzKVdoYXGH8j31eqmg7eFhkB5PrmsApdofr0Vysxu72sjZCydcPeq6PcquDBcZAQmlnmcUDZCw8fCt9ogEbGZCnGA78znBhsZAiS8YMv0mWDwZD


Parse error: parse error in /Users/Stesz/Desktop/fb_socialnetwork_1.php on line 28

macbook-pro-de-stephane:~ Stesz$

Une idée ?

En réessayant ça m'a bien généré le fichier voulu, donc ça a l'air bon, merci encore. Maintenant le contenu du fichier ne va pas dans l'application (il n'y a que moi et pas mes contacts dans la base de donnée), mais ce n'est plus le même problème... je vois ça tout seul et j'appellerai à l'aide si je bloque trop longtemps !
vraiment merci pour le temps passé à me dépanner !
Stesz
 
vraiment merci pour le temps passé à me dépanner !

De rien. Ce qui m'a pris un peu de temps > ça n'a pas été de trouver où gîtait le problème > seulement de tourner en Français une petite explication touchant le loggement automatique de l'opérateur du shell à la racine de son dossier de compte > et la nécessité d'adapter l'adresse des objets qu'on désigne à l'utilitaire appelé en départ de commande (php ici).

Ce qui ne m'a pas empêché de commettre un lapsus en chemin : j'ai dit « erperluette » (&) à la place de « tilde » (~) - ayant le soir tendance à confondre ce que je distingue dans l'aube...
 
Dernière édition par un modérateur: