|Other languages:||English • 日本語|
The API can be called internally from within PHP without going through an HTTP request.
However, application logic should avoid this, and directly access the PHP classes that are responsible for the respective functionality, instead of going through the API framework.
Internal API calls should generally only be used for testing purposes, and quick prototyping.
From test suite code
To call the API from within tests, the easiest way is to extend your test class from
ApiTestCase (rather than
MediaWikiTestCase). Then you can use
ApiTestCase::doApiRequest() as follows.
$result = $this->doApiRequest( [ 'action' => 'edit', 'title' => 'Test_page', 'appendtext' => 'Testing editing.', 'token' => $user->getEditToken(), ] );
This is how tests of the API should be done, but sometimes you want a test to use the API in order to set up for other tests that are not actual API tests. In this case you'll probably not want to inherit from ApiTestCase.
In this situation the request has to be constructed in more detail because the edit token needs to be stored in the session. In this case, the
$wgRequest global is a FauxRequest that is already configured by the test harness.
global $wgRequest; $user = parent::getTestSysop()->getUser(); $this->assertTrue($user->isLoggedIn()); $apiParams = [ 'action' => 'edit', 'title' => 'Test_page', 'appendtext' => 'Testing editing.', 'token' => $user->getEditToken(), ]; $apiRequest = new FauxRequest( $apiParams, true, $wgRequest->getSessionArray() ); $context = new DerivativeContext( new RequestContext() ); $context->setRequest( $apiRequest ); $context->setUser( $user ); $api = new ApiMain( $context, true ); $result = $api->execute();
From application code
There are some acceptable cases when this technique is acceptable, however: unit and functional tests.
WikiPage::doEditContent()instead of an API request.
Sometimes other PHP code may wish to use the data access and aggregation functionality of the action API. Rather than making an HTTP network request to the same server, you can make a call within PHP.
The steps are:
1) If you are executing in the context of an existing request from a user, prepare request parameters using the
- Its constructor's first parameter is the request to derive from.
- Its constructor's second parameter is an array of API parameters that is the same as if making the request over the web.
- Its constructor's third parameter is optional, specify
trueto treat the API call as a POST when the API module you're invoking requires POST requests.
This sample code issues the 'allpages' list query starting at the letter 'M'. This is a simple query, not requiring a user or POST.
$params = new DerivativeRequest( $this->getRequest(), // Fallback upon $wgRequest if you can't access context. array( 'action' => 'query', 'list' => 'allpages', 'apnamespace' => 0, 'aplimit' => 10, 'apprefix' => 'M' ) );
If you need to provide an edit token as an API parameter when making edits or other changes, you can get the edit token like so:
$user = $this->getUser(); // Or User::newFromName, etc. $token = $user->getEditToken();
2) Create an
ApiMain instance. Then execute the API request. Because the parameter is a
ApiMain will not execute any formatting printers, nor will it handle any errors. A parameter error or any other internal error will cause an exception that may be caught in the calling code.
$api = new ApiMain( $params ); $api->execute();
Important: If you want to create or edit pages, you have to pass
true as a second parameter when creating the
$api = new ApiMain( $params, true ); // default is false $api->execute();
3) Get the resulting data array.
$data = $api->getResult()->getResultData();
$api = new ApiMain( new DerivativeRequest( $this->getRequest(), // Fallback upon $wgRequest if you can't access context array( 'action' => 'edit', 'title' => $talk->getFullText(), 'appendtext' => ( $talk->exists() ? "\n\n" : '' ) . wfMsgForContent( 'newsectionheaderdefaultlevel', $params['subject'] ) . "\n\n" . $params['text'], 'token' => $params['token'], 'summary' => wfMsgForContent( 'wikilove-summary', $wgParser->stripSectionName( $params['subject'] ) ), 'notminor' => true ), true // treat this as a POST ), true // Enable write. ); $api->execute();
The example above creates a
This "inherits" some of the original request, such as IP and request headers that are set when MediaWiki is doing an action on behalf of a user, typically when handling a web request.
If there is no user request context, for example when invoking the action API from a system process, or if you want to make a completely separate internal request, then you can use
FauxRequest for write operations without passing request context causes bug T36838.
UsageException. If its possible for your code to send an invalid parameter, you should probably call the API from inside a try/catch block
- wikitech:Debugging in production#Debugging api.php in shell for how to debug api.php in WMF production