Sample Apple Push Notification PHP Script

This is an old script that I used to use for sending notifications. I don’t remember the source, on the other hand, it has been modified a couple of times already.

Even though I could manage to send notifications with this script, the Apple server was rejecting the connection after the amount reaches more than 50. It was usually getting cut off around 70. So it needs to get some management for not sending in a loop, like threading or whatever.

<?php
 
// set time limit to zero in order to avoid timeout
set_time_limit(0);
 
// charset header for output
header('content-type: text/html; charset: utf-8');
 
// this is the pass phrase you defined when creating the key
$passphrase = 'my_secret_pass';
 
// you can post a variable to this string or edit the message here
if (!isset($_POST['msg'])) {
$_POST['msg'] = "Notification message here!";
}
 
// tr_to_utf function needed to fix the Turkish characters
$message = tr_to_utf($_POST['msg']);
 
// load your device ids to an array
$deviceIds = array(
'lh142lk3h1o2141p2y412d3yp1234y1p4y1d3j4u12p43131p4y1d3j4u12p4313',
'y1p4y1d3j4u12p43131p4y1d3j4u12p4313lh142lk3h1o2141p2y412d3yp1234'
);
 
// this is where you can customize your notification
$payload = '{"aps":{"alert":"' . $message . '","sound":"default"}}';
 
$result = 'Start' . '<br />';
 
////////////////////////////////////////////////////////////////////////////////
// start to create connection
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'MyAppGenerated.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
 
echo count($deviceIds) . ' devices will receive notifications.<br />';
 
foreach ($deviceIds as $item) {
    // wait for some time
    sleep(1);
     
    // Open a connection to the APNS server
    $fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx);
 
    if (!$fp) {
        exit("Failed to connect: $err $errstr" . '<br />');
    } else {
        echo 'Apple service is online. ' . '<br />';
    }
 
    // Build the binary notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $item) . pack('n', strlen($payload)) . $payload;
     
    // Send it to the server
    $result = fwrite($fp, $msg, strlen($msg));
     
    if (!$result) {
        echo 'Undelivered message count: ' . $item . '<br />';
    } else {
        echo 'Delivered message count: ' . $item . '<br />';
    }
 
    if ($fp) {
        fclose($fp);
        echo 'The connection has been closed by the client' . '<br />';
    }
}
 
echo count($deviceIds) . ' devices have received notifications.<br />';
 
// function for fixing Turkish characters
function tr_to_utf($text) {
    $text = trim($text);
    $search = array('Ü', 'Þ', 'Ð', 'Ç', 'Ý', 'Ö', 'ü', 'þ', 'ð', 'ç', 'ý', 'ö');
    $replace = array('Ãœ', 'Åž', '&#286;ž', 'Ç', 'Ä°', 'Ö', 'ü', 'ÅŸ', 'ÄŸ', 'ç', 'ı', 'ö');
    $new_text = str_replace($search, $replace, $text);
    return $new_text;
}
 
// set time limit back to a normal value
set_time_limit(30);

Node.js -3 | Reading user input from the command line

Readline module, which comes with the Node.js core reads user input so that you can use it as an interaction.

In this example, the user will tell how many glasses of water he/she drinks each day and we’ll say if it’s healthy enough or not.

In the script.js file, require the module like:

var rl = require("readline");

Create the prompts variable:

var prompts = rl.createInterface(process.stdin, process.stdout);

Request user input with a question:

prompts.question("How many glass of water do you drink each day?", function (glasses) {
    var message = "";
    if (glasses > 5) {
        message = "Great! Water is the key of a healthy life.";
    } else {
        message = "Are you drinking just " + glasses + " glass of water? You should drink at least " + (6 - glasses) + " more.";
    }
    console.log(message);
    process.exit();
});

Output will be like:

$ node script.js
$ How many glass of water do you drink each day?
$ 5
$ Are you drinking just 5 glass of water? You should drink at least 1 more.
$ node script.js
$ How many glass of water do you drink each day?
$ 7
$ Great! Water is the key of a healthy life.

Node.js -2 | Modules: Custom Module and Sample Usage of Markdown Module

In this post, I’ll share some code about how to use modules in Node.js. I will use a custom module (user-defined) and a public module (Markdown module). The code samples are form Lynda.com’s Node.js lessons.

