SlideShare a Scribd company logo
1 of 68
Download to read offline
Simplifiez-vous les Design
  Patterns avec PHP 5.3
        Hugo Hamon – 12/07/12
Observateur

Dependency Injection

Inversion de Contrôle
Observer
Un sujet, l’objet
observable, émet un signal
à des modules qui jouent
le rôle d’observateurs.
Event Dispatcher
Le Dispatcheur est un objet
qui gère les connexions
entre le sujet observé et ses
observateurs (écouteurs).
# composer.json

{
    "require": {
        "php": ">=5.3.3",
        "symfony/event-dispatcher": "2.1.*"
    }
}
use SymfonyComponentEventDispatcherEvent;
use SymfonyComponentEventDispatcherEventDispatcher;
use AFUPArticleListener;

$dispatcher = new EventDispatcher();

// Déclaration des écouteurs
$listener1 = array(new ArticleListener(), 'onDelete');
$listener2 = array(new ArticleListener(), 'onSave');

// Enregistrement des écouteurs
$dispatcher->addListener('article.delete', $listener1);
$dispatcher->addListener('article.pre_save', $listener2);

// Notification des écouteurs
$dispatcher->dispatch('article.pre_save', new Event());
Mise en Pratique
use AFUPModelArticle;

$article = new Article();
$article->setTitle('AFUP Design Patterns');
$article->setContent('Some **content**');
$article->save();

echo $article->getHtmlContent();
<p>
      Some <strong>content</strong>
</p>
namespace AFUPModel;

use PropelRuntimeConnectionConnectionInterface;
use dflydevmarkdownMarkdownParser;

class Article extends AFUPModelBaseArticle
{
    public function save(ConnectionInterface $con = null)
    {
        $parser = new MarkdownParser();
        $html = $parser->transformMarkdown($this->getContent());
        $this->setHtmlContent($html);

        $ret = parent::save($con);

        $this->updateLuceneIndex();

        return $ret;
    }
}
Le Sujet
   Observé
namespace AFUPModel;

use SymfonyComponentEventDispatcherEventDispatcher;
use AFUPModelBaseArticle as BaseArticle;

class Article extends BaseArticle
{
    private $dispatcher;

    public function setDispatcher(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
}
namespace AFUPModel;

// ...
use PropelRuntimeConnectionConnectionInterface;
use AFUPEventArticleEvent;

class Article extends BaseArticle
{
    // ...
    public function save(ConnectionInterface $con = null)
    {
        $event = new ArticleEvent($this);
        $this->dispatcher->dispatch('article.pre_save', $event);

         $ret = parent::save($con);
         $this->dispatcher->dispatch('article.post_save', $event);

         return $ret;
    }
}
Propager un
   Evénement
namespace AFUPEvent;

use SymfonyComponentEventDispatcherEvent;
use AFUPModelArticle;

class ArticleEvent extends Event
{
    private $article;

    public function __construct(Article $article)
    {
        $this->article = $article;
    }

