With service contracts usage (API interfaces), it will be possible to expose custom module functionality as web API just by adding config etc/webapi.xml
. Improved capabilities for integration with 3rd party systems based on service contracts will be added in the future, as well as queue support.
Another benefit, if there is another module dependent on your module, it can just rely on service interfaces. This reduces coupling between modules and minimizes risk of accidental breaking of dependent module.
Sometimes i have to create lots of api models, so I created this script Smiley Happy
This one generates the model
<?php
$json = '{
"provider": "OMNIVA",
"type": "POST_OFFICE",
"name": "Abja-Paluoja postkontor",
"city": "Abja vald",
"country": "ESTONIA",
"availability": "E,T,K,R 8:30-13:00 ja 13:30-16:00;N 8:30-13:00 ja 13:30-18:00;L,P suletud",
"destination_id": 69400,
"street_address": "P\u00e4rnu maantee 8",
"postal_code": "69400",
"coordinate_x": "58.1264356146443",
"coordinate_y": "25.3548298784361",
"temp_service_hours": null,
"temp_service_hours_until": null,
"temp_service_hours_2": "25.03.2016 suletud",
"temp_service_hours_2_until": "25.03.2016",
"comment_et": null,
"comment_en": null,
"comment_ru": null,
"comment_fi": null,
"comment_lv": null,
"comment_lt": null
}';
$name = 'Location';
$vendor = 'Makecommerce';
$module = 'Omniva';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$json = $_POST['json'];
$name = $_POST['name'];
$vendor = $_POST['vendor'];
$module = $_POST['module'];
$base = "
namespace $vendor\\$module\\Model;
use Magento\\Framework\\Model\\AbstractExtensibleModel;
use $vendor\\$module\\Api\\Data\\{$name}Interface;
class {$name} extends AbstractExtensibleModel implements {$name}Interface
{";
$json = json_decode($json, true);
$base .= ' ';
foreach ($json as $key => $value) {
$value = strtoupper(preg_replace('|([a-z])([A-Z])|', '$1_$2', $key));
// $base .= 'const ';
// $base .= $value;
// $base .= " = '".$key."';";
// $base .='
// ';
$json[$key] = $value;
}
// $base .= '
// /**#@-*/
// ';
foreach ($json as $key => $value) {
$base .= '
/**
* {@inheritdoc}
*/
public function get';
$base .= ucfirst(preg_replace_callback("/_([a-z])?/", function($match){ return strtoupper($match[1]); },$key));
$base .='()
{
return $this->getData(self::'.$value.');
}
';
}
foreach ($json as $key => $value) {
$converted = preg_replace_callback("/_([a-z])?/", function($match){ return strtoupper($match[1]); },$key);
$base .= '
/**
* {@inheritdoc}
*/
public function set';
$base .= ucfirst($converted);
$base .='( $'.$converted.' )
{
return $this->setData(self::'.$value.', '. $converted.');
}
';
}
$base .= '
}';
echo "<pre>";
echo $base;
die;
}?>
<form method="POST">
<label for="json">Json</label>
<textarea id="json" name="json"></textarea><br>
<label for="name">Name(before Interface) $name.Interface</label>
<input type="text" name="name" id="name"><br>
<label for="vendor">Vendor $vendor\$module\Api\Data</label>
<input type="text" name="vendor" id="vendor"><br>
<label for="module">Module $vendor\$module\Api\Data</label>
<input type="module" name="module" id="module"><br>
<input type="submit">
</form>
And this one generates the Interface
<?php
$json = '{
"provider": "OMNIVA",
"type": "POST_OFFICE",
"name": "Abja-Paluoja postkontor",
"city": "Abja vald",
"country": "ESTONIA",
"availability": "E,T,K,R 8:30-13:00 ja 13:30-16:00;N 8:30-13:00 ja 13:30-18:00;L,P suletud",
"destination_id": 69400,
"street_address": "P\u00e4rnu maantee 8",
"postal_code": "69400",
"coordinate_x": "58.1264356146443",
"coordinate_y": "25.3548298784361",
"temp_service_hours": null,
"temp_service_hours_until": null,
"temp_service_hours_2": "25.03.2016 suletud",
"temp_service_hours_2_until": "25.03.2016",
"comment_et": null,
"comment_en": null,
"comment_ru": null,
"comment_fi": null,
"comment_lv": null,
"comment_lt": null
}';
$name = 'Location';
$vendor = 'Makecommerce';
$module = 'Omniva';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$json = $_POST['json'];
$name = $_POST['name'];
$vendor = $_POST['vendor'];
$module = $_POST['module'];
$base = "
namespace $vendor\\$module\\Api\\Data;
interface {$name}Interface
{".
/**#@+
* Constants defined for keys of array, makes typos less likely
*/
"";
$json = json_decode($json, true);
$base .= ' ';
foreach ($json as $key => $value) {
$value = strtoupper(preg_replace('|([a-z])([A-Z])|', '$1_$2', $key));
// $base .= 'const ';
// $base .= $value;
// $base .= " = '".$key."';";
// $base .='
// ';
$json[$key] = $value;
}
// $base .= '
// /**#@-*/
// ';
foreach ($json as $key => $value) {
$base .= '
/**
*
* @return string|null
*/
public function get';
$base .= ucfirst(preg_replace_callback("/_([a-z])?/", function($match){ return strtoupper($match[1]); },$key));
$base .='();
';
}
foreach ($json as $key => $value) {
$converted = preg_replace_callback("/_([a-z])?/", function($match){ return strtoupper($match[1]); },$key);
$base .= '
/**
*
* @param string|null $'.$converted.'
* @return $this
*/
public function set';
$base .= ucfirst($converted);
$base .='( $'.$converted.' );
';
}
$base .= '
}';
echo "<pre>";
echo $base;
die;
}
?>
<form>
<label for="json">Json</label>
<textarea id="json" name="json"></textarea><br>
<label for="name">Name(before Interface) $name.Interface</label>
<input type="text" name="name" id="name"><br>
<label for="vendor">Vendor $vendor\$module\Api\Data</label>
<input type="text" name="vendor" id="vendor"><br>
<label for="module">Module $vendor\$module\Api\Data</label>
<input type="module" name="module" id="module"><br>
<input type="submit">
</form>
Best Answer
@api
, not necessarily service contract interfaces, but preferably. If interface is requested in dependencies, Magento object manager resolves actual model to be instantiated according to preferences declared indi.xml
(since interface itself cannot be instantiated). See official documentation