Is it possible to serve images with Wordpress Rest API endpoint based on attachment ID?
I mean, if the following link was pasted in browser, i should get the real image instead of JSON response. http://demo.dev/wp-json/custom/v1/image/80
I need it for REST-full Wordpress theme, based on Vue.js and Metabox.io plugin with mb REST API add-on. My metaboxes contain lots of repeatable, nested groups and they output only image ids in array.
I added endpoint in functions.php:
add_action( 'rest_api_init', function () {
register_rest_route( 'custom/v1', '/image/(?P<id>\S+)', [
'methods' => WP_REST_Server::READABLE,
'callback' => 'custom_get_image',
'args' => [
'id'
],
] );
} );
if ( !function_exists('custom_get_image') ){
function custom_get_image($data){
$id="";
$src= get_template_directory_uri().'/img/placeholder.png';
if ( isset($data['id']) ){
$image = wp_get_attachment_image_src($data["id"], 'medium');
if($image){
$src=$image[0];
}
}
return $src;
}
}
Currently, i solved the problem by creating an extra vue component, which calls the API and inserts the file url. However, i wanted to have an API endpoint, that can be added directly to img "src" or div "background-image" without extra ajax call.
<template>
<img :src="src">
</template>
<script>
import axios from 'axios';
export default {
props: ['id'],
data: function() {
return {
src: 'http://demo.dev/wp-content/themes/vue-theme/static/img/placeholder.jpg',
};
},
methods: {
getSrc(id) {
//var id = 83;
var endpoint = 'http://demo.dev/wp-json/custom/v1/image/';
var url = endpoint + id;
axios
.get(url)
.then(response => {
this.src = response.data;
})
.catch(error => {});
},
},
mounted: function() {
this.$nextTick(function() {
this.getSrc();
});
},
};
</script>
I found working solution in php (may not be the best, wp-load.php must be required). I added a helper script that takes attachment id as a query parameter and redirects to image url:
<?php
$path = preg_replace('/wp-content.*$/','',__DIR__);
define( 'WP_USE_THEMES', false );
require( $path.'\wp-load.php' );
$id= isset($_GET['id']) ? $_GET['id'] : '';
$size= isset($_GET['size']) ? $_GET['size'] : 'fullsize';
$url=$_SERVER['REQUEST_URI'];
$src=$url."/wp-content/themes/vue-theme/static/img/placeholder.jpg";
if($id){
$image = wp_get_attachment_image_src( $id, $size );
if($image){
$src=$image[0];
}
}
header("Location: ".$src);
die();
?>
Now i can add url with id like this:
<div v-for="item in items" class="bg-block" v-bind:style="{ backgroundImage: 'url('+ 'http://demo.dev/wp-content/themes/vue-theme/helpers/service.php?size=medium&id=' + item.imgId +')'></div>;