Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Dependency Injection - A minimal Symfony Example

Unlike other posts revolving around Dependency Injection this one cares only the very basic about definition and instead it focuses on how to get things done relatively simple.

What you need to know is that by following DI pattern using Symfony your classes become "services" that are available for other parts of the application through the Symfony Service Locator.

The same way your class becomes a service that others can use, you can use other available services.

Say for example that your class needs to interact with an API. Save time and instead of building up a custom API client require Guzzle in your project.

Get started

[DISCLOSURE] As always you can refer to the docs in the Symfony official site but be aware the code samples are sometimes too abstract and without practical context it becomes a pain to get the application going. My purpose for this guideline is to clear things out of the path.

After the brief disclosure time to move along; since we want to use Guzzle we have to require it as it is not shipped with Symfony as default. Go ahead and add this package to your composer.json. Run composer update to get your vendor directory updated.

After Guzzle is installed create a class in your bundle that will interact with an "score" API. The class constructor will tell us what are the minimal required arguments to get it working: an instance of Guzzle and three string scalars for url, key and pass respectively.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
/** * Class Score * / class Score{ /** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
}

Next step is to let the Service Locator know about this new class.

app/config/services.yml
# Learn more about services, parameters and containers at# http://symfony.com/doc/current/book/service_container.htmlparameters:
## arguments for guzzleurl: http://jlopez.mx/scores/key: keypass: secretservices:
## guzzle http clientguzzle:
class: \GuzzleHttp\Client## scorescore:
class: AppBundle\Services\Scorearguments: ["@guzzle", "%url%", "%key%", "%pass%"]

Observe what is happening here:

  • The application will be aware of a service named guzzle and it resolves to an instance of \GuzzleHttp\Client.
  • The application will be aware of a service named score and the arguments are an instance of \GuzzHttp\Client and three scalar values for api url, api key and api password respectively. It resolves your custom class.
  • When you inject a service into another service you have to prefix it with @
  • When you inject scalar values to your service you have to start and end with %

So at this point your dependencies are declared and ready to be injected yet there is not actual logic at all.

Lets implement something to make an API call and output the response from the default Symfony controller.

AppBundle/Services/Score.php
<?phpnamespaceAppBundle\Services;
useGuzzleHttp\Psr7\Response;
/** * Class Score */class Score{
/** * @var \GuzzleHttp\Client */private$client;
/** * @var string */private$url;
/** * @var string */private$key;
/** * @var string */private$pass;
/** * Score constructor. * @param \GuzzleHttp\Client $client * @param string $url * @param string $key * @param string $pass */publicfunction__construct(\GuzzleHttp\Client$client, $url = '', $key = '', $pass = ''){
$this->client = $client;
$this->url = $url;
$this->key = $key;
$this->pass = $pass;
}
/** * @param $question * @param $answer * @return Response */publicfunctionretrieve($question, $answer){
return$this->client->request('GET', '?'. http_build_query(['q' => $question, 'a' => $answer]), [
'base_uri' => $this->url,
'auth' => [$this->key, $this->pass]
]);
}
}
AppBundle/Controller/DefaultController.php
<?phpnamespaceAppBundle\Controller;
useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;
useSymfony\Bundle\FrameworkBundle\Controller\Controller;
useSymfony\Component\HttpFoundation\Request;
useSymfony\Component\HttpFoundation\Response;
class DefaultController extends Controller{
/** * @Route("/", name="homepage") */publicfunctionindexAction(Request$request){
// invoke score service$score = $this->get('score');
// retrieve results for question 1, answer option 1return Response::create($score->retrieve(1,1)->getBody()->getContents());
}
}

Testing the actual code in a browser displays a value for the score.

{"score":10}

Bottomline

Though it may look a pretty basic example the implementation shows what you have to setup in order for the Dependency Injector become aware of your custom code.

If walked thru the example you have noticed that the service locator reads the declaration of your services and parameters in only one configuration file and it automatically resolves and injects such services throughout the application.

Benefits

Stop worrying to scan all your base code to see the how classes relate and communicate each other. This is a key DI benefit.

Leverage this pattern the next time you find yourself not declaring up front class-dependencies but instead creating objects on-demand: at the long term your application will be eating unnecesary large chunks of memory to hold these objects having bad performance as a result.

If you plan ahead to use DI with Symfony have this guideline as reference to help you to get started.

Jaziel Lopez, Experienced Software Developer, Tijuana Area Mexico, 2016

About

Symfony Dependency Injection Minimal Example

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages