SlideShare une entreprise Scribd logo
1  sur  65
Télécharger pour lire hors ligne
Symfony2
The Unofficial “Best” Practices
Gerry Vandermaesen
AKA
How Gerry Does Symfony2
About Me
• Developer and trainer at King Foo
• SensioLabs Certified Symfony Developer
• We develop tailor-made PHP applications
• @gerryvdm / gerry@king-foo.be
The Official Best Practices
• Excellent guidelines for beginning Symfony
developers
• Use a single bundle for application specific
code
• Use the app/Resources/views/ directory for
all application specific templates
• Use YAML for application configuration
Keep your Business Logic
Outside Bundles
• Your business logic hopefully outlives
Symfony2
• Keep your model agnostic / decoupled from
the framework (and ORM)
Keep Mapping and Validation Configuration

Outside Entity Classes
=
Do Not Use Annotations
# config.yml 

doctrine:

orm:

auto_mapping: false

mappings:

model:

type: yml

prefix: KingFooPresentationModel

dir: %kernel.root_dir%/config/doctrine

alias: Model
Tip:

Defining Constraints in

app/config/validation.yml
use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface;

use SymfonyComponentDependencyInjectionContainerBuilder;



class RegisterValidationMappingsPass implements CompilerPassInterface

{

public function process(ContainerBuilder $container)

{

if ($container->hasDefinition('validator.builder')) {

$file = $container->getParameter('kernel.root_dir') .

'/config/validation.yml';



$container->getDefinition('validator.builder')

->addMethodCall('addYamlMappings', [$file]);

}

}

}
Combo-Tip:
Defining Constraints in

