CINXE.COM
wikimedia/services - Packagist
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>wikimedia/services - Packagist</title> <meta name="description" content="Generic service to manage named services using lazy instantiation based on instantiator callback functions" /> <meta name="author" content="Jordi Boggiano" /> <link rel="canonical" href="https://packagist.org/packages/wikimedia/services" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="shortcut icon" href="/favicon.ico?v=1732552146" /> <link rel="stylesheet" href="/build/app.css?v=1732552146" /> <link rel="alternate" type="application/rss+xml" title="New Releases - wikimedia/services" href="https://packagist.org/feeds/package.wikimedia/services.rss" /> <link rel="alternate" type="application/rss+xml" title="New Releases - wikimedia" href="https://packagist.org/feeds/vendor.wikimedia.rss" /> <link rel="alternate" type="application/rss+xml" title="Newly Submitted Packages - Packagist" href="https://packagist.org/feeds/packages.rss" /> <link rel="alternate" type="application/rss+xml" title="New Releases - Packagist" href="https://packagist.org/feeds/releases.rss" /> <link rel="search" type="application/opensearchdescription+xml" href="/search.osd?v=1732552146" title="Packagist" /> <script nonce="/LsuuZcpjQ80mO0AhgEIBA=="> var onloadRecaptchaCallback = function() { document.querySelectorAll('.recaptcha-protected').forEach((el) => { el.closest('form').querySelectorAll('button, input[type="submit"]').forEach((submit) => { grecaptcha.render(submit, { 'sitekey' : '6LfKiPoUAAAAAGlKWkhEEx7X8muIVYy6oA0GNdX0', 'callback' : function (token) { submit.form.submit(); } }); }) }); }; </script> <link rel="stylesheet" href="/css/github/markdown.css?v=1732552146"> </head> <body> <section class="wrap"> <header class="navbar-wrapper navbar-fixed-top"> <nav class="container"> <div class="navbar" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <h1 class="navbar-brand"><a href="/">Packagist</a> <em class="hidden-sm hidden-xs">The PHP Package Repository</em></h1> </div> <div class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li> <a href="/explore/">Browse</a> </li> <li> <a href="/packages/submit">Submit</a> </li> <li> <a href="/register/">Create account</a> </li> <li class="nav-user"> <section class="nav-user-signin"> <a href="/login/">Sign in</a> <section class="signin-box"> <form action="/login/" method="POST" id="nav_login"> <div class="input-group"> <input class="form-control" type="text" id="_username" name="_username" placeholder="Username / Email"> <span class="input-group-addon"><span class="icon-user"></span></span> </div> <div class="input-group"> <input class="form-control" type="password" id="_password" name="_password" placeholder="Password"> <span class="input-group-addon"><span class="icon-lock"></span></span> </div> <div class="checkbox"> <label for="_remember_me"> <input type="checkbox" id="_remember_me" name="_remember_me" value="on" checked="checked" /> Remember me </label> </div> <div class="signin-box-buttons"> <a href="/login/github" class="pull-right btn btn-primary btn-github"><span class="icon-github"></span>Use Github</a> <button type="submit" class="btn btn-success" id="_submit_mini" name="_submit">Log in</button> </div> </form> <div class="signin-box-register"> <a href="/register/">No account yet? Create one now!</a> </div> </section> </section> </li> </ul> </div> </div> </nav> </header> <section class="wrapper wrapper-search"> <div class="container "> <form name="search_query" method="get" action="/search/" id="search-form" autocomplete="off"> <div class="sortable row"> <div class="col-xs-12 js-search-field-wrapper col-md-9"> <input type="search" id="search_query_query" name="query" required="required" autocomplete="off" placeholder="Search packages..." tabindex="1" class=" form-control" value="" /> </div> </div> </form> </div> </section> <section class="wrapper"> <section class="container content" role="main"> <div id="search-container" class="hidden"> <div class="row"> <div class="search-list col-md-9"></div> <div class="search-facets col-md-3"> <div class="search-facets-active-filters"></div> <div class="search-facets-type"></div> <div class="search-facets-tags"></div> </div> </div> <div class="row"> <div class="col-md-9"> <div id="powered-by"> Search by <a href="https://www.algolia.com/"><img src="/img/algolia-logo-light.svg?v=1732552146"></a> </div> <div id="pagination-container"> <div class="pagination"></div> </div> </div> </div> </div> <div class="row" id="view-package-page"> <div class="col-xs-12 package"> <div class="package-header"> <div class="row"> <div class="col-md-9"> <h2 class="title"> <a href="/packages/wikimedia/">wikimedia<span class="hidden"> </span>/</a><span class="hidden"> </span>services </h2> </div> </div> </div> <div class="row"> <div class="col-md-8"> <p class="requireme"><i class="glyphicon glyphicon-save"></i> <input type="text" readonly="readonly" value="composer require wikimedia/services" /></p> <p class="description">Generic service to manage named services using lazy instantiation based on instantiator callback functions</p> </div> <div class="col-md-offset-1 col-md-3"> <div class="row package-aside"> <div class="details col-xs-12 col-sm-6 col-md-12"> <h5>Maintainers</h5> <p class="maintainers"> <a href="/users/mediawiki/"><img width="48" height="48" title="mediawiki" src="https://www.gravatar.com/avatar/69f26e89abcd06129a098b407d072686?s=48&d=identicon" srcset="https://www.gravatar.com/avatar/69f26e89abcd06129a098b407d072686?s=96&d=identicon 2x"></a> <a href="/users/legoktm/"><img width="48" height="48" title="legoktm" src="https://www.gravatar.com/avatar/10e80b44109f3f9cf36fb197b1fc57ee?s=48&d=identicon" srcset="https://www.gravatar.com/avatar/10e80b44109f3f9cf36fb197b1fc57ee?s=96&d=identicon 2x"></a> <a href="/users/wikimedia/"><img width="48" height="48" title="wikimedia" src="https://www.gravatar.com/avatar/2e04c0db7589a07fdccfc836d70a5ba3?s=48&d=identicon" srcset="https://www.gravatar.com/avatar/2e04c0db7589a07fdccfc836d70a5ba3?s=96&d=identicon 2x"></a> </p> <h5>Details</h5> <p class="canonical"> <a href="https://github.com/wikimedia/mediawiki-libs-Services" title="Canonical Repository URL">github.com/wikimedia/mediawiki-libs-Services</a> </p> <p><a rel="nofollow noopener external noindex ugc" href="https://www.mediawiki.org/wiki/Services_(PHP_library)">Homepage</a></p> <p><a rel="nofollow noopener external noindex ugc" href="https://github.com/wikimedia/mediawiki-libs-Services/tree/4.0.0">Source</a></p> </div> <div class="facts col-xs-12 col-sm-6 col-md-12"> <p> <span> <a href="/packages/wikimedia/services/stats" rel="nofollow">Installs</a>: </span> 339 013 </p> <p> <span> <a href="/packages/wikimedia/services/dependents?order_by=downloads" rel="nofollow">Dependents</a>: </span> 1 </p> <p> <span> <a href="/packages/wikimedia/services/suggesters" rel="nofollow">Suggesters</a>: </span> 0 </p> <p> <span> <a href="/packages/wikimedia/services/advisories" rel="nofollow">Security</a>: </span> 0 </p> <p> <span> <a href="https://github.com/wikimedia/mediawiki-libs-Services/stargazers">Stars</a>: </span> 1 </p> <p> <span> <a href="https://github.com/wikimedia/mediawiki-libs-Services/watchers">Watchers</a>: </span> 2 </p> <p> <span> <a href="https://github.com/wikimedia/mediawiki-libs-Services/forks">Forks</a>: </span> 0 </p> </div> </div> </div> </div> <div class="row versions-section"> <div class="version-details col-md-9"> <div class="title"> <span class="version-number">4.0.0</span> <span class="release-date">2024-11-08 15:57 UTC</span> </div> <div class="clearfix package-links"> <div class="row"> <div class="clearfix visible-sm-block"></div> <div class="clearfix visible-md-block visible-lg-block"></div> <div class="requires col-sm-6 col-md-4 "> <p class="link-type">Requires</p> <ul><li>php: >=7.4.3</li><li><a href="/packages/psr/container">psr/container</a>: ^1.1 || ^2.0</li><li><a href="/packages/wikimedia/scoped-callback">wikimedia/scoped-callback</a>: ^3.0 || ^4.0 || ^5.0</li></ul> </div> <div class="devRequires col-sm-6 col-md-4 "> <p class="link-type">Requires (Dev)</p> <ul><li><a href="/packages/mediawiki/mediawiki-codesniffer">mediawiki/mediawiki-codesniffer</a>: 45.0.0</li><li><a href="/packages/mediawiki/mediawiki-phan-config">mediawiki/mediawiki-phan-config</a>: 0.14.0</li><li><a href="/packages/mediawiki/minus-x">mediawiki/minus-x</a>: 1.1.3</li><li><a href="/packages/ockcyp/covers-validator">ockcyp/covers-validator</a>: 1.6.0</li><li><a href="/packages/php-parallel-lint/php-console-highlighter">php-parallel-lint/php-console-highlighter</a>: 1.0.0</li><li><a href="/packages/php-parallel-lint/php-parallel-lint">php-parallel-lint/php-parallel-lint</a>: 1.4.0</li><li><a href="/packages/phpunit/phpunit">phpunit/phpunit</a>: 9.6.21</li></ul> </div> <div class="clearfix visible-sm-block"></div> <div class="suggests col-sm-6 col-md-4 hidden-xs"> <p class="link-type">Suggests</p> <p class="no-links">None</p> </div> <div class="clearfix visible-md-block visible-lg-block"></div> <div class="provides col-sm-6 col-md-4 "> <p class="link-type">Provides</p> <ul><li><a href="/providers/psr/container-implementation">psr/container-implementation</a>: 1.0.0</li></ul> </div> <div class="clearfix visible-sm-block"></div> <div class="conflicts col-sm-6 col-md-4 hidden-xs"> <p class="link-type">Conflicts</p> <p class="no-links">None</p> </div> <div class="replaces col-sm-6 col-md-4 hidden-xs"> <p class="link-type">Replaces</p> <p class="no-links">None</p> </div> </div> </div> <div class="metadata"> <p class="license"><i class="glyphicon glyphicon-copyright-mark" title="License"></i> GPL-2.0-or-later <span class="source-reference"><i class="glyphicon glyphicon-bookmark" title="Source Reference"></i> 87f71136c19ca4769dcb2b870e565dceb72e23fb</span></p> <i class="glyphicon glyphicon-user" title="Authors"></i> <ul class="authors"> <li>Daniel Kinzler <span class="visible-sm-inline visible-md-inline visible-lg-inline"><dkinzler<span style="display:none">.woop</span>@wikimedia.org></span></li> </ul> </div> </div> <div class="col-md-3 no-padding"> <div class="package-aside versions-wrapper"> <ul class="versions"> <li class="details-toggler version" data-version-id="dev-master" data-load-more="/versions/4109517.json"> <a href="#dev-master" class="version-number">dev-master</a> </li> <li class="details-toggler version open" data-version-id="4.0.0" data-load-more="/versions/8578675.json"> <a href="#4.0.0" class="version-number">4.0.0</a> </li> <li class="details-toggler version" data-version-id="3.0.0" data-load-more="/versions/6443533.json"> <a href="#3.0.0" class="version-number">3.0.0</a> </li> <li class="details-toggler version" data-version-id="2.0.1" data-load-more="/versions/4123690.json"> <a href="#2.0.1" class="version-number">2.0.1</a> </li> <li class="details-toggler version" data-version-id="2.0.0" data-load-more="/versions/4112811.json"> <a href="#2.0.0" class="version-number">2.0.0</a> </li> <li class="details-toggler version last" data-version-id="1.0.0" data-load-more="/versions/3110967.json"> <a href="#1.0.0" class="version-number">1.0.0</a> </li> </ul> <div class="hidden versions-expander"> <i class="glyphicon glyphicon-chevron-down"></i> </div> </div> <div class="last-update"> <p class="auto-update-success">This package is auto-updated.</p> <p>Last update: 2024-11-09 14:25:20 UTC </p> </div> </div> </div> <hr class="clearfix"> <div class="readme markdown-body"> <h1>README</h1> <p><a href="https://packagist.org/packages/wikimedia/services" rel="nofollow noindex noopener external ugc"><img src="https://camo.githubusercontent.com/e2fef629de6521fdad33ea827ce659bce6fc8d17540e154084c02d1880ef17c3/68747470733a2f2f706f7365722e707567782e6f72672f77696b696d656469612f73657276696365732f762f737461626c652e737667" alt="Latest Stable Version" /></a> <a href="https://packagist.org/packages/wikimedia/services" rel="nofollow noindex noopener external ugc"><img src="https://camo.githubusercontent.com/7c8564de0c60a131053ca21dff3595e76e3d973c33d9aa15c1a4b3d6b173017a/68747470733a2f2f706f7365722e707567782e6f72672f77696b696d656469612f73657276696365732f6c6963656e73652e737667" alt="License" /></a></p> <h1 class="heading-element">Services</h1><a id="user-content-services" class="anchor" href="#user-content-services" rel="nofollow noindex noopener external ugc"></a> <p>A <a href="https://www.php-fig.org/psr/psr-11/" rel="nofollow noindex noopener external ugc">PSR-11</a>-compliant services framework. Services are created by instantiators (callables), which are usually defined in separate wiring files.</p> <h2 class="heading-element">Usage</h2><a id="user-content-usage" class="anchor" href="#user-content-usage" rel="nofollow noindex noopener external ugc"></a> <pre><span class="pl-s1"><span class="pl-c1">$</span>services</span> = <span class="pl-k">new</span> <span class="pl-v">ServiceContainer</span>(); <span class="pl-s1"><span class="pl-c1">$</span>services</span>-><span class="pl-en">defineService</span>( <span class="pl-s">'<span class="pl-s">MyService</span>'</span>, <span class="pl-k">static</span> <span class="pl-k">function</span> ( <span class="pl-smi"><span class="pl-smi">ServiceContainer</span></span> <span class="pl-s1"><span class="pl-c1">$</span>services</span> ): <span class="pl-smi"><span class="pl-smi">MyService</span></span> { <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">MyService</span>(); } ); <span class="pl-s1"><span class="pl-c1">$</span>services</span>-><span class="pl-en">loadWiringFiles</span>( [ <span class="pl-s">'<span class="pl-s">path/to/ServiceWiring.php</span>'</span>, ] );</pre> <p>Where <code>ServiceWiring.php</code> looks like this:</p> <pre><span class="pl-k">return</span> [ <span class="pl-s">'<span class="pl-s">MyOtherService</span>'</span> => <span class="pl-k">static</span> <span class="pl-k">function</span> ( <span class="pl-smi"><span class="pl-smi">ServiceContainer</span></span> <span class="pl-s1"><span class="pl-c1">$</span>services</span> ): <span class="pl-smi"><span class="pl-smi">MyOtherService</span></span> { <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">MyOtherService</span>( <span class="pl-s1"><span class="pl-c1">$</span>services</span>-><span class="pl-en">get</span>( <span class="pl-s">'<span class="pl-s">MyService</span>'</span> ) ); }, <span class="pl-c">// ...</span> ];</pre> <p>Each instantiator receives the service container as the first argument, from which it may retrieve further services as needed. Additional arguments for each instantiator may be specified when constructing the <code>ServiceContainer</code>.</p> <p>Custom subclasses of <code>ServiceContainer</code> may offer easier access to certain services:</p> <pre><span class="pl-k">class</span> <span class="pl-v">MyServiceContainer</span> <span class="pl-k">extends</span> <span class="pl-v">ServiceContainer</span> { <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getMyService</span>(): <span class="pl-smi"><span class="pl-smi">MyService</span></span> { <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-><span class="pl-en">get</span>( <span class="pl-s">'<span class="pl-s">MyService</span>'</span> ); } <span class="pl-k">public</span> <span class="pl-k">function</span> <span class="pl-en">getMyOtherService</span>(): <span class="pl-smi"><span class="pl-smi">MyOtherService</span></span> { <span class="pl-k">return</span> <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-><span class="pl-en">get</span>( <span class="pl-s">'<span class="pl-s">MyOtherService</span>'</span> ); } } <span class="pl-c">// ServiceWiring.php</span> <span class="pl-k">return</span> [ <span class="pl-s">'<span class="pl-s">MyOtherService</span>'</span> => <span class="pl-k">static</span> <span class="pl-k">function</span> ( <span class="pl-smi"><span class="pl-smi">MyServiceContainer</span></span> <span class="pl-s1"><span class="pl-c1">$</span>services</span> ): <span class="pl-smi"><span class="pl-smi">MyOtherService</span></span> { <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">MyOtherService</span>( <span class="pl-s1"><span class="pl-c1">$</span>services</span>-><span class="pl-en">getMyService</span>() ); }, ];</pre> <h2 class="heading-element">Running tests</h2><a id="user-content-running-tests" class="anchor" href="#user-content-running-tests" rel="nofollow noindex noopener external ugc"></a> <pre class="notranslate"><code>composer install --prefer-dist composer test </code></pre> <h2 class="heading-element">History</h2><a id="user-content-history" class="anchor" href="#user-content-history" rel="nofollow noindex noopener external ugc"></a> <p>This library was first introduced in <a href="https://www.mediawiki.org/wiki/MediaWiki_1.27" rel="nofollow noindex noopener external ugc">MediaWiki 1.27</a> (<a href="https://gerrit.wikimedia.org/r/264403" rel="nofollow noindex noopener external ugc">I3c25c0ac17</a>). It was split out of the MediaWiki codebase and published as an independent library during the <a href="https://www.mediawiki.org/wiki/MediaWiki_1.33" rel="nofollow noindex noopener external ugc">MediaWiki 1.33</a> and <a href="https://www.mediawiki.org/wiki/MediaWiki_1.34" rel="nofollow noindex noopener external ugc">MediaWiki 1.34</a> development cycles.</p> </div> </div> </div> </section> </section> </section> <footer class="wrapper-footer"> <nav class="container"> <div class="row"> <ul class="social col-xs-7 col-sm-4 col-md-2 pull-right"> <li><a href="http://github.com/composer/packagist" title="GitHub"><span class="icon-github"></span></a></li> <li><a href="https://twitter.com/packagist" title="Follow @packagist"><span class="icon-twitter"></span></a></li> <li><a href="mailto:contact@packagist.org" title="Contact"><span class="icon-mail"></span></a></li> </ul> <ul class="col-xs-4 col-sm-4 col-md-2"> <li><a href="/about">About Packagist</a></li> <li><a href="/feeds/" rel="nofollow">Atom/RSS Feeds</a></li> </ul> <div class="clearfix visible-xs-block"></div> <ul class="col-xs-3 col-sm-4 col-md-2"> <li><a href="/statistics" rel="nofollow">Statistics</a></li> <li><a href="/explore/">Browse Packages</a></li> </ul> <div class="clearfix visible-xs-block visible-sm-block"></div> <ul class="col-xs-3 col-sm-4 col-md-2"> <li><a href="/apidoc">API</a></li> <li><a href="/mirrors">Mirrors</a></li> </ul> <div class="clearfix visible-xs-block"></div> <ul class="col-xs-3 col-sm-4 col-md-2"> <li><a href="https://status.packagist.org/">Status</a></li> <li><a href="https://p.datadoghq.com/sb/x98w56x71erzshui-4a54c45f82bacc991e83302548934b6a">Dashboard</a></li> </ul> </div> <div class="row sponsor"> <p class="col-xs-12">Packagist maintenance and hosting provided by <a href="https://packagist.com/"><img alt="Private Packagist" src="/img/private-packagist.svg?v=1732552146" /></a></p> </div> <div class="row sponsor"> <p class="col-xs-12">Monitoring provided by <a href="https://datadog.com/"><img alt="Datadog" src="/img/datadog-light.png?v=1732552146" /></a></p> </div> </nav> </footer> <script nonce="/LsuuZcpjQ80mO0AhgEIBA=="> var algoliaConfig = {"app_id":"M58222SH95","search_key":"5ae4d03c98685bd7364c2e0fd819af05","index_name":"packagist"}; window.process = { env: { DEBUG: undefined }, }; </script> <script nonce="/LsuuZcpjQ80mO0AhgEIBA==" src="/build/app.js?v=1732552146"></script> </body> </html>