Counter - cnt.php
The counter exists of two parts; the JavaScript Code that calls a PHP page with parameters to log the access and the PHP page that logs the call.
Database
The database exists of one table.
CREATE TABLE `counters` (
`ID` bigint(20) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`cat` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`page` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`ip` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
The cat is the category and the page is the page name. With the category you can group pages.
The JavaScript Code or iFrame
This example is used a Laravel App (BookStack) and gets the category and page name from the URL.
The JavaScript code only accepts categories Page or Books, those are the BookStack objects from the URL where we are interested in.
<script>
var HttpClient = function() {
this.get = function(aUrl, aCallback) {
var anHttpRequest = new XMLHttpRequest();
anHttpRequest.onreadystatechange = function() {
if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200) {
aCallback(anHttpRequest.responseText);
}
}
anHttpRequest.open( "GET", aUrl, true );
anHttpRequest.send( null );
}
}
var pathArray = window.location.pathname.split('/');
if ( pathArray.length >=2 ) {
var page = pathArray[pathArray.length-1];
var cat = pathArray[pathArray.length-2];
if ( cat.toUpperCase() == 'PAGE' || cat.toUpperCase() == 'BOOKS' ) {
var client = new HttpClient();
var url='https://www.roc.ovh/cnt.php?id='+cat+':'+page;
console.log('Getting:'+url);
client.get(url, function(response) {
console.log(response);
});
} else {
console.log('Invalid cat: '+cat);
}
}
</script>
Alternatively this code can also be called from an HTML iframe
<iframe style="border: none;" src="//www.maxdata.ovh/cnt.php?id=php1-allefilmpjes"></iframe>
Nate that in the JavaScript version the cat and page are delimited by a semicolon : whereas in the iframe example the cat and page are delimited by a dash -
The PHP code
The code that is called from the JavaScript (above). This version is tuned to the BookStack environment; the dashes are removed from the page and the page name is converted to CamelCase style to make it a bit more compact.
<?php
// Define DB Params
define("DB_HOST", "localhost");
define("DB_USER", "counters");
define("DB_PASS", "");
define("DB_NAME", "counters");
class DB{
protected $dbh;
protected $stmt;
protected $resultSet;
public function __construct(){
$this->dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS);
$this->resultSet=[];
}
public function executeSQL($query){
$this->stmt = $this->dbh->prepare($query);
$result = $this->stmt->execute();
if (! $result) {
die('<pre>Oops, Error execute query '.$query.'</pre><br><pre>'.'Result code: '.$result.'</pre>');
}
$this->resultSet = $this->stmt->fetchAll(PDO::FETCH_ASSOC);
return count($this->resultSet);
}
public function getRow(){
if (count($this->resultSet) >0 ){
return array_shift($this->resultSet);
} else {
return 0;
}
}
}
function dashesToCamelCase($string, $capitalizeFirstCharacter = false)
{
$str = str_replace(' ', '', ucwords(str_replace('-', ' ', $string)));
if (!$capitalizeFirstCharacter) $str[0] = strtolower($str[0]);
return $str;
}
list($cat, $page)=explode(":", $_GET['id']); // get parameters
$cat = dashesToCamelCase($cat, true);
$page = dashesToCamelCase($page, true);
if ( strlen($cat) > 10 ) $cat = substr($cat,0,10);
if ( strlen($page) > 20 ) $page = substr($page,0,20);
$ip=$_SERVER['REMOTE_ADDR'];
if ( $cat != "" AND $page != "" ) {
$DB = new DB;
$query = "INSERT INTO counters (cat,page,ip) VALUES ('$cat', '$page', '$ip')";
$DB->executeSQL($query);
$query = "SELECT count(*) FROM counters WHERE DATE(date)=CURDATE() AND cat='$cat' AND page='$page'";
$DB->executeSQL($query);
$result=$DB->getRow()['count(*)'];
} else {
$result="_";
}
echo "<p style=\"font-size:12px;color:#DCDCDC;\">- $result -</p>";
?>
The somewhat simpler version:
<?php
// Define DB Params
define("DB_HOST", "localhost");
define("DB_USER", "counters");
define("DB_PASS", "");
define("DB_NAME", "counters");
class DB{
protected $dbh;
protected $stmt;
protected $resultSet;
public function __construct(){
$this->dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS);
$this->resultSet=[];
}
public function executeSQL($query){
$this->stmt = $this->dbh->prepare($query);
$result = $this->stmt->execute();
if (! $result) {
die('<pre>Oops, Error execute query '.$query.'</pre><br><pre>'.'Result code: '.$result.'</pre>');
}
$this->resultSet = $this->stmt->fetchAll(PDO::FETCH_ASSOC);
return count($this->resultSet);
}
public function getRow(){
if (count($this->resultSet) >0 ){
return array_shift($this->resultSet);
} else {
return 0;
}
}
}
list($cat, $page)=explode("-", $_GET['id']); // get parameters
$ip=$_SERVER['REMOTE_ADDR'];
if ( $cat != "" AND $page != "" ) {
$DB = new DB;
$query = "INSERT INTO counters (cat,page,ip) VALUES ('$cat', '$page', '$ip')";
$DB->executeSQL($query);
$query = "SELECT count(*) FROM counters WHERE DATE(date)=CURDATE() AND cat='$cat' AND page='$page'";
$DB->executeSQL($query);
$result=$DB->getRow()['count(*)'];
} else {
$result="_";
}
echo "<p style=\"font-size:12px;color:#DCDCDC;\">- $result -</p>";
?>
This version simply logs the parameters cat and page specified by the GET. Example ?id=cat-page
This version returns a small and almost white page counter.
--