I'm new to symfony and the api platform and I want to develop an api with specific routes.
I'm looking to do is create a post query with nested resources to add relationships between tables.
example: I have 3 tables (users, periods, articles). I need to create a post request to add a new post with the following structure:
URL: api/:userid/:period/item
:userID = user ID
:period = Period name
name = element name
This request must create a new article in my "articles" table by adding the identifier, the name of the period and the name of the article entered as a parameter.
So my question is how do I pass multiple parameters in my path and save them in the database using the api platform?
Thanks in advance !
You can use custom routes with API platform, which allow you to create a route that correspond to a custom query => but you need to have these data before setting them in your Api platform path.
First of all, I would use the query builder to create the query you need get the data you need, then you can use your method directly in your entity (more here https://api-platform.com/docs/core/controllers/).
You can set the route you want inside of the path of the route and set the different arguments you need like this:
'path' => '/books/{id}/publication'
here id is your argument coming from your repository function.
Related
I want to support pagination in my RESTful API.
My API method should return a JSON list of product via http://localhost/products/v1/getproductsbycategory, there are potentially thousands of products, and I want to page through them, so my request should look something like this:
public function getProductsByCategory($product_id,$page){
$perPage=5;
$start=($page-1)*$perPage;
$stmt=$this->conn->prepare("SELECT id,product,description,destination_url,expiry_type,savings,expiry,title,last_updated_on FROM products WHERE product_id=? ORDER BY last_updted_on DESC LIMIT $start ,$perPage");
$stmt->bind_param('i',$category_id);
$stmt->execute();
$productbycategory=$stmt->get_result();
$stmt->close();
return $productbycategory;
}
}
Firstly, in a RESTful call, the URL should ideally be noun-based and not verbs. We are using HTTP verbs (GET, PUT, POST, etc) to do an action on a noun - product in your case.
So, the URL should be http://localhost/products/v1/category
This effectively means you are GETting product of type v1 based on category. To get a given page number, simply add it as a query parameter -
http://localhost/products/v1/category?page=1
and handle it accordingly in your GET implementation corresponding to localhost/products/v1/category
Hope this helps.
Pagination has nothing to do with the JSON format per se - it's all about the query string in the URL and how the server interprets that.
Expanding on #Sampada's answer, you can have a URL like
http://localhost/products/v1/category?pageSize=5&pageNumber=2
and then you'll simply pick the corresponding elements on the server side (consider whether you'll want 0 or 1-based index for the pageNumber), and return them.
Additionally you can wrap this collection in an object that also provides links as to navigate to the previous/next/specific page - see HATEOAS & Richardson's Maturity Model level 3.
I recently started experimenting with the REST API for SharePoint 2013 Foundation and I am trying to return all entries in a list. My GET request returns the data I am looking for, but the IDs used to identify the columns in the list are not helpful for identifying what the information is (see images below). The column IDs between 'Title' and 'ID', in the second image, are a jumble of characters.
SharePoint List View
Response Data
Is there any way to configure the list to use the column names as IDs? Also, is there some significance to the characters currently used as IDs?
You will need to make a second request to get a listing of columns that includes the InternalName and the Title which is what you are trying to reference:
You can use this REST call:
_api/web/lists/GetByTitle('Project Details')/fields
or you can use CSOM:
using (ClientContext context = new ClientContext(url))
{
List list = context.Web.Lists.GetByTitle("Project Details");
context.Load(list, l => l.Fields);
context.ExecuteQuery();
foreach(Field field in list.Fields)
{
Console.WriteLine(field.Title);
Console.WriteLine(field.InternalName);
}
}
SharePoint automatically generates the InternalName and it is a read-only field, at least using REST. It'll be easier to get the Field Data to correlate the InternalName to the Title than changing the values.
The column you are referring to, between Title and Id, is the ID of the content type associated to the item. It is not a column ID.
The SharePoint REST API is OData compliant, so you can use the $select parameter to query for the neccesary fields.
http://server/site/_api/web/lists('guid')/items?$select=Column1,Column2
Please be aware though, lookup fields need to be expanded as well, otherwise you get only the Id of the lookup item.
http://server/site/_api/web/lists('guid')/items?$select=LookupColumn&$expand=LookupColumn/Title
In Keystone admin list view the handy download link exports all list items in a CSV file, however, if some of the fields are of Relationship type, the exported CSV contains Mongo ObjectIDs instead of nmeaningful strings (name, title, etc) which would be useful.
How can one force the ObjectIDs to be mapped / replaced by another field?
Keystone has an undocumented feature that allows you to create your own custom CSV export function. This feature was added back in April (see KeystoneJS Issue #278).
All you need to do is add a method to the schema called toCSV. Keystone will inject any of the following dependencies when specified as arguments to this method.
- req (current express request object)
- user (currently authenticated user)
- row (default row data, as generated without custom toCSV())
- callback (invokes async mode, must be provided last)
You could, for example, use the Mongoose Model.Populate method to replace the Object Ids of any relationship field with whatever data you want.
Assume you have a Post list with an author field of Types.Relationship to another list (let's say User) which has a name field. You could replace the author Object Id with the author's name (from the User list) by doing the following.
Post.schema.methods.toCSV = function(callback) {
var post = this,
rtn = this.toJSON();
this.populate('author', function() {
rtn.author = post.author.name; // <-- author now has data from User list
callback(null, rtn);
});
};
.toCSV() will be called for every document returned with the Model as the context. When used asynchronously (as above) you should return a JSON representation of the new CSV data by passing it as the second argument of the callback. When using it synchronously simply return the updated JSON object.
I want URL manager to process URL with the company name with my CompanyController. To do so dynamically I should get company names from my database.
Now I have such rule (but it's not dynamic):
'<alias:(vector|karnasch|tecnomagnete|ruko|bds-maschinen|exact)>' => 'company/view',
(vector|karnasch|tecnomagnete|ruko|bds-maschinen|exact) --> data to this line I want to get from database.
I can get this data (manually establish connection to db), but maybe it's another more beautiful solution with help of Yii functional. Thanks!
You can always create your custom UrlRuleclass. If you only want to parse incoming URLs you can simply return false from the createUrl() method. In the parseUrl() method you query the DB for your company names and inspect if the current URL matches. If not, you simply return false again.
Well, you don't need to do this, you just have to define the right pattern, e.g. :
'contact' => 'contact/form',
// other rules should be set before this one
'<alias:[-\w]+>' => 'company/view',
http://www.yiiframework.com/doc/guide/1.1/en/topics.url#using-named-parameters
Question
How do I return different results for the same resource?
Details
I have been searching for some time now about the proper way to build a RESTful API. Tons of great information out there. Now I am actually trying to apply this to my website and have run into a few snags. I found a few suggestions that said to base the resources on your database as a starting point, considering your database should be structured decently. Here is my scenario:
My Site:
Here is a little information about my website and the purpose of the API
We are creating a site that allows people to play games. The API is supposed to allow other developers to build their own games and use our backend to collect user information and store it.
Scenario 1:
We have a players database that stores all player data. A developer needs to select this data based on either a user_id (person who owns the player data) or a game_id (the game that collected the data).
Resource
http://site.com/api/players
Issue:
If the developer calls my resource using GET they will receive a list of players. Since there are multiple developers using this system they must specify some ID by which to select all the players. This is where I find a problem. I want the developer to be able to specify two kinds of ID's. They can select all players by user_id or by game_id.
How do you handle this?
Do I need two separate resources?
Lets say you have a controller name 'Players', then you'll have 2 methods:
function user_get(){
//get id from request and do something
}
function game_get(){
//get id from request and do something
}
now the url will look like: http://site.com/api/players/user/333, http://site.com/api/players/game/333
player is the controller.
user/game are the action
If you use phil sturgeon's framework, you'll do that but the url will look like:
http://site.com/api/players/user/id/333, http://site.com/api/players/game/id/333
and then you get the id using : $this->get('id');
You can limit the results by specifying querystring parameters, i.e:
http://site.com/api/players?id=123
http://site.com/api/players?name=Paolo
use phil's REST Server library: https://github.com/philsturgeon/codeigniter-restserver
I use this library in a product environment using oauth, and api key generation. You would create a api controller, and define methods for each of the requests you want. In my case i created an entirely seperate codeigniter instance and just wrote my models as i needed them.
You can also use this REST library to insert data, its all in his documentation..
Here is a video Phil threw together on the basics back in 2011..
http://philsturgeon.co.uk/blog/2011/03/video-set-up-a-rest-api-with-codeigniter
It should go noted, that RESTful URLs mean using plural/singular wording e.g; player = singular, players = all or more than one, games|game etc..
this will allow you to do things like this in your controller
//users method_get is the http req type.. you could use post, or put as well.
public function players_get(){
//query db for players, pass back data
}
Your API Request URL would be something like:
http://api.example.com/players/format/[csv|json|xml|html|php]
this would return a json object of all the users based on your query in your model.
OR
public function player_get($id = false, $game = false){
//if $game_id isset, search by game_id
//query db for a specific player, pass back data
}
Your API Request URL would be something like:
http://api.example.com/player/game/1/format/[csv|json|xml|html|php]
OR
public function playerGames_get($id){
//query db for a specific players games based on $userid
}
Your API Request URL would be something like:
http://api.example.com/playerGames/1/format/[csv|json|xml|html|php]