    public function getArticle()
    {
        return $this->article;
    }
}
Ajouter des
   écouteurs
namespace AFUPListener;

use AFUPEventArticleEvent;
use dflydevmarkdownMarkdownParser;

class ArticleListener
{
    public function onPreSave(ArticleEvent $event)
    {
        $article = $event->getArticle();
        $markdown = $article->getContent();

        $parser = new MarkdownParser();
        $html = $parser->transformMarkdown($markdown);
        $article->setHtmlContent($html);
    }
}
namespace AFUPListener;

use   ZendSearchLuceneDocument;
use   ZendSearchLuceneDocumentField;
use   AFUPEventArticleEvent;
use   AFUPModelArticlePeer;

class LuceneListener
{
    public function onPostSave(ArticleEvent $event)
    {
        $article = $event->getArticle();

          // ...
      }
}
namespace AFUPListener;

// ...
class LuceneListener
{
    public function onPostSave(ArticleEvent $event)
    {
        $article = $event->getArticle();
        $index = ArticlePeer::getLuceneIndex();

        // remove existing entries
        foreach ($index->find('pk:'.$article->getId()) as $hit) {
            $index->delete($hit->id);
        }

        $doc = new Document();
        $doc->addField(Field::Keyword('pk', $article->getId()));
        $doc->addField(Field::UnStored('title', $article->getTitle()));
        $doc->addField(Field::UnStored('content', $article->getContent()));

        $index->addDocument($doc);
        $index->commit();
    }
}
Enregistrer les
    écouteurs
use   SymfonyComponentEventDispatcherEventDispatcher;
use   AFUPListenerArticleListener;
use   AFUPListenerLuceneListener;
use   AFUPModelArticle;

// Déclaration des écouteurs
$listener1 = array(new ArticleListener(), 'onPreSave');
$listener2 = array(new LuceneListener(), 'onPostSave');

// Enregistrement des écouteurs
$dispatcher = new EventDispatcher();
$dispatcher->addListener('article.pre_save', $listener1);
$dispatcher->addListener('article.post_save', $listener2);
$article = new Article();

$article->setDispatcher($dispatcher);

$article->setTitle('AFUP Design Patterns');

$article->setMarkdownContent(
    'Some **markdown** content'
);

$article->save();
Dependency Injection
Mauvaise
Conception
Initiale
class Mailer
{
    public function send(Message $message)
    {
        try {
             $transport = new SMTPTransport(
                 'smtp.foo.com', 1234, 'mailer', 'p$wD^'
             );
             return $transport->send($message);
        } catch (TransportException $e) {
             $logger = Logger::getInstance();
             $logger->log('Unable to send message to...');
             $logger->logException($e);
             throw $e;
        }
    }
}
$message = new Message();
$message->setFrom('me@example.com');
$message->setTo('you@example.com');
$message->setSubject('Bonjour ...');
$message->setBody('Hello ...');

$mailer = new Mailer();
$mailer->send($message);
Ca fonctionne !
Oui mais ?!!!
$transport = new SMTPTransport(
    'smtp.foo.com',
     1234,
     'mailer',
     'p$wD^'
);
Je veux utiliser
un transport
différent…
Je veux configurer
le SMTP en dev et
en prod…
$logger = Logger::getInstance();
$logger->log('Unable to...');
$logger->logException($e);
Si le logger
n’existe pas ?
Si je veux changer
la configuration
du logger?
Je veux tester mon
code avec PHPUnit
et je n’y arrive
pas…
La Solution?
Injecter ses
dépendances au
Mailer
What ???
Injection par
les propriétés
class Mailer
{
    public $transport;

    public function send(Message $message)
    {
        try {
            $this->transport->send($message);
        } catch (TransportException $e) {
            // ...
        }
    }
}
$message = Message();
$message->setFrom('me@example.com');
$message->setTo('you@example.com');
$message->setSubject('Bonjour ...');
$message->setBody('Hello ...');

$transport = new SMTPTransport('...');

$mailer = new Mailer();
$mailer->transport = $transport;
$mailer->send($message);
Injection par
constructeur
class Mailer
{
    private $transport;

    function __construct(Transport $t)
    {
        $this->transport = $t;
    }
}
$message = Message();
$message->setFrom('me@example.com');
// ...

$transport = new SMTPTransport('...');

$mailer = new Mailer($transport);
$mailer->send($message);
Injection par
un mutateur
class Mailer
{
    private $logger;

    function setLogger(Logger $logger)
    {
        $this->logger = $logger;
    }
}
class Mailer
{
    // ...
    public function send(Message $message)
    {
        try {
             $this->transport->send($message);
        } catch (TransportException $e) {
             if (null !== $this->logger) {
                 $this->logger->log('...');
                 $this->logger->logException($e);
                 throw $e;
             }
        }
    }
}
$message = Message();
// ...

$logger = new FileLogger('/to/dev.log');
$transport = new SMTPTransport('...');

$mailer = new Mailer($transport);
$mailer->setLogger($logger);
$mailer->send($message);
Découplage
avec les
interfaces
class Mailer
{
    function __construct(TransportInterface $t)
    {
        $this->transport = $t;
    }

