Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Map with User Resource
If the data source has a set of "user_" prefix key and `user` property, It auto combine field to UserResource and Map to user property of the current resource

Manual mapping
Use We can override or manual mapping fields use Setter and Getter methods. Setter method uses to control input data, Getter control the output. The naming convention of setter & getter methods follow examples bellowAll field

Resource's property nameSetter methodGetter method
namesetName()getName()
short_descriptionsetShortDescription()getShortDescription()
is_approvedsetIsApproved()getIsApproved()

 

All fields query from the database table has a String data type. But Native App requires to return exactly data type in JSON.
Override "loadMetadataSchema" method of resource to control the response data type.


Following is an example:

Code Block
<?php

/* A lot of code above */
class PostResource extends ResourceBase
{
/* ... */
	protected function loadMetadataSchema(ResourceMetadata $metadata = null)
	{
		parent::loadMetadataSchema($metadata);
		$this->metadata
		    ->mapField('title', ['type' => ResourceMetadata::STRING])
		    ->mapField('description', ['type' => ResourceMetadata::STRING])
		    ->mapField('item_id', ['type' => ResourceMetadata::INTEGER])
		    ->mapField('module_id', ['type' => ResourceMetadata::STRING])
		    ->mapField('is_approved', ['type' => ResourceMetadata::BOOL])
		    ->mapField('is_sponsor', ['type' => ResourceMetadata::BOOL])
		    ->mapField('is_featured', ['type' => ResourceMetadata::BOOL])
		    ->mapField('is_liked', ['type' => ResourceMetadata::BOOL])
		    ->mapField('is_friend', ['type' => ResourceMetadata::BOOL])
		    ->mapField('post_status', ['type' => ResourceMetadata::INTEGER]);
	}
}

...

Code Block
<?php 

/* A lot of code above */
class PostResource extends ResourceBase
{
/* ... */
/**
Get detail url
@return string
*/
	public function getLink()
	{
		return \Phpfox::permalink('post', $this->id, $this->title);
	} 
	public function getImage()
	{
		return Image::createFrom([
			'file' => $this->rawData['image_path'],
			'server_id' => $this->rawData['server_id'],
			'path' => 'post.url_photo',
			'suffix' => '_1024'
		]);
	} 
/**
@return array
@throws \Exception
*/
	public function getCategories()
	{
		return $this->categories;
	} 
	public function getTags()
	{
		return $this->tags;
	} 
	public function getText()
	{
		if (empty($this->text) && !empty($this->rawData['text'])) {
			$this->text = $this->rawData['text'];
		}
		TextFilter::pureHtml($this->text, true);
		return $this->text;
	}
    /* ... */
} 

Define API service to handle API requests

...

Code Block
<?php
namespace Apps\Posts\Service; 
/* ... */ 
class PostApi extends AbstractResourceApi implements ActivityFeedInterface, MobileAppSettingInterface
{
/**
@var Post
*/
	private $postService; 
	/**
	@var Process
	*/
	private $processService; 
	/**
	@var Category
	*/
	private $categoryService; 
	/**
	@var \User_Service_User
	*/
	private $userService; 

	public function __construct()
	{
		parent::__construct();
		$this->postService = Phpfox::getService("post");
		$this->categoryService = Phpfox::getService('post.category');
		$this->processService = Phpfox::getService('post.process');
		$this->userService = Phpfox::getService('user');
	}
    /* .. */
}

In  

Describe the example above:

  • The PostApi class extent AbstractResourceApi to reuse resource base featureall features
  • Implement ActivityFeedInterface to able display the resource to Activity Feed page
  • Implement MobileAppSettingInterface to register more screens and actions to Mobile App without change code

Now you need to implement all abstract method from parent class and interfaces.
The initial code of your service would look like bellowlike below:


PostApi.php  

Code Block
<?php 

namespace Apps\Posts\Service;
/* ... */ 
class PostApi extends AbstractResourceApi implements ActivityFeedInterface, MobileAppSettingInterface
{
	/**
	 * Get list post
	 *
	 * @param array $params
	 * @return array|mixed
	 * @throws ValidationErrorException
	 */
	function findAll($params = [])
	{
	    /* ... */
		$aItems = $this->browse()->getRows();
		if ($aItems) {
			$this->processRows($aItems);
		} 
		return $this->success($aItems);
	} 
	
    /**
	 * @param $params
	 * @return array|bool
	 */
	function findOne($params)
	{
		$id = $this->resolver->resolveId($params);
		/* ... */
		return $this->success($resource->loadFeedParam()->toArray());
	} 

