WordPress REST API: comment and like count - javascript

What's the easiest way to fetch the number of comments and the number of likes a post has?
I don't see any usefull field when fetching a post (with a request like https://site/wp-json/wp/v2/posts?after=2018-07-21T15:05:44.000Z)
I'm currently using javascript issuing direct requests with axios.

If you have edit access to the code of the site your are requesting, you could add the field to the responses provided by the JSON API.
Something like this:
add_action( 'rest_api_init', function() {
\register_rest_field( 'post', 'comment_count', [
'get_callback' => function ( $post ) {
return (int) wp_count_comments( $post['id'] )->approved;
},
'schema' => [
'description' => 'List number of comments attached to this post.',
'type' => 'integer',
],
] );
});
If you don't have access to the site you are requesting, you can have the comments added to the response by send ?_embed=true at the end of the URL and simply count the replies.
Something like this:
const {data} = await Axios.get( 'https://site/wp-json/wp/v2/posts?after=2018-07-21T15:05:44.000Z&_embed=true' );
data.map( post => {
console.log( post._embedded.replies.length );
});

Not so much a JavaScript related question but here's an answer anyway.
The easiest way to get the number of comments for any post aside from adding a custom endpoint to the REST API is to use the comments endpoint (https://site/wp-json/wp/v2/comments?post=1234&per_page=1) and use the response's X-WP-Total header.

Related

Why is the Inertia.post method dumping form data into the query string?

I am using Inertia in a Laravel-React stack and have a page component that lets me write, edit, and delete blog posts and preview them as they would be styled on the site in real time.
I have a form that uses the State hook to update the value of its fields and display form data in a styled div on the right. I also have POST routes that direct to a controller which does some transforming and inserts/updates/deletes the site database with form data.
The top of the form, in React 17:
<div className="editor">
{props.id && <h3>Editing {props.title}</h3>}
<form onSubmit={(e) => {
e.preventDefault;
!props.id ? // are we editing an existing post?
Inertia.post('gutenberg.new') : // if no, then insert a new one
!delPost.bool ? // if yes, are we deleting it?
Inertia.post('gutenberg.update') : // if no, then update with this ID
Inertia.post('gutenberg.delete') // if yes, then delete with this ID
One of the controller's public methods, in this case, for the "edit" route. Sorry if there is too much information here. I am curious if it's forbidden to use this kind of logic in a controller when trying to do something like this, or if I am breaking something else inadvertently. In PHP using Laravel 9:
public function updatePost(Request $request) {
$postID = $request->input('id');
BlogPost::where('id', '=', $postID)->update([
'title' => $request->input('title'),
'slug' => $request->input('slug'),
'body' => $request->input('body'),
'image' => $request->input('image'),
'language' => $request->input('language'),
]);
/* Now, we pull the existing associative records for the post in
from the post tags table to compare them to the tags that were
sent to the backend. That way, I can edit the tags for each post
within the editor itself.
*/
$comparisonTags = PostTags::join('tags', 'tags.id', '=', 'post_tags.tag_id')
->where('post_tags.post_id', '=', $postID)
->get();
// Get the tags included in the request
$collectedTags = collect(json_decode($request->input('tags')));
foreach ($collectedTags as $index => $tag) {
// Add any totally new tags
Tags::upsert(['name' => $tag], ['id', 'name']);
/* "If the tags included in the update request contain something
that the post tags table doesn't for this post ID, then insert
them there." */
if (!$comparisonTags->contains('name', $tag)) {
$tagID = Tags::select('id')->where('name', '=', $tag)->get('id')->toArray();
$scalarTagID = strval($tagID[0]['id']);
PostTags::insert([
'post_id' => $postID,
'tag_id' => $scalarTagID,
]);
}
}
foreach ($comparisonTags as $id => $tag) {
/* "If the tags in the post tags table associated with the
updated post's ID contain something that the new tag list
does not, then remove those tags from the post tags table."
*/
if (!$collectedTags->contains($tag->name)) {
PostTags::where('tag_id', '=', $tag->id)->delete();
}
}
return Redirect::route('index');
// Inertia requests need Inertia responses
// country roads... take me home...
}
public function deletePost(Request $request) {
// pretty self-explanatory
$postID = $request->input('id');
BlogPost::where('id', '=', $postID)->delete();
PostTags::where('post_id', '=', $postID)->delete();
return Redirect::route('index');
}}
And the route in question:
Route::post('gutenberg/edit',
[Gutenberg::class, 'updatePost'])
->name('gutenberg.update');
The problem occurs when using the Inertia.post method to send form data to the controller for handling there. The issue does not show up when I use the normal HTML form-action-method approach, but I want to use Inertia's visit method so that I can use CSRF protection on the site.
Upon submitting the form, rather than redirect to the Inertia response that the controller returns for its POST method functions, the page just dumps all of the form data into the query string. Nothing happens on the backend, as no updates are made to the database, and the old form data is still visible on the page.
A screenshot of my browser after hitting "Submit." Note the query string, with a title attribute of "a very different title" from the originally exasperated ffs.
Could the controller be introducing some kind of unexpected JSON response, thus breaking the Inertia.post method? I stepped through the whole thing with Firefox's debugger, and the only thing I saw that looked out of the ordinary was a terrifying 16,000-character wide line that included that string about each Inertia request needing a valid Inertia response.
Any help would be appreciated.
I forgot the brackets on event.preventDefault().

Retrieve article object including its image using the Shopify JavaScript Buy SDK custom query

I'm using the shopify-buy SDK to try and fetch the articles off of my Shopify store just using JavaScript on the frontend, following the "Expanding the SDK" directions here: https://shopify.github.io/js-buy-sdk/#expanding-the-sdk.
Using the code below, I am able to retrieve my articles and some of the fields that I need.
// Build a custom query using the unoptimized version of the SDK
const articlesQuery = client.graphQLClient.query((root) => {
root.addConnection('articles', {args: {first: 10}}, (article) => {
article.add('title')
article.add('handle')
article.add('url')
article.add('contentHtml')
})
})
// Call the send method with the custom query
client.graphQLClient.send(articlesQuery).then(({model, data}) => {
console.log('articles data')
console.log(data)
})
However, I really need to pull the featured image for each article as well, and unfortunately, when I add the line article.add('image') in my articlesQuery, the resulting articles data logs null. I tried building a custom productsQuery, and that has a similiar problem - I can retrieve some of the product fields, but when I try add the line product.add('images'), I just get null back from the storefront API.
Does anyone have experience building custom/expanded queries and successfully retrieving images?
Try following:
// Fetch all products in your shop
client.graphQLClient.fetchAll().then((acticles) => {
console.log(acticles);
});
And then check in console what sort of available property names your articles have. If SDK allows you get any image data, there should be for sure anything like imageSrc || imageUrl || img......
Thanks to Rebecca Friedman on the js-buy-sdk repo's github issues section for providing this working solution:
const articlesQuery = client.graphQLClient.query((root) => {
root.addConnection('articles', {args: {first: 10}}, (article) => {
article.add('title')
article.add('handle')
article.add('url')
article.add('contentHtml')
article.addField('image', {}, (image) => {
image.add('id')
image.add('originalSrc')
})
})
})
// Call the send method with the custom query
client.graphQLClient.send(articlesQuery).then(({model, data}) => {
console.log('articles data')
console.log(data) // works!
})
Because the image field is its own object, you have to add a callback function to specify the fields you need.

Adonis.js populate all with related tables data

I use MySql, all relationships have been configured correctly in models and schemas:
I have 3 tables:
1. posts ( main )
2. categories ( 1 post has 1 cat, 1 cat belongs to many posts )
3. tags ( many-to-many )
Categories and tags both have "post_id" column relating to "id" column in posts table.
What is the best way to get all related data ( post data + post category data + post tags data ) ?
( for now I know I can get something like:
const post = await Post.find(params.id)
const category = await post.categories().fetch()
etc for every related table
I'm sure there must be better way.
I'd like result to be:
{
post data - name, text ...,
"category": {
category data - name, text ...
},
"tags": [
{
tag1 data
},
{
tag2 data
}
]
}
const wantedData = await Post.query().where('id', params.id).with('categories').with('tags').fetch()
Yes, there is a better way to do this.
The Latest Adonis js Have the feature of the Query builder. You can perform almost all SQL queries using this. For Example
#select
Database
.from('users')
.select('id', 'username', 'email')
So There are many queries you can perform as your need. The following links will be very useful for you. Query builder Documentation

Laravel-datatables protection

I'm using https://github.com/yajra/laravel-datatables currently to send ajax request for my datatable but noticed this:
columns: [
{ data: 'first_name' },
{ data: 'last_name' },
{ data: 'email' },
]
but those are lines in my javascript document. I'm currently providing data like this:
return Datatables::of(User::all())->make(true);
That means if someone change lines in my js file he can view columns that he is not supposed to. Now if you take a look at github documentation you can see that this package can also accept collection or query. Is it possible to target only certain columns from database with collection or query ?
You can fetch only necessary columns from database like this:
return Datatables::of(User::all(['first_name','last_name','email']))->make(true);

how to use spinejs fetch ajax data with conditions

For example, I have this Model as Users:
var Users = Spine.Model.sub();
Users.configure('Users', 'name', 'gender', 'age');
Users.extend(Spine.Model.Ajax);
Users.extend({url:"/users"});
Assume that we already have some data saved in database.
If run
var users = Users.fetch();
Ajax will send a GET request to /users, and all results will be returned.
But if I wanna fetch all female or male users, or age above 25, or top 10 users in specified order, how to pass these variables? I cant find spec in the document. The fetch method can pass a callback function parameter to revoke when fetch complete, clearly not what I want.
I found the solution myself..Actually the document tells how to paginate results.
var Photo = Spine.Model.sub();
Photo.configure('Photo', 'index');
Photo.extend(Spine.Model.Ajax);
Photo.extend({
fetch: function(params){
if ( !params && Photo.last() )
params = {data: {index: this.last().id}}
this.constructor.__super__.fetch.call(this, params);
}
});
But I found the code can't run, first
this.constructor.__super__.fetch.call(this, params);
should be
this.__super__.constructor.fetch.call(this, params);
secondly, if run Photo.fetch({data:{id:1}}), it will send a GET request like this
GET /photos?[object%20Object]
correct it
Photo.fetch({data: $.param({id:1})});
HTTP Request
GET /photos?id=1

Categories

Resources