This is a simple question regarding Wordpress API /wp-json. I am querying some data filtered with certain category in Wordpress. My questions is how can I control amount of result that gets returned from my Get request... The default returns seems to return around 11 most recent results. Is there any way I can make it return only 1 (most recent), or like 100 posts. What is the minimum and maximum amount I can return. And what is the syntax for it. This is the default request I have:
http://thisismywebsitewherewordpresslives.com/wp-json/posts?fiter[category_name]=Some Category Name I want to query&filter[order]=ASC
If you're using v2 of the WordPress REST API, it looks like the current method of controlling the number of results returned is:
website.com/wp-json/wp/v2/posts/?per_page=100
Replace 100 with the desired count.
If you're using a custom post type, replace posts with the custom post type. Also make sure to set 'show_in_rest' => true when configuring the custom post type.
Add the filter[posts_per_page] parameter to the query to restrict the number of results returned by the API.
http://thisismywebsitewherewordpresslives.com/wp-json/posts?filter[posts_per_page]=2&fiter[category_name]=Some Category Name I want to query&filter[order]=ASC
The above query should return only 2 results. The list of query parameters are present here https://github.com/WP-API/WP-API/blob/master/docs/routes/routes.md#retrieve-posts
As another said : (v2)
http://example.com/wp-json/wp/v2/posts?per_page=10
But If you want to get more next posts : (paged)
http://example.com/wp-json/wp/v2/posts?per_page=10&page=2
Docs : http://v2.wp-api.org/reference/posts/ (Scroll to List Posts)
My recommendation above is no longer correct. Now you'll want to use:
website.com/wp-json/wp/v2/posts/?filter[posts_per_page]=100
Change the number to retrieve more or fewer posts. Change "posts" to your custom post type if necessary and make sure to set 'show_in_rest' => true when registering the custom post type.
Note: While setting the posts_per_page value to -1 worked in earlier beta versions of the plugin (2.0-beta13.1), it does not seem to work in the most recent versions. Now it seems you must define a value in the endpoint.
Currently the API imposes a 99 post limit return. So the max is website.com/wp-json/wp/v2/posts/?&per_page=99, that said it seems like you can modify to allow for additional posts. There's a discussion on that here: https://github.com/WP-API/WP-API/issues/2914
You might change:
add_action( 'rest_YOUR_CPT_params', function($params){
if ( isset( $params ) AND isset( $params[ 'per_page' ] ) ) {
$params[ 'per_page' ][ 'maximum' ] = 500;
}
return $params;
});
And in fetch url add ?per_page=500
Example: https://domain.pl/wp-json/wp/v2/books?per_page=500
The arg in V2 is "per_page" - http://v2.wp-api.org/reference/posts/
I'm surprised no one mentioned using the native filters WordPress has created for situations exactly like this.
I was able to achieve returning a desired amount of posts by default, while still allowing the $_GET['per_page'] param to work like so:
/**
* Default to all posts being returned rather than the default 10 posts per
* page. Also, do not get in the way of the native $_GET['per_page'] setting.
* #param {int} $newDefault The new default amount of posts to return per paginated page
* #var {void}
*/
function setRestApiPostsPerPage($newDefault) {
foreach (get_post_types() as $i => $postType) {
add_filter( "rest_{$postType}_query", function ($args, $request) {
if (! isset($_GET['per_page'])) {
// new default to overwrite the default 10
$args['posts_per_page'] = $newDefault;
}
return $args;
}, 15, 2);
}
}
I did find out you can't set $args['posts_per_page'] = -1; That results in an error being thrown which you can see here.
You can throw any logic within the closure/callback/filter to set the $args['posts_per_page'] however you'd like to.
In reference to Aaron Nusselbaum answer but corrected a few things:
add_filter instead of add_action
filter name must contain additional '_collection', so 'rest_YOUR_CPT_collection_params'
For example:
add_filter( 'rest_comment_collection_params', function($params){
if ( isset( $params ) AND isset( $params[ 'per_page' ] ) ) {
$params[ 'per_page' ][ 'maximum' ] = 500;
}
return $params;
});
Related
I got a api request that has a parameter in it which is projectname. The problem is when I search for example A the results will be A but when I search for B the result is till A even if I search C the result is still the same. I think the cache saved the first results from the first search string. My question is how could I save every results in every search query without getting the same result based on the search query?
Here is my code
public function getRecordDetails(Request $request){
if(!empty($request->limit)){
$limit = " LIMIT ".$_REQUEST['limit'];
}
else{
$limit= '';
}
if(empty($request->projectname)){
dd('Field is empty');
}
else{
$data = Cache::rememberForever('results', function () use($request) {
$result = DB::connection('mysql2')
->table('xp_pn_ura_transactions')
->whereRaw(DB::raw("CONCAT(block, ' ', street,' ',project_name,' ', postal_code,'')LIKE '%$request->projectname%' order by STR_TO_DATE(sale_date, '%d-%M-%Y') desc"))
->limit($request->limit)
->distinct()
->get();
$count = DB::connection('mysql2')
->table('xp_pn_ura_transactions')
->whereRaw(DB::raw("CONCAT(block, ' ', street,' ',project_name,' ', postal_code,'')LIKE '%$request->projectname%'"))
->count();
return json_encode(array('count'=>$count,'result'=>$result));
});
return $data;
}
}
PS: This question is based here How could I cache every api response results in my query in Laravel? I answered here but this is different problem based on my answer. Thanks for helping.
Laravel find the Cache by the key. You're using results as your key.
So no matter how different request you pass. It still can find the cache by results.
So it will return the first cache you store in results.
$key = "results:".$request->projectname.':' $request->limit;
Cache::rememberForever($key, function () use ($request) {
...
}
This one will store every different projectname you request.
However
Problem 1:
There are so many diff possibilities that user can request.
I don't think it is a good idea to store all these cache. If there are not that much, it is ok.
Solution:
Or you can use remember() instead of rememberForever()
$ttl = ????; // Find the appropriate time to expire the cache
$value = Cache::remember($key, $ttl, function () {});
Problem 2:
There is a $request->limit in your cache.
That means if someone insert or delete a record in that table. next time you request with another limit, you will face the duplicated records.
Solution:
So I think you can clear the cache after you create , update or delete the records.
Because you are using the same cache slug over and over. You should change the cache slug according to the changed input. Adding the $request as a use argument to your function will not magically change the cache slug.
In your case, this should work:
Cache::rememberForever("results_{$request->projectname}", function () use ($request) {
you should add text value after and before key id like bello
Cache::rememberForever('product_'.$product->id.'_key',function ()
});
In the official docs I read:
Do bear in mind that virtual fields cannot be used in finds. If you want them to be part of JSON or array representations of your entities, see Exposing Virtual Fields.
It's not clear to me if the second sentence is in someway related to the first one - say as a workaround to overcome the limitation - or they are completely independent.
I mean: if I expose a Virtual Field then may I use it in a find statement?
Is there a way to include a virtual field in a query? Here a real example:
ItemOrdersTable.php:
$this->setTable('item_orders');
$this->setDisplayField('summary'); // virtual field
$this->setPrimaryKey('id');
Entity:
protected $_virtual = [
'summary'
];
protected function _getSummary()
{
return $this->name . ' ' . $this->description;
}
Usage in a Controller:
return TableRegistry::get('itemOrders')->find('list')->where(['order_id' => $id]);
Because I specified 'summary' as DisplayField, I'm expecting a key-value list of all records that meet the where clause, with the id as key and the summary virtual field as value. Because this doesn't happen (the returned object is null) I'm trying to understand if my code is wrong or I didn't read correctly the documentation as asked above.
Customize Key-Value Output:
https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#customize-key-value-output
Update:
$results = TableRegistry::getTableLocator()->get('item_orders')
->find('list')
->where(['order_id' => $id]);
debug($results->toArray());
$this->set('orders', $results);
debug($orders); exit; <-- test results, and post in your question.
I want to modify the query that is running to create a table in a view but am having a hard time, so to keep it simple I am using a plain view that just lists users in a table and am trying to modify the query to make the table have two columns. I have been looking at the documentation for Drupal queries, trying to find tutorials, and looking at blog posts on how others modified queries in Drupal and Views, but so far none have worked or shown how to do something as simple as this, or I've tried to create simple query statements following what they did with no outcome.
I've mainly been trying to use hook_views_pre_execute() but have also tried . This is what my code looks like at the moment:
<?php
/**
* Implements hook_views_query_alter().
*/
// This function is called right before the execute process.
function my_module_views_pre_execute(&$view) {
if ($view->name == 'page' && $view->current_display == 'page') { //checks name of the view and what type it is
drupal_set_message("I can make changes to the view here.."); //diagnostic information, shows we can make changes to that view
$query =db_select('node','n')//select base table, alias is n.
->fields('n',array('nid', 'title', 'created', 'uid')); //adding fields nid, title, created, uid.
dpm($query->execute()->fetchAll()); // diagnostic information, shows whats being returned by the query
$query->execute()->fetchAll();
$view->build_info['query'] = $query;
}
}
I am able to create a message on the view with drupal_set_message("I can make changes to the view here..");, and in the Views settings tab I enabled 'Show the SQL query' and the output of that is the query from my module/code (it doesn't match the table created by Views).
So why doesn't it affect the table output at all? How do I modify what query is being run to display the view (which is apparently different from the 'Show the SQL query' output)?
I have taken example only for nid here I can provide you just an Idea for alter the views output.
/**
*
* #param type $view
* #param type $query
* Implements hook_views_query_alter(). This function is Used when we need to Alter the query before executing the query.
*/
function mymodule_views_query_alter(&$view, &$query) {
if ($view->name == 'VIEW_NAME' && $view->current_display == 'PAGE_NAME') {
drupal_set_message("I can make changes to the view here.."); //diagnostic information, shows we can make changes to that view
$query =db_select('node','n')//select base table, alias is n.
->fields('n',array('nid', 'title', 'created', 'uid')); //adding fields nid, title, created, uid.
dpm($query->execute()->fetchAll()); // diagnostic information, shows whats being returned by the query
$result = $query->execute()->fetchAll();
$nids = array();
foreach ($result as $value) {
$nids[] = $value->nid;
}
$view->query->where[1]['conditions'][] = array('field' => "node.nid", "value" => $nids, "operator" => "IN");
}
}
hook_views_pre_execute() is too late in the query build processs so I think you should use hook_views_query_alter().
Thanks
Within an extension (JSON access), I'm calling getContent() with:
$items = $this->app['storage']->getContent($contenttype, $options);
$response = $this->app->json($items);
return $response;
The options array is:
[
'limit' => 5,
'page' => 3
]
But getContent only returns the latest 5 results, not calculating the offset from the page variable. Is there another setting that I have to change to get it to recognise the paging?
Calling getContent you need to specify that you want paging turned on, here's some adding 'paging'=>true to the options should work correctly.
I have extended the Mage_Adminhtml_Block_Sales_Order_Grid class with a custom module to add several customer attributes (Magento EE 1.10) to the grid.
I added the custom attributes to the collection in my MyCompany_MyModule_Block_Adminhtml_Order_Grid class in the _prepareCollection() method using three joins like this:
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
//get the table names for the customer attributes we'll need
$customerEntityVarchar = Mage::getSingleton('core/resource')
->getTableName('customer_entity_varchar');
$customerEntityInt = Mage::getSingleton('core/resource')
->getTableName('customer_entity_int');
// add left joins to display the necessary customer attribute values
$collection->getSelect()->joinLeft(array(
'customer_entity_int_table'=>$customerEntityInt),
'`main_table`.`customer_id`=`customer_entity_int_table`.`entity_id`
AND `customer_entity_int_table`.`attribute_id`=148',
array('bureau'=>'value'));
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_table`.`entity_id`
AND `customer_entity_varchar_table`.`attribute_id`=149',
array('index_code'=>'value'));
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_2_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_2_table`.`entity_id`
AND `customer_entity_varchar_2_table`.`attribute_id`=150',
array('did_number'=>'value'));
$this->setCollection($collection);
return parent::_prepareCollection();
}
UPDATE: While everything displays fine when viewing orders, things are not fine when I try to search / filter orders by any of the text join fields (index_code or did_number). The result is a SQL error: "SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'store_id' in where clause is ambiguous."
This problem also exists if I remove all but one of the leftJoin() statements, so something is going wrong with both (either) of the joins with the customer_entity_varchar table.
As now there are two columns with the name store_id, you have to specify filter_index when you add the column to the grid:
$this->addColumn('store_id', array(
...
'filter_index'=>'main_table.store_id',
));
So that it knows which one you are referring while filtering.
I hope it helps!
More than likely it is because you are joining customer_entity_varchar_table twice.
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_table`.`entity_id`
AND `customer_entity_varchar_table`.`attribute_id`=149',
array('index_code'=>'value'));
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_2_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_2_table`.`entity_id`
AND `customer_entity_varchar_2_table`.`attribute_id`=150',
array('did_number'=>'value'));
You may want to combine those, you can also try and print the SQL to see what the Query looks like:
$collection->getSelect()->getSelectSql();
More info on collections: http://blog.chapagain.com.np/magento-collection-functions/
The problem appears to exist in two different places. One case is if logged in as a user with a single store, the other as a user who can filter various stores.
Single store user
The solution I went with was to override the addAttributeToFilter method on the collection class. Not knowing exactly what changing the Enterprise_AdminGws_Model_Collections::addStoreAttributeToFilter method would affect other behavior I wanted to avoid that, and I found adding a filter index in Mage_Adminhtml_Block_Sales_Order_Grid as Javier suggested did not work.
Instead I added the following method to Mage_Sales_Model_Resource_Order_Grid_Collection:
/**
* {#inheritdoc}
*/
public function addAttributeToFilter($attribute, $condition = null)
{
if (is_string($attribute) && 'store_id' == $attribute) {
$attribute = 'main_table.' . $attribute;
}
return parent::addFieldToFilter($attribute, $condition);
}
A patch can be found here: https://gist.github.com/josephdpurcell/baf93992ff2d941d02c946aeccd48853
Multi-store user
If a user can filter orders by store at admin/sales_order, the following change is also needed to Mage_Adminhtml_Block_Sales_Order_Grid around line 75:
if (!Mage::app()->isSingleStoreMode()) {
$this->addColumn('store_id', array(
'header' => Mage::helper('sales')->__('Purchased From (Store)'),
'index' => 'store_id',
'type' => 'store',
'store_view'=> true,
'display_deleted' => true,
'filter_index' => 'main_table.store_id',
));
}
A patch can be found here: https://gist.github.com/josephdpurcell/c96286a7c4d2f5d1fe92fb36ee5d0d5a
I had the same bug, after grepping the code, I finally found the troublemaker which is in the Enterprise_AdminGws_Model_Collections class at line ~235:
/**
* Add store_id attribute to filter of EAV-collection
*
* #param Mage_Eav_Model_Entity_Collection_Abstract $collection
*/
public function addStoreAttributeToFilter($collection)
{
$collection->addAttributeToFilter('store_id', array('in' => $this->_role->getStoreIds()));
}
You have to replace 'store_id' by 'main_table.store_id', of course you'll have to extend that particular method in your own rewrite to stick into Magento guidelines :p
Hope it helps!