	public function delete($params)
	{
		$id = $this->resolver->resolveId($params); 
		$result = Phpfox::getService('post.process')->delete($id);
		if ($result !== false) {
			return $this->success([
				'id' => $id
			]);
		}
		return $this->error('Cannot delete post'); 
	} 
	
    /**
	 * Get Create/Update document form
	 * @param array $params
	 * @return mixed
	 * @throws \Exception
	 */
	public function form($params = [])
	{
		/** @var PostForm $form */
		$form = $this->createForm(PostForm::class, [
			'title' => 'adding_a_new_post',
			'method' => 'post',
			'action' => UrlUtility::makeApiUrl('post')
		]);
		/* ... */
		return $this->success($form->getFormStructure());
	} 
	/**
	 * Create a new Post API
	 * @param array $params
	 * @return array|bool|mixed
	 */
	public function create($params = [])
	{
	  /* ... */
	} 
	
    /**
	 * Update a post
	 *
	 * @param $params
	 * @return mixed
	 */
	public function update($params)
	{
	 /* ... */
	} 

	/**
	 * @param $id
	 * @param bool $returnResource
	 * @return array|PostResource
	 */
	function loadResourceById($id, $returnResource = false)
	{
		$item = Phpfox::getService("post")->getPost($id); 
		if (empty($item['post_id'])) {
			return null;
		}
		if ($returnResource) {
			return $this->processOne($item);
		}
		return $item;
	} 
	/**
	 * Update multiple document base on document query
	 *
	 * @param $params
	 * @return mixed
	 * @throws \Exception
	 */
	public function patchUpdate($params)
	{
		/* ... */
	} 


	/**
	 * Get for display on activity feed
	 * @param array $feed
	 * @param array $item detail data from database
	 * @return array
	 */
	public function getFeedDisplay($feed, $item)
	{
		/* ... */
	} 

	/**
		 * Create custom access control layer
	 */
	public function createAccessControl()
	{
		$this->accessControl = new PostAccessControl($this->getSetting(), $this->getUser()); 
		/* ... */
	} 
	
    /**
	 * @param array $params
	 * @return mixed
	 */
	function searchForm($params = [])
	{
		$this->denyAccessUnlessGranted(PostAccessControl::VIEW);
		/** @var PostSearchForm $form */
		$form = $this->createForm(PostSearchForm::class, [
			'title' =>'search',
			'method' => 'GET',
			'action' => UrlUtility::makeApiUrl('post')
		]); 
		return $this->success($form->getFormStructure());
	} 

	public function getRouteMap()
	{
		/* ... */
	} 
	
    /**
	 * @param $param
	 * @return MobileApp
	 */
	public function getAppSetting($param)
	{
		/* ... */
	}
}

...

Code Block
<?php

/* ... */
Phpfox::getLib('module')
	->addAliasNames('post', 'Posts')
	->addServiceNames([
		    
    // New API service register here
	'mobile.post_api' => Service\PostApi::class,
	'mobile.post_category_api' => Service\PostCategoryApi::class, 
		
    // Other Services of the app
	'post.category' => Service\Category\Category::class,
	'post.category.process' => Service\Category\Process::class,
	'post.api' => Service\Api::class,
	'post' => Service\Posts::class,
	'post.browse' => Service\Browse::class,
	'post.cache.remove' => Service\Cache\Remove::class,
	'post.callback' => Service\Callback::class,
	'post.process' => Service\Process::class,
	'post.permission' => Service\Permission::class,
	]);
/* ... */

...

Code Block
<?php

class PostApi extends AbstractResourceApi implements ActivityFeedInterface, MobileAppSettingInterface
{
    /**
    This method allow you add custom route for APIs
    Return an array with key is routing rule and mapping condition
    In this case, 'mobile/post/search-form' map to `searchForm` method
    */
    public function __naming()
    {
	    return [
		    'post/search-form'=> [
		    'get'=>'searchForm'
		    ]
	    ];
    }

    /**
    @param array $params
    @return mixed
    */
    function searchForm($params = [])
    {
	    $this->denyAccessUnlessGranted(PostAccessControl::VIEW);
	    /** @var PostSearchForm $form */
	    $form = $this->createForm(PostSearchForm::class, [
		    'title' =>'search',
		    'method' => 'GET',
		    'action' => UrlUtility::makeApiUrl('post')
		    ]); 
	    return $this->success($form->getFormStructure());
    }
}

You can download the full sample code of Post API service.

...