app/config/validation/*.yml
use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface;

use SymfonyComponentDependencyInjectionContainerBuilder;

use SymfonyComponentFinderFinder;



class RegisterValidationMappingsPass implements CompilerPassInterface

{

public function process(ContainerBuilder $container)

{

if ($container->hasDefinition('validator.builder')) {

$dir = $container->getParameter('kernel.root_dir') .

'/config/validation';



$finder = new Finder();

$finder->files()->name('*.yml')->in($dir);



$files = [];



foreach ($finder as $file) {

$files[] = $file->getRealPath();

}



if (count($files)) {

$container->getDefinition('validator.builder')

->addMethodCall('addYamlMappings', [$files]);

}

}

}

}
The Front Controller
$kernel = new AppKernel('prod', false);
use SymfonyComponentDebugDebug;
$env = getenv('SYMFONY_ENV') ?: 'prod';

$debug = getenv('SYMFONY_DEBUG') === '1' && $env !== 'prod';
if ($debug) {

Debug::enable();

}
$kernel = new AppKernel($env, $debug);
<VirtualHost *:80>

# ...

SetEnv SYMFONY_ENV dev

SetEnv SYMFONY_DEBUG 1

</VirtualHost>
server {

location /app.php {

# ...

fastcgi_param SYMFONY_ENV dev;

fastcgi_param SYMFONY_DEBUG 1;

}

}
Apache
Nginx
Taking It One Step Further
server {

# ...



location / {

try_files $uri @app;

}



location @app {

fastcgi_pass unix:/var/run/php5-fpm.sock;

include fastcgi_params;



fastcgi_param SCRIPT_FILENAME /path/to/project/app/app.php;

fastcgi_param SCRIPT_NAME /path/to/project/app/app.php;



fastcgi_param SYMFONY_ENV dev;

fastcgi_param SYMFONY_DEBUG 1;

}

}

Use PSR-4 for
the `src/` Directory
{

"autoload": {

"psr-4": { "KingFooPresentation": "src/" }

}

}
💫
Prevent Autoloading of

Tests in Production
{

"autoload": {

"psr-4": { "KingFooPresentation": "src/" }

},

"autoload-dev": {

"psr-4": { “KingFooPresentationTests”: "tests/" }

}

}

Add Requirements to
your Routes
# routing.yml

homepage:

path: /{_locale}



ticket_index:

path: /{_locale}/tickets



tickets_detail:

path: /{_locale}/tickets/{id}



tickets_create:

path: /{_locale}/tickets/create



login:

path: /login
# routing.yml

homepage:

path: /{_locale}

requirements: { _locale: "(nl|fr|en)" }



ticket_index:

path: /{_locale}/tickets

requirements: { _locale: "(nl|fr|en)" }



tickets_detail:

path: /{_locale}/tickets/{id}

requirements: { _locale: "(nl|fr|en)", id: "[1-9][0-9]*" }



tickets_create:

path: /{_locale}/tickets/create

requirements: { _locale: "(nl|fr|en)" }



login:

path: /login
Regex 😕
Global “Requirements”
use SymfonyComponentHttpKernelEventGetResponseEvent;

use SymfonyComponentHttpKernelExceptionNotFoundHttpException;



class CheckLocaleListener

{

private $availableLocales;



public function __construct(array $availableLocales)

{

$this->availableLocales = $availableLocales;

}



public function checkLocale(GetResponseEvent $event)

{

$request = $event->getRequest();



if ($locale = $request->attributes->get('_locale')) {

if (!in_array($locale, $this->availableLocales)) {

throw new NotFoundHttpException();

}

}

}

}
# services.yml

parameters:

available_locales: [nl, fr, en]



services:

check_locale_listener:

class: CheckLocaleListener

arguments: [%available_locales%]

tags:

- name: kernel.event_listener

event: kernel.request

method: checkLocale

priority: 24
Bring Order in your
Services Configuration
# services.yml



# 500 lines of service declarations...
# services.yml

imports:

- { resource: services/controllers.yml }

- { resource: services/event_listeners.yml }

- { resource: services/repositories.yml }

Try Defining Your Services
as Private
# services.yml

services:

my_fantastic_service:

class: KingFooPresentationFantasticService

public: false
class DependentService extends ContainerAware

{

public function doSomething()

{

$this->container->get('my_fantastic_service')

->doSomethingElse();

}

}
class DependentService

{

public function __construct(FantasticService $service)

{

$this->service = $service;

}



public function doSomething()

{

$this->service->doSomethingElse();

}

}
Define your Repositories
as Services
# repositories.yml

services:

abstract_repository:

abstract: true

factory_service: doctrine.orm.entity_manager

factory_method: getRepository

public: false

blog_post_repository:

parent: abstract_repository

class: KingFooPresentationRepositoryBlogPostRepository

arguments: [Model:BlogPost]

comment_repository:

parent: abstract_repository

class: KingFooPresentationRepositoryCommentRepository

arguments: [Model:Comment]
Define your Controllers
as Services
# controllers.yml

services:

blog_post_controller:

class: KingFooPresentationControllerBlogPostController

arguments:

- @blog_post_repository

- @doctrine.orm.entity_manager
One Controller One Action
# controllers.yml

services:

blog_post_list_controller:

class: KingFooPresentationControllerBlogPostListController

arguments: [@blog_post_repository]

blog_post_create_controller:

class: KingFooPresentationControllerBlogPostCreateController

arguments: [@doctrine.orm.entity_manager]
<?php



namespace KingFooPresentationControllerBlogPost;



use DoctrineCommonPersistenceObjectManager;

use SymfonyComponentHttpFoundationRequest;



class CreateController

{

public function __construct(ObjectManager $manager)

{

// ...

}



public function __invoke(Request $request)

{

// ...

}

}
Annotate your Controllers
public function __invoke(Request $request)

{

if (!$this->authorizationChecker->isGranted('ROLE_EDITOR')) {

throw new AccessDeniedHttpException();

}



$response = new Response();

$response->setMaxAge(3600);



return $this->templating->renderResponse(

'blog_post/create.html.twig',

array(

// view parameters

),

$response

);

}
use SensioBundleFrameworkExtraBundleConfigurationCache;

use SensioBundleFrameworkExtraBundleConfigurationRoute;

use SensioBundleFrameworkExtraBundleConfigurationSecurity;

use SensioBundleFrameworkExtraBundleConfigurationTemplate;



/**

* @Route(service="blog_post_create_controller")

*/

class CreateController

{

/**

* @Route("/blog/create", name="foo")

* @Cache(maxage=3600)

* @Security("has_role('ROLE_EDITOR')")

* @Template("blog_post/create.html.twig")

*/

public function __invoke(Request $request)

{

return array(

// view parameters

);

}

}
Never Circumvent the
Framework
class BadController

{

public function __invoke()

{

$template = $_GET['template'];

setcookie('lastGeneration', time());



$this->archaicPdfLib->output($template);

exit;

}

}
use SymfonyComponentHttpFoundationCookie;