    function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}
class SMTPTransport implements TransportInterface
{
}

class MailTransport implements TransportInterface
{
}

class NullTransport implements TransportInterface
{
}
Bénéfices vs
Pertes ?!
Configurabilité
   Modularité
      Testabilité
Construction
   un peu plus
      Complexe
Inversion de Contrôle
# composer.json
{
    "require": {
        "pimple/pimple": "1.0.*"
    }
}
Global Configuration
    + Lazy Services
        = Container
Paramètres
Globaux de
Configuration
$pimple = new Pimple();

$pimple['logger.file'] = '/path/to/dev.log';
$pimple['logger.severity'] = 200;

$pimple['transport.smtp.host'] =   'smtp.foo.com';
$pimple['transport.smtp.port'] =   1234;
$pimple['transport.smtp.user'] =   'mailer';
$pimple['transport.smtp.passwd']   = '^p4$$W0rD*';
Enregistrer
des services
$pimple['logger'] = $pimple->share(function ($c) {

      if (!is_writable($c['logger.file'])) {
          throw new Exception('...');
      }

      $logger = new Logger($c['logger.file']);

      if (isset($c['logger.severity'])) {
          $logger->setSeverity($c['logger.severity']);
      }

      return $logger;
});
$pimple['mailer.transport'] = $pimple
->share(function ($c) {

      return new SMTPTransport(
          $c['transport.smtp.host'],
          $c['transport.smtp.port'],
          $c['transport.smtp.user'],
          $c['transport.smtp.passwd']
      );
});
$pimple['mailer'] = $pimple->share(function ($c) {

      $mailer = new Mailer($c['mailer.transport']);

      if (isset($c['logger'])) {
          $mailer->setLogger($c['logger']);
      }

      return $mailer;
});
Initialisation des
services à la
demande
$pimple = new Pimple();
$pimple['logger.file'] = '/path/to/dev.log';
$pimple['logger.severity'] = 200;
// ...

$message = Message();
$message->setFrom('me@example.com');
// ...

// Création à la demande du mailer
$pimple['mailer']->send($message);
Design Patterns avec PHP 5.3, Symfony et Pimple

More Related Content

What's hot

Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
Bill Chang
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
Fabien Potencier
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
Hugo Hamon
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
Fabien Potencier
 

What's hot (20)

Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of Lithium
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 

Similar to Design Patterns avec PHP 5.3, Symfony et Pimple

SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
smueller_sandsmedia
 

Similar to Design Patterns avec PHP 5.3, Symfony et Pimple (20)

How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Extbase and Beyond
Extbase and BeyondExtbase and Beyond
Extbase and Beyond
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
 
A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Oops in php
Oops in phpOops in php
Oops in php
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 

More from Hugo Hamon

Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec Jenkins
Hugo Hamon
 
Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend FrameworkExposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Hugo Hamon
 

More from Hugo Hamon (11)

Monitor the quality of your Symfony projects
Monitor the quality of your Symfony projectsMonitor the quality of your Symfony projects
Monitor the quality of your Symfony projects
 
Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CI
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
Développeurs, cachez-moi ça ! (Paris Web 2011)
Développeurs, cachez-moi ça ! (Paris Web 2011)Développeurs, cachez-moi ça ! (Paris Web 2011)
Développeurs, cachez-moi ça ! (Paris Web 2011)
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 Performant
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec Jenkins
 
Symfony2 en pièces détachées
Symfony2 en pièces détachéesSymfony2 en pièces détachées
Symfony2 en pièces détachées
 
Mieux Développer en PHP avec Symfony
Mieux Développer en PHP avec SymfonyMieux Développer en PHP avec Symfony
Mieux Développer en PHP avec Symfony
 
Introduction à Symfony2
Introduction à Symfony2Introduction à Symfony2
Introduction à Symfony2
 
Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend FrameworkExposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
Exposer des services web SOAP et REST avec symfony 1.4 et Zend Framework
 

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Recently uploaded (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

Design Patterns avec PHP 5.3, Symfony et Pimple