In Symfony2, a service is defined as [emphasis mine]:
A Service is a generic term for any PHP object that performs a
specific task. A service is usually used “globally“, such as a
database connection object or an object that delivers email messages.
In Symfony2, services are often configured and retrieved from the
service container. An application that has many decoupled services is
said to follow a service-oriented architecture.
With “globally” being the key word, all the examples I see of how to define a service have the service declared within an existing bundle? Here’s an example from MartinSikora.com
<?php
// Bundle/HelloBundle/Services/MyService.php
namespace Bundle\HelloBundle\Services;
class MyService {
public function sum($n1, $n2) {
return $n1 + $n2;
}
}
?>
He then uses it from within the Hello Controller:
<?php
// Bundle/HelloBundle/Controller/HelloController.php
namespace Bundle\HelloBundle\Controller;
class HelloController extends Controller {
public function indexAction() {
$number = $this->get('my_service')->sum(12, 37);
// this returns 49
/*
...
*/
}
}
?>
Notice how his example service is declared inside of the HelloBundle bundle in a folder labeled “Services”. Wouldn’t it be better if the “Services” folder were stored one or more levels higher outside of any specific bundle since services are meant to be used across the entire application?
- What’s the best practice here?
- Is the service only available to controllers within the HelloBundle Bundle?
- Why is it usually done this way?
Short answer
No, services do not need to be defined within a bundle. The actual service class may or may not live within a bundle – they may live in a vendor library folder (or anywhere else for that matter). And service definitions, while commonly defined within a bundle’s
Resources\config\services.yml, can also be defined inapp/config.ymlunder aserviceskey.A service is simply a class that has been registered with Symfony’s dependency injection container. The class itself can live anywhere.
Long answer
It’s important to understand the purpose of bundles in Symfony2. The majority of your project (with the main exception being 3rd party libraries) is comprised of bundles. Some people like to put everything in one giant bundle, but I prefer to use them as containers for specific pieces of functionality (ie: User management, Blog Post management, Asset management.)
Because bundles should represent a piece of functionality, it makes sense to define some services within bundles. For example, it’s natural to define a
BlogPostEntityServiceclass in aBlogPostBundle. Now, just because the service is contained within a bundle, doesn’t make it any less global. If I register my service asblog_bundle.blog_post_entity_service, I can still access it from any other bundle.In Martin’s example,
MyServiceis a vague example – it isn’t specific likeBlogPostEntityService. However, it is likely that you’ll create utility services (ieArrayUtilService), in which case you might want to create aUtilBundleand store the service there.There’s no definitive answer – it’s up to you to decide where to store service classes. Ask yourself if the service deals directly with the piece of functionality your bundle represents – if so, it likely belongs in the bundle. This also makes sense if you plan on sharing or reusing your bundle.
No. You can call the service from within any controller (or any
containeraware class). You can also injectMyServiceinto any other service.