use SymfonyComponentHttpFoundationRequest;

use SymfonyComponentHttpFoundationStreamedResponse;



class BetterController

{

public function __invoke(Request $request)

{

$template = $request->query->get('template');



$response = new StreamedResponse(

function() use ($template) {

$this->archaicPdfLib->output($template);

}

);



$cookie = new Cookie('lastGeneration', time());

$response->headers->setCookie($cookie);



return $response;

}

}
Securing your Application
Avoid usage of
`access_control` in
security.yml
access_control:

- { path: ^/(nl|fr|en)/admin, roles: ROLE_ADMIN }
Regex 😕
class AdminController

{

/**

* @Route("/{_locale}/admin")

* @Security("has_role('ROLE_ADMIN')")

*/

public function __invoke(Request $request)

{

// if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {

// throw new AccessDeniedHttpException();

// }



// ..

}

}
Use Bcrypt
# security.yml

security:

encoders:

KingFooPresentationSecurityUser:

algorithm: bcrypt

cost: 13
# services.yml

services:

password_encoder:

class: SymfonyComponentSecurity...BCryptPasswordEncoder

arguments: [13]



# security.yml

security:

encoders:

KingFooPresentationSecurityUser:

id: password_encoder
Create Your Own Symfony
Framework Edition
• Remove clutter
• Add/remove default dependencies
• Customize default configuration
• Fork symfony/symfony-standard
• Make modifications
• Modify composer.json package name
• Publish on GitHub and Packagist
{

"name": "kingfoo/symfony-project",

"autoload": {

"psr-4": { "": "src/" }

},

"require": {

"php": ">=5.5.0",

"symfony/symfony": "~2.6",

"doctrine/mongodb-odm": "~1.0@dev",

"doctrine/mongodb-odm-bundle": "~3.0@dev",

"symfony/monolog-bundle": "~2.4",

"sensio/distribution-bundle": "~3.0,>=3.0.12",

"sensio/framework-extra-bundle": "~3.0",

"incenteev/composer-parameter-handler": "~2.0"

},

"require-dev": {

"phpunit/phpunit": "~4.4"

}

}
Miscellaneous / Flamebait
• Bundles are for extending the container and
configuring (third-party) libraries that are
reusable across projects in the container.
• Try doing without bundles for project-
specific configuration.
• YAML is the preferred configuration file
format for application-specific config, XML
for configuration of bundles
Develop Your Own

Best Practices
• Do it as a team
• Write them down
• Be consistent
• Learn regex 😉
Next Symfony Training
• Getting Started with Symfony2
• 12-13th February 2015
• Aarschot
• Leave your name + email for a €50 reduction
Questions? 🙉

Contenu connexe

En vedette

CQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationCQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationSamuel ROZE
 
Design pattern in Symfony2 - Nanos gigantium humeris insidentes
Design pattern in Symfony2 - Nanos gigantium humeris insidentesDesign pattern in Symfony2 - Nanos gigantium humeris insidentes
Design pattern in Symfony2 - Nanos gigantium humeris insidentesGiulio De Donato
 
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 DICKonstantin Kudryashov
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages webJean-Pierre Vincent
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsDavey Shafik
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phingRajat Pandit
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)Matthias Noback
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performanceafup Paris
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Marcello Duarte
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!tlrx
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLGabriele Bartolini
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Bruno Boucard
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)Arnauld Loyer
 
Performance serveur et apache
Performance serveur et apachePerformance serveur et apache
Performance serveur et apacheafup Paris
 

En vedette (20)

CQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationCQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony application
 
Design pattern in Symfony2 - Nanos gigantium humeris insidentes
Design pattern in Symfony2 - Nanos gigantium humeris insidentesDesign pattern in Symfony2 - Nanos gigantium humeris insidentes
Design pattern in Symfony2 - Nanos gigantium humeris insidentes
 
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
 
Elastic Searching With PHP
Elastic Searching With PHPElastic Searching With PHP
Elastic Searching With PHP
 
Diving deep into twig
Diving deep into twigDiving deep into twig
Diving deep into twig
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages web
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP Streams
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phing
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performance
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQL
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Performance serveur et apache
Performance serveur et apachePerformance serveur et apache
Performance serveur et apache
 

Dernier

What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 

Dernier (20)

What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 

Symfony2 - The Unofficial "Best" Practices