Page tree

Versions Compared

Key

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

...

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]);
	}
}

Develop restful resource APIs

...

Code Block
<?php 

namespace Apps\Posts\Api\Resource; 
/* ... */ 
class PostResource extends ResourceBase
{
	/**
	Define the unique resource name
	*/
	const RESOURCE_NAME = "post"; 
	const TAG_CATEGORY = 'post';
	public $resource_name = self::RESOURCE_NAME;
	public $module_name = 'post'; 
	/**
	@var string Post's title mapping
	*/
	public $title; 
	/**
	@var string Post's description mapping
	*/
	public $description; 
	/**
	@var string Post's parent module id
	*/
	public $module_id; 
	/**
	@var int Post's parent id
	*/
	public $item_id; 
	/**
	@var bool Status of the post
	*/
	public $is_approved; 
	/**
	@var bool sponsor status of the post
	*/
	public $is_sponsor; 
	/**
	@var bool sponsor status of the post
	*/
	public $is_featured;
	public $is_liked;
	public $is_friend;
	public $post_status;
	public $text;

Override ResourceBase::loadMetadataSchema() method to define database for each field when mapping

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]);
	}
}


If mapping base on the field's name and data type are not enough. We can override the property's value via getting/setting method

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

 

API Service is similar to PHPFOX App's Service, you can extend from the parent class to minimal and reuse code
Create PostApi.php within Service folder
PostApi.php

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 example above

...

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)
	{
		/* ... */
	}
}

Register services and resources

...

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,
	]);
/* ... */

Next step, you need to create hook "mobile_api_routing_registration.php" in the hooks folder.
mobile_api_routing_registration.php

...

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());
}
}

...