——

Defining a local module (A module that returns Fibonacci numbers)

1- In the root of Node.js application, navigate to node_modules folder and then create a dir for your module:

cd node_modules
mkdir data_module

2- Create module file:

nano fibonacci.js

And edit its content like this:

exports.data = [1,1,2,3,4,8,13,21];

Save and exit the editor.

3- In app root folder, create the main file:

cd ..
nano script.js

And edit like this:

// './' prefix tells that the module is local, not global
var sequence = require("./fibonacci");
console.log(sequence.data);

Note: “Local modules are useful for when you want to separate your data from your code.”

——

Markdown module simple usage

First, create a Node.js app with Markdown module dependency enabled and install these dependencies as I talked about here.

In your script.js file:

var parser = require("node-markdown");
var html = parser.Markdown("This is a **markdown** text.");
console.log(html);

Node.js -1 | Initialize a Node.js project with dependencies

Not so long ago I’ve started to study lessons about Node.js. There’s no need to praise or to talk about it or why I want to learn it, it just excites me as a new platform and I intend to keep studying unless I don’t feel like it’s not worth it -which I doubt.

Here I want to share my Node.js notes regularly, from very basic to the complex(hopefully).

———

Running Node.js scripts

Download and install from:

http://nodejs.org/

To build (run) a Node.js script:

node file.js

———

Initializing a node app and build it with dependencies

1- Initialize:

npm init

2- After initialization, package.json contains project information. You can add “dependencies” to this file like:

"dependencies": {
    "node-markdown": "0.1.0"
}

If you want to require latest version of a dependency module:

"node-markdown": "*"

3- Install these dependencies:

npm install

———

Some other useful stuff about managing the app

Update these dependencies to latest versions:

npm update

Update node.js global libraries:

npm update -g

Remove an installed library:

# remove from "dependencies" object in package.json, then:
npm prune

Search through node.js modules available for free:

npm search
# better not to use it without grep or it may take quite long time
npm search | grep markdown
# or find from http://npmjs.org

Tail changes of a file and execute it automatically on console after each change:

# -g installs as global
sudo npm install node-dev -g
node-dev script.js

———

No “Hello, world!” yet. These are just basics that we’ll probably do quite seldom.

Selecting Grouped Row Count When Using MySQL GROUP BY Column

You may have been using subqueries to get how many rows were grouped when using MySQL’s GROUP BY function. There’s a little trick that helps to get this number without using subqueries, more clean and faster (when the amount of rows get higher).

Let’s assume we have a table contain folks from different cities. Like this:

folk_name   |   city_name
---------------------------
evren       |   ohio
steve       |   ohio
cem         |   weston
don         |   sunderland
ritchie     |   weston
ian         |   hounslow
alican      |   ohio

When we want to get only city names (distinct) from this table, we may group the data by city_name column like this:

SELECT f.* FROM `folks` f GROUP BY f.`city_name`

And the result would be:

folk_name   |   city_name
---------------------------
ian         |   hounslow
evren       |   ohio
don         |   sunderland
cem         |   weston

The expected behaviour of GROUP BY is to select first rows so other folks from same cities do not appear. It also orders by the GROUP BY column (ascending).

Let’s say we want to get how many folks exist in each city by grouping by. First thing comes to mind could be using a subquery like this:

SELECT f1.*, (SELECT COUNT(f2.`folk_name`) FROM `folks` f2 WHERE f2.`city_name` = f1.`city_name`) AS `folk_count` FROM `folks` f1 GROUP BY `city_name`

And the result would be:

folk_name   |   city_name   |   folk_count
-------------------------------------------
ian         |   hounslow    |   1
evren       |   ohio        |   3
don         |   sunderland  |   1
cem         |   weston      |   2

Let’s admit, subqueries are messy. They make the query more complicated to read and also are question marks on performance.

How about selecting number 1 (one) for each row and sum it up on grouping by?

Doing something like this:

SELECT f.*,SUM(1) AS `folk_count` FROM `folks` f GROUP BY f.`city_name`

Would return:

folk_name   |   city_name   |   folk_count
-------------------------------------------
ian         |   hounslow    |   1
evren       |   ohio        |   3
don         |   sunderland  |   1
cem         |   weston      |   2

Nicely done.