I am in the process of setting up my first apigility project and so far it is going well. I'm having some issues with the routing and how to set it up though.
Suppose I have songs, albums and artist (fictitious example for this question only). I want to do a structure like this:
/artists (GET, POST, PUT, PATCH, DELETE)
/albums (GET, POST, PUT, PATCH, DELETE)
/songs (GET, POST, PUT, PATCH, DELETE)
Pretty easy so far. I have filters on those end-points so I can say:
/artists/?style=jazz
/albums/?year=2012
etc...
Now, I also want to include child end-points like this:
/artist/12345/albums (GET) - get all albums for artists with id 12345
/artist/12345/songs (GET) - get all songs for artists with id 12345
/albums/98765/songs (GET) - get all songs for album with id 98765
How do I set this up in a proper way in apigility?
I started by creating a separate service ArtistAlbum, with route /artists/:artist_id/albums and then changing the entity from ArtistAlbumEntity to AlbumEntity (it is basically that) and the collection from ArtistAlbumCollection to AlbumCollection. The route identifier name is set to artist_album_id though, which I will never use. You cannot delete that though.
This ways feels a bit hacky to be honest.
In effect, the above route /artists/:artist_id/albums is actually an alias for /albums/?artist_id=:artist_id. It is a sort of filter.
How do I implement something like this in a proper way?
You can distinguish different types of relationships between your (REST) classes/resources.
association
aggregation
composition
This is nicely explained here on this blogpost but those relationship types are also nicely defined on Wikipedia.
Understanding those types of relationships will help you on how to define (the hierarchy in) your model and it can also help in organizing your urls. I won't go into details here because you can already find a lot of information on relationship types, nested resources and and rest design on stackoverflow. I would only be repeating things. For example here, here, here, here or here but you can surely find more yourself.
Simply search for: "nested resources REST design"
There is not one commonly accepted solution for url design. People often have personal preferences on how to deal with this. Some people (I do not agree) even believe a proper rest model should not use nested (so no hierarchical) urls but a flat structure for all resources.
Consider the following Zend 2 router configuration in module.config.php
<?php
[
'router' => [
'routes' => [
'api.rest' => [
'type' => 'Hostname',
'options' => [
'route' => 'api.site.dev'
],
'may_terminate' => false,
'child_routes' => [
'homeRoute' => [
'type' => 'Literal',
'options' => [
'route' => '/',
'defaults' => [
'controller' => 'Api\\V1\\Rest\\Welcome\\Controller',
]
],
'may_terminate' => true,
'child_routes' => [
'appRoute' => [
'type' => 'Literal',
'options' => [
'route' => 'app',
],
'may_terminate' => false,
'child_routes' => [
'postsRoute' => [
'type' => 'Literal',
'options' => [
'route' => '/posts',
'defaults' => [
'controller' => 'Api\\V1\\Rest\\Post\\Controller',
],
],
]
]
]
],
]
]
],
]
]
];
Then using Apigility, if you want the route name to run Post resource located at api.site.dev/app/posts, just call it with api.rest/homeRoute/appRoute/postsRoute
Eg: Use the URL Plugin like this $this->url('api.rest/homeRoute/appRoute/postsRoute');
Don't know if it works with older versions but actually I use Apigility 1.4.1 and it works like a charm
Related
I am using the Yii2 Framework and I am translating all texts of buttons, labels, messages, etc.
Then I read this article http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html that shows how to do it automatically but I don't understand it.
I want to translate to Spanish from Argentina: es-AR or at least to any Spanish.
So I think I need to change from en-US to es-AR but I would like to know which files should I change.
Also I am using the great Gii code generator where I can see a checkbox called Enable I18N.
I watched these files but I am not sure if I am looking the right files:
vendor/yiisoft/yii2/base/Application.php
vendor/yiisoft/yii2/i18n/I18N.php
common/config/main-local.php
Add language propery and i18n component in application config. For advanced application template in common/config/main.php
return [
'language' => 'es-AR',
...
'components' => [
...
'i18n' => [
'translations' => [
'app*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '#app/messages',
],
],
],
...
],
]
Use Yii::t() for all user messages (model labels, views, error messages etc).
echo \Yii::t('app', 'Friend');
Create directory messages/es-AR. Create file app.php in this directory and add translations
return [
'Friend' => 'Amigo',
'Girl' => 'Сhica',
...
];
Try to look into the official documentation, it is best tutorial for you. http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html
Also, look at this answer yii2 basic multiple language
You can change default language by changing 'language' parameter of your main configuration file. Like this:
return
[
// set target language to be English
'language' => 'en-US',
]
Where instead 'en-US' you must to set needed locale code, e.g. 'es-AR'
Is it possible to use two or more caching storage in yii2 framework? I already setup a Memcache for my web app but I wanted also to use a FileCache since I will be dealing with a large chunk of data.
hope someone can help. Thanks!
You can set any cache. Just set it at config file.
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
'memCache' => [
'class' => 'MEMCACHE CLASS HERE',
],
.... ANY cache you want ...
]
You can register multiple cache application components. The component named cache is used by default by many cache-dependent classes (e.g. yii\web\UrlManager).
Official link
'components' => [
'cache' => [
'class' => 'yii\caching\MemCache',
],
'fileCache' => [
'class' => 'yii\caching\FileCache',
]
]
I've made a REST API with the Yii2 basic template. I've made some changes to the webconfig so I could use links like web/users and web/users/1. It works fine but I couldn't access the web/index anymore. So i've added some more rules to the UrlManager.
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
//basic/web
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:[\w\-]+>/<action:[\w\-]+>/<id:[\d]+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
//basic/web/users
['class' => 'yii\rest\UrlRule', 'controller' => ['user', 'car']],
//basic/web/countries
//Id is een string, vandaar de tokens
['class' => 'yii\rest\UrlRule', 'controller' => 'country', 'tokens' => ['{id}' => '<id:\\w+>']],
],
],
With the above code I can acces web/index. I could also access web/users to get a list with users. but I can't acces web/users/1. it gives an 404 error.
edit:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
//basic/web
/*
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:[\w\-]+>/<action:[\w\-]+>/<id:[\d]+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
*/
//basic/web/users
['class' => 'yii\rest\UrlRule', 'controller' => ['user', 'car', 'site']],
//basic/web/countries
//Id is een string, vandaar de tokens
['class' => 'yii\rest\UrlRule', 'controller' => 'country', 'tokens' => ['{id}' => '<id:\\w+>']],
],
],
I've changed it like this. Now I can acces web/sites because of pluralize.
But if I go to web/sites/about for example, it will give an 404 error again. So it's not the best solution
I think it won't be easy to maintain a REST API and HTML webpages within the same config file. For example cookies and session usually are disabled with REST as recommended by its stateless nature while you may need both to authenticate a user within a classic HTML page.
I would recommend modifying your app structure and having your REST API implemented as an independent module with its own routing configuration and maybe its own Entry Script without missing with the web entry.
A better structure may look like this : (from the tutorial linked below)
+ web
+ config
+ controllers
...
+ api
+ config
+ modules
+ v1
+ controllers
.htaccess
index.php
Then you'll be able to open your HTML files within web/sites/about while retrieving your resources within api/users/1. Each entry may host its own controllers and own models or they may both share #app/models. Check this step by step tutorial to see how to implement it :
Creating a REST API for
Yii2-basic-template
- by Joachim Werner
You may also check api and auth folders in this app where both are independent REST APIs.
I am working on yii2 framework.This is new framework for me. I want to setup multiple language. I tried some way but didn't got success. Can anyone please suggest me simplest way ? What should i have to do ?
I am using this reference link
http://techisworld.com/working-with-multiple-languages-app-in-yii2-framework-using-i18n-system.html
1- For dynamic content (coming from database) I usually use this:
webvimark/multilanguage
It is very easy and isolated from your app DB tables structure and code, that gives flexibility in adding/removing languages at the long term.
2- For static content (words inside the markup) in frontend as an example:
add the lines in your frontend/config/main.php file,
'i18n' => [
'translations' => [
'app*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '#app/messages',
'sourceLanguage' => 'en_US',
'fileMap' => [
'app' => 'app.php'
],
],
],
],
Put you translation file app.php file inside /frontend/messages, as any Yii translation file it returns an array of translations in a key-value pairs.
Then you can translate your static content using:
Yii::t('app', 'text to be translated')
I am beginner working with Zend. I have seen may_terminate in module route configuration. I don't understand what it is for. According to ZF2 official docs,
the option “may_terminate” hints to the router that no other
segments will follow it.
Still I don't get the meaning of no other segments will follow it. What is it here? Can anyone please explain it with small example?
The may_terminate option will indicate to the router that 'this' route is able to be matched solely on the value of its route; even when it defines child_routes.
Consider the following example route configuration.
'router' => [
'routes' => [
'home' => [
'type' => 'literal',
'options' => [
'route' => '/home',
],
'may_terminate' => false,
'child_routes' => [
'foo' => [
'type' => 'literal',
'options' => [
'route' => '/foo',
],
],
],
],
],
],
There is some ambiguity in the above configuration, which only occurs with routes that define children. Do we want to allow our users to match on two routes or just one?
We could allow matching on just the /home part; which would mean we have two routes both
/home and /home/foo or we might only want to allow /home/foo.
This is where the may_terminate option is used. If we browsed to /home in our browser, when the routing occurs the router cannot regard the home route as a matchable route as may_terminate = false. In ZF2 terminology the router cannot "terminate" at this route and continues on searching for a match into the child_routes, which will fail and a 404 error will be raised.
So by modifying the value of the may_terminate option in the above example, we can change the routes that can be matched on.
may_terminate = true
home
home/foo
may_terminate = false
home/foo