[英]Uncaught SyntaxError: Unexpected token < in JSON at position 0 at JSON.parse - Wordpress
I am new to AJAX and It seems like I might be missing a quite fundamental detail.我是 AJAX 的新手,看来我可能遗漏了一个非常基本的细节。 If I do this locally without using Wordpress, it works correctly.
如果我在不使用 Wordpress 的情况下在本地执行此操作,它会正常工作。 I am sending you the link:
我把链接发给你:
But if I create a function with Wordpress it comes out:但是,如果我用 Wordpress 创建一个 function,它就会出现:
Uncaught SyntaxError: Unexpected token < in JSON at position 0 at JSON.parse
未捕获的语法错误:JSON 中的意外令牌 < position 中的 0 JSON.parse
This is my code:这是我的代码:
add_action( 'wp_head', 'conta_visite');
function conta_visite(){
$dir = get_stylesheet_directory() . "/users";
if (!file_exists($dir)) {
wp_mkdir_p( $dir );
}
if(isset($_POST['getCustomerCount']))
{
$dbfile = get_stylesheet_directory() . "/visitors.db"; // path to data file
$expire = 3; // average time in seconds to consider someone online before removing from the list
if(!file_exists($dbfile)) {
echo json_encode(['success'=> false,'error_message'=>"Error: Data file " . $dbfile . " NOT FOUND!"]);
die();
//die("Error: Data file " . $dbfile . " NOT FOUND!");
}
if(!is_writable($dbfile)) {
echo json_encode(['success'=> false,'error_message'=>"Error: Data file " . $dbfile . " is NOT writable! Please CHMOD it to 666!"]);
die();
//die("Error: Data file " . $dbfile . " is NOT writable! Please CHMOD it to 666!");
}
$count = CountVisitors($dbfile, $expire);
if(is_numeric($count)){
$out = $count; // format the result to display 3 digits with leading 0's
echo json_encode(['success'=>'true', 'customer_count'=>$out]);
}
else
{
echo json_encode(['success'=> false, 'error_message'=>"count is not numeric"]);
}
}
else{
echo $dbfile;
echo json_encode($_POST);
}
function CountVisitors() {
global $dbfile, $expire;
$cur_ip = getIP();
$cur_time = time();
$dbary_new = array();
$dbary = json_decode(file_get_contents($dbfile),true);
if(is_array($dbary)) {
foreach($dbary as $user_ip => $user_time){
if(($user_ip != $cur_ip) && (($user_time + $expire) > $cur_time)) {
$dbary_new[$user_ip] = $user_time;
}
}
}
$dbary_new[$cur_ip] = $cur_time; // add record for current user
$fp = fopen($dbfile, "w");
fputs($fp, json_encode($dbary_new));
fclose($fp);
return count($dbary_new);
}
function getIP() {
if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
elseif(isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
else
{
$ip = "0.0.0.0";
}
return $ip;
}
?>
<p id="customer_count">Customers Online: <span></span></p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
function updateCustomerCount() {
$.ajax({
type: "POST",
cache: false,
data: {getCustomerCount: true},
success: function(response) {
var data = JSON.parse(response);
//var data = response;
console.log(response);
if (data.success) {
$("#customer_count span").text(data.customer_count);
} else {
console.log(data.error_message);
}
},
error: function(response, request, status, error) {
console.log(error);
}
});
setTimeout(updateCustomerCount, 2000);
}
updateCustomerCount();
</script>
<?php
}
This is the Demo link in Wordpress: You can find the counter in the upper right corner of the header.这是Wordpress中的Demo链接:header右上角可以找到计数器。
Can you help me?你能帮助我吗? Because I'm going crazy and I can't figure out where I'm going wrong....
因为我快疯了,我不知道我哪里出错了……
Ok so this should do what you're looking for.好的,这应该可以满足您的需求。 I've rewritten your code for better WordPress integration.
我已经重写了您的代码以更好地集成 WordPress。
First, you'll need to create a new javascript file name visitor-counter.js
and place it a js
folder in your themes directory.首先,您需要创建一个新的 javascript 文件名
visitor-counter.js
并将其放置在您的主题目录中的一个js
文件夹中。 This will be used for our jQuery and ajax request.这将用于我们的 jQuery 和 ajax 请求。
/js/visitor-counter.js
(function($) {
window.VisitorCounter = window?.VisitorCounter || {
/**
* @type {object} Temp storage object
*/
_temp: {},
/**
* Get a PHP variable.
*
* @param varName
* @returns {*}
*/
getVar(varName) {
const vars = window?.VisitorCounterVars;
return vars?.[varName];
},
/**
* Make ajax request to server, store response in temp object.
*
* @returns {Promise<unknown>}
*/
request() {
return new Promise((accept, reject) => {
const url = this.getVar('ajaxUrl');
const action = this.getVar('ajaxAction');
const post_id = this.getVar('post_id');
if (url && action) {
$.ajax({
url: url,
data: {
action: action,
post_id: post_id
},
cache: false
}).then(response => {
this._temp.count = response.data;
accept(response);
console.log(response);
});
} else {
reject('Visitor counter ajax url or action not available.');
}
});
},
/**
* Get the count value.
*
* @returns {number}
*/
getCount() {
return parseInt(this._temp?.count || 0);
},
/**
* Refresh data continuously.
*
* @param {callback} callback
* @param {number} timeout
*/
refresh(callback, timeout) {
this._temp.lastRefreshed = Date.now();
this.request().then(() => {
const now = Date.now();
callback.apply(this);
const timeoutDiff = now - this._temp.lastRefreshed;
// If request took longer than timeout, run next refresh instantly.
if (timeout && timeoutDiff >= timeout) {
this.refresh(callback, timeout);
}
// Request was quicker than timeout, queue next refresh call.
else {
setTimeout(() => {
this.refresh(callback, timeout);
}, timeout - timeoutDiff);
}
});
}
};
// Initiate refresh loop
VisitorCounter.refresh(function() {
$('#customer_count span').text(VisitorCounter.getCount());
}, 2000);
})(jQuery);
Next add the below to your themes functions.php file...接下来将以下内容添加到您的主题 functions.php 文件中...
/functions.php
class VisitorCounter {
private static $instance;
/**
* @var string $file Relative path to the tracking file.
*/
public $file = 'users/';
/**
* @var int $expires Automatically expire vistor after X amount of seconds.
*/
public $expires = 3;
/**
* @return $this
*/
public static function init() {
if ( !static::$instance ) {
static::$instance = new static( ...func_get_args() );
}
return static::$instance;
}
/**
* Get the full database file path and create file if not exists.
*
* @return string|false
*/
public function getPath() {
$post_id = $_GET['post_id'];
$path = get_stylesheet_directory() . '/' . ltrim( $this->file, '/' ) . 'product-view-id-' . $post_id . '.db';
$exists = file_exists( $path );
if ( !$exists ) {
wp_mkdir_p( dirname( $path ) );
$exists = touch( $path );
}
return $exists ? $path : true;
}
/**
* Read the contents of the visitors database file as a JSON.
*
* @return array
*/
public function getData() {
if ( $path = $this->getPath() ) {
if ( $contents = file_get_contents( $path ) ) {
if ( $json = @json_decode( $contents, true ) ) {
return $this->cleanData( $json );
}
}
}
return [];
}
/**
* Clean the visitor data by removing expired entries.
*
* @param array $input
* @return array
*/
private function cleanData( array $input ) {
$now = time();
foreach ( $input as $ip => $timestamp ) {
if ( $timestamp + $this->expires < $now ) {
unset( $input[ $ip ] );
}
}
return $input;
}
/**
* Add visitor count data.
*
* @param string $ip
* @param int $timestamp
* @return array
*/
public function logUser() {
// Get current data.
$data = $this->getData();
// Add new entry.
if ( $ip = $this->getUserIp() ) {
$data[ $ip ] = time();
}
// Clean data before saving.
$data = $this->cleanData( $data );
// Encode and save data.
file_put_contents( $this->getPath(), wp_json_encode( $data ) );
// Return data.
return $data;
}
/**
* Get the current users IP address.
*
* @return string|null
*/
public function getUserIp() {
// In order of preference, with the best ones for this purpose first.
$address_headers = [
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'REMOTE_ADDR'
];
$client_ip = null;
foreach ( $address_headers as $header ) {
if ( !empty( $_SERVER[ $header ] ) ) {
/*
* HTTP_X_FORWARDED_FOR can contain a chain of comma-separated
* addresses. The first one is the original client. It can't be
* trusted for authenticity, but we don't need to for this purpose.
*/
$address_chain = explode( ',', $_SERVER[ $header ] );
$client_ip = trim( $address_chain[ 0 ] );
break;
}
}
return $client_ip;
}
}
/**
* Helper function for visitor counter class.
*
* @return VisitorCounter
*/
function visitor_counter() {
return VisitorCounter::init();
}
/**
* Register an ajax request handler.
*/
add_action( 'wp_ajax_active_visitor', 'handle_visitor_activity' );
add_action( 'wp_ajax_nopriv_active_visitor', 'handle_visitor_activity' );
function handle_visitor_activity() {
$controller = visitor_counter();
$controller->logUser();
wp_send_json_success( count( $controller->getData() ) );
}
/**
* Load our javascript file on the frontend data.
*/
add_action( 'wp_enqueue_scripts', function() {
if ( is_product()) {
// Load the counter javascript file after `jquery` in the footer.
wp_enqueue_script( 'visitor-counter', get_stylesheet_directory_uri() . '/js/visitor-counter.js', [ 'jquery' ], '1.0.0', true );
// Load php data that can be accessed in javascript.
wp_localize_script( 'visitor-counter', 'VisitorCounterVars', [
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'ajaxAction' => 'active_visitor',
'post_id'=> get_the_id()
] );
}
} );
Things to lookup...要查找的东西...
WordPress ajax handlers ( add_action( 'wp_ajax_' )
and add_action( 'wp_ajax_nopriv_' )
) documentation can be found here: WordPress ajax 处理程序(
add_action( 'wp_ajax_' )
和add_action( 'wp_ajax_nopriv_' )
)文档可以在这里找到:
WordPress JSON responses wp_send_json_error()
and wp_send_json_success()
: WordPress JSON 响应
wp_send_json_error()
和wp_send_json_success()
:
Loading javascript on the frontend:在前端加载 javascript:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.