Pour fonctionner correctement vous devez exposer un service nommé cache
dans l'injection de dépendance de phalcon.
Ce service doit, au minimum exposer 2 méthodes publiques: hIncrBy
et hScan
. Ces méthodes sont natives dans la classe
\Redis
(voir hIncrBy
et hScan
).
En utilisant la classe \Phalcon\Cache\Backend\Redis
vous pouvez les définir comme suit :
namespace App;
class Redis extends \Phalcon\Cache\Backend\Redis {
/**
* @param string $key
* @param string $hashKey
* @param int $value
* @return int
*/
public function hIncrBy($key, $hashKey, $value)
{
return $this->_redis->hIncrBy($key, $hashKey, $value);
}
/**
* @param string $key
* @param string $pattern
* @param int $count
* @return array
*/
public function hScan($key, &$iterator = null, $pattern = null, $count = 0)
{
$results = [];
$this->_redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY);
do {
$arr_keys = $this->_getRedis()->hScan($key, $iterator, $pattern, $count);
if (!$arr_keys) {
break;
}
foreach ($arr_keys as $str_field => $str_value) {
$results[$str_field] = $str_value;
}
} while ($arr_keys);
return $results;
}
}
Versions :
- 1.X : Phalcon 3
- 2.X : Phalcon 4
- 3.X : Phalcon 5
-
Ajouter la dépendance
Il faut rajouter le repository git dans votre configuration Composer
{ "repositories": [ { "type": "vcs", "url": "https://github.com/lemonde/phalcon-abtest.git" } ], }
composer require lemonde/phalcon-abtest
-
Ajouter les configurations PHP
-
Ajouter le listener des évènements
dispatch
:$eventManager->attach('dispatch', new \ABTesting\Plugin\AnnotationListener());
-
Ajouter l'extension volt:
$volt->getCompiler()->addExtension(new \ABTesting\Volt\ABTestingExtension());
-
Ajouter le contrôleur au routing:
# il faut forcément un paramètre nommé testName # et un autre nommé winner $router->add('/_my_ab_redirection/{testName:[a-zA-Z0-9\_]+}/{winner:[a-zA-Z0-9\_]+}', ['controller' => 'ab_test', 'action' => 'count', 'namespace' => 'ABTesting\Controller'])->setName('ab_test_redirect');
-
Spécifier le device du client, deux méthodes :
- en le faisant manuellement depuis le contrôleur
public function beforeExecuteRoute(Dispatcher $dispatcher) { ABTestEngine::getInstance()->setDevice('desktop'); }
- ou via un service nommé
phalcon-abtest.device_provider
qui implémente l'interface DeviceProviderInterface.php
$di->setShared('phalcon-abtest.device_provider', function () { return new class () extends ABTesting\DeviceProvider\DeviceProviderInterface { public function getDevice() { return 'desktop'; } } });
Vous pouvez utiliser mobiledetect/mobiledetectlib via le service device_provider:
$di->setShared('phalcon-abtest.device_provider', function () { return new class () extends ABTesting\DeviceProvider\DeviceProviderInterface { public function getDevice() { $detect = new MobileDetect(); if ($detect->isTablet()) { return 'tablet'; } elseif ($detect->isMobile()) { return 'mobile' } return 'desktop'; } } });
-
(Optionnel) Ajouter le reporting au routing:
$router->add('/_my_ab_dashboard', ['controller' => 'ab_test', 'action' => 'report', 'namespace' => 'ABTesting\Controller'])->setName('ab_test_report');
-
-
Ajouter un service nommé
phalcon-abtest.tests
(utilisant\Phalcon\Config
) renvoyant la configuration des tests A/B$di->setShared('phalcon-abtest.tests', function () { return new Phalcon\Config([ 'home_text_content' => [ 'default' => 'home_test_A', 'variants' => [ 'home_test_A' => 'something', 'home_test_B' => 'some other thing', ], 'chooser' => [\ABTesting\Chooser\PercentChooser::class] ], 'home_link_url' => [ 'default' => 'https://www.google.com', 'variants' => [ 'home_test_A' => 'https://www.google.fr', 'home_test_B' => 'https://www.google.be', ], 'chooser' => [\ABTesting\Chooser\PercentChooser::class] ], 'home_partial' => [ 'default' => 'path/to/default', 'variants' => [ 'home_test_A' => 'path/to/A', 'home_test_B' => 'path/to/B', ], 'chooser' => [\ABTesting\Chooser\PercentChooser::class] ], ]); });
Plus d'info ici
-
Déclarer les actions soumises aux tests A/B avec l'annotation
@AbTesting('home_text_content')
-
Utiliser les fonctions volt pour afficher les élements souhaités, par exemple :
-
pour tester un wording :
<a {{ ab_test_href('home_text_content', 'https://www.google.com') }}> {{ ab_test_result('home_text_content') }} </a>
-
pour tester un lien défini comme test :
<a {{ ab_test_href('home_link_url', ab_test_result('home_link_url')) }}> Lien </a>
-
pour tester 2 formats :
{# home.volt #} {{ partial('path/to/specific/partial/dir/' ~ ab_test_result('home_partial')) }}
{# path/to/specific/partial/dir/path/to/A.volt #} <!-- your content --> <a {{ ab_test_href('home_partial', 'https://example.org/link/for/A') }}> Lien </a>
{# path/to/specific/partial/dir/path/to/B.volt #} <!-- your content --> <a {{ ab_test_href('home_partial', 'https://example.org/link/for/B') }}> Lien </a>
{# path/to/specific/partial/dir/path/to/default.volt #} <!-- your content --> <a href="https://example.org"> Lien </a>
-
Pour configurer vos tests A/B, tout se fait dans une conf en tableau sous la forme :
'nom_du_test' => [ # Définition du test
'variants' => [ # Définition des résultats possibles
'varianteA' => 'une valeur',
'varianteB' => 'une autre valeur',
'varianteC' => 1337,
],
'default' => 'valeur par défaut', # Valeur par défaut du résultat (s'il n'y a pas eu de bataille par exemple)
'chooser' => ['\La\Classe\Du\Chooser', 'les', 'arguments', 'du', 'constructeur']
]
- Les variantes peuvent être de n'importe quel type compatible avec
var_export
. - Le chooser doit être une classe qui implémente
ABTesting\Chooser\ChooserInterface
- Vous pouvez écouter sur les évenements de l'
ABTesting\Engine
:abtest:beforeBattle
: avant le calcul d'un testabtest:afterBattle
: après le calcul d'un testabtest:beforePrint
: avant l'affichage du résultat via voltabtest:beforeClick
: avant la redirection via le lien du test
- Build l'image de test en local
docker build --no-cache -t phalcon-abtest .
- Lancer le conteneur et ouvrir une session bash
docker run --rm -it -v "$PWD":/app phalcon-abtest
- installer les packages PHP
composer install
- Exécuter les tests
./vendor/bin/phpunit --no-coverage