Pixel Envision Ltd.
Mobile Game Development Studio
  • Home
  • About Us
  • Our Games
    • Hyper-Casual
    • Casual Games
      • Don’t Get Caught
      • Hordes of Enemies
      • noded
      • kubic
      • Whip Swing
      • Witches’ Brew
    • Kids Apps
      • Coloring Book
      • Cars & Trucks Puzzle
      • Train Puzzles for Kids
      • Animal Puzzle
      • Fairy Tale Puzzles for Kids
      • Find the Differences
  • Support
  • Privacy Policy
Select Page ...

Tag: Programming

PHP Credit Card Validation class using Mod 10 (Luhn) + more!

February 17, 2012 PHP, Programming

Here is another PHP code snippet from my library. This PHP class allows you to validate credit card information before processing it further. Doing all possible off-line checks before sending it to he credit card gateway will help you save time & money…

If the card is valid it will return cleaned & formatted card number along with the card type (Visa, Mastercard, Amex, Dinners, Discover, JCB & Maestro).

Besides regular checks, validates the card number against Mod 10 (Luhn) as well as know test card numbers…

Features

  • Checks if the card number, expiration date & validation numbers are valid.
  • Checks if the card is expired
  • Finds & returns the card type.
  • Checks against the known test card numbers.
  • Validates the card number using Mod 10 algorithm.

Usage Sample

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
require ('mod10.php');
$CARDTYPE = $ErrArr = NULL;
 
$cc = new CCVal($_POST["card_number"], $_POST["card_expire_month"], $_POST["card_expire_year"], $_POST["card_cvv2"]);
 
$cstatus = $cc->IsValid();
 
if ($cstatus[0] == "valid")
{
    $CARDTYPE = $cstatus[1];
    $_POST["card_number"] = $cstatus[2];
    $_POST["card_cvv2"] = $cstatus[3];
}
else
{
    $ErrArr = $cstatus;
}
?>

Download

  • Download PHP code snippet *UPDATED FOR AMEX CVV FIX
  • Code is PHP5 compatible but it should also work on PHP4 (Untested)

License

This code is free to use, distribute, modify and study. When referencing please link back to this website / post in any way e.g. direct link, credits etc. If you find this useful, please leave a comment and share using the buttons below!

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
<?php class CCVal
{
    var $__ccType = '';
    var $__ccNum = '';
    var $__ccExpM = 0;
    var $__ccExpY = 0;
    var $__ccCVV = '';
    function CCVal($num, $expm, $expy, $cvv)
    {
        if (!empty($num))
        {
            $cardNumber = ereg_replace("[^0-9]", "", $num);
            if (!empty($cardNumber))
            {
                $this - &gt;
                __ccNum = $cardNumber;
            }
        }
 
        if (!empty($cvv))
        {
            $cardCVV = ereg_replace("[^0-9]", "", $cvv);
            if (!empty($cardCVV))
            {
                $this - &gt;
                __ccCVV = $cardCVV;
            }
        }
 
        if (!is_numeric($expm) || $expm & lt;
        1 || $expm & gt;
        12)
        {
            $this - &gt;
            __ccExpM = NULL;
        }
        else
        {
            $this - &gt;
            __ccExpM = $expm;
        }
 
        $currentYear = date('Y');
        settype($currentYear, 'integer');
        $expy = $expy + 2000;
        if (!is_numeric($expy) || $expy & lt;
        $currentYear || $expy & gt;
        $currentYear + 15)
        {
            $this - &gt;
            __ccExpY = NULL;
        }
        else
        {
            $this - &gt;
            __ccExpY = $expy;
        }
 
        if (ereg("^5[1-5][0-9]{14}$", $this - &gt;
        __ccNum))
        {
            $this - &gt;
            __ccType = MASTERCARD;
        }
        elseif (ereg("^4[0-9]{12}([0-9]{3})?$", $this - &gt;
        __ccNum))
        {
            $this - &gt;
            __ccType = VISA;
        }
        elseif (ereg("^3[47][0-9]{13}$", $this - &gt;
        __ccNum))
        {
            $this - &gt;
            __ccType = AMEX;
        }
        elseif (ereg("^3(0[0-5]|[68][0-9])[0-9]{11}$", $this - &gt;
        __ccNum))
        {
            $this - &gt;
            __ccType = DINNERS;
        }
        elseif (ereg("^6011[0-9]{12}$", $this - &gt;
        __ccNum))
        {
            $this - &gt;
            __ccType = DISCOVER;
        }
        elseif (ereg("^(3[0-9]{4}|2131|1800)[0-9]{11}$", $this - &gt;
        __ccNum))
        {
            $this - &gt;
            __ccType = JCB;
        }
        elseif (ereg("^(5[06-8]|6)[0-9]{10,17}$", $this - &gt;
        __ccNum))
        {
            $this - &gt;
            __ccType = MAESTRO;
        }
        else
        {
            $this - &gt;
            __ccType = UNKNOWN;
        }
    }
 
    function IsValid()
    {
 
        $validFormat = false;
        $validExp = false;
        $passCheck = false;
        $validCVV = false;
        $testCard = false;
 
        switch ($this - &gt;
        __ccType)
        {
            case MASTERCARD:
                $validFormat = true;
            break;
            case VISA:
                $validFormat = true;
            break;
            case AMEX:
                $validFormat = true;
            break;
            case DISCOVER:
                $validFormat = true;
            break;
            case DINNERS:
                $validFormat = true;
            break;
            case JCB:
                $validFormat = true;
            break;
            case MAESTRO:
                $validFormat = true;
            break;
            default:
 
                $validFormat = false;
        }
 
        $cardExpM = $this - &gt;
        __ccExpM;
        $cardExpY = $this - &gt;
        __ccExpY;
 
        if ($cardExpM & amp; & amp;
        $cardExpY & amp; & amp;
        date('Ym') & lt; = $cardExpY . $cardExpM)
        {
            $validExp = true;
        }
        $cardCVV = $this - &gt;
        __ccCVV;
 
        if ($cardCVV & amp; & amp;
        (strlen($cardCVV) == 3 & amp; & amp;
        $this - &gt;
        __ccType != AMEX))
        {
            $validCVV = true;
        }
        elseif ($cardCVV & amp; & amp;
        (strlen($cardCVV) == 4 & amp; & amp;
        $this - &gt;
        __ccType == AMEX))
        {
            $validCVV = true;
        }
 
        $cardNumber = strrev($this - &gt;
        __ccNum);
        $numSum = 0;
 
        for ($i = 0;$i & lt;strlen($cardNumber);$i++)
        {
            $currentNum = substr($cardNumber, $i, 1);
            if ($i % 2 == 1)
            {
                $currentNum *= 2;
            }
            if ($currentNum & gt;
            9)
            {
                $firstNum = $currentNum % 10;
                $secondNum = ($currentNum - $firstNum) / 10;
                $currentNum = $firstNum + $secondNum;
            }
 
            $numSum += $currentNum;
        }
 
        $passCheck = ($numSum % 10 == 0);
 
        $testCard = in_array($this - &gt;
        __ccNum, array(
            '340000000000009',
            '341111111111111',
            '343434343434343',
            '346827630435344',
            '370000000000002',
            '370000200000000',
            '370407269909809',
            '370556019309221',
            '371449635398431',
            '374200000000004',
            '376462280921451',
            '377752749896404',
            '378282246310005',
            '378734493671000',
            '30000000000004',
            '30569309025904',
            '5019717010103742',
            '30204169322643',
            '30218047196557',
            '30221511563252',
            '36000000000008',
            '36148900647913',
            '36700102000000',
            '38000000000006',
            '38520000023237',
            '6011000000000004',
            '6011000000000012',
            '6011000400000000',
            '6011000990139424',
            '6011111111111117',
            '6011153216371980',
            '6011601160116611',
            '6011687482564166',
            '6011814836905651',
            '201400000000009',
            '201481123699422',
            '214925980592653',
            '214983972181233',
            '180001638277392',
            '180040153546898',
            '180058601526635',
            '3528000700000000',
            '3528723740022896',
            '3530111333300000',
            '3566002020360505',
            '3569990000000009',
            '630495060000000000',
            '6304900017740292441',
            '6333333333333333336',
            '5100080000000000',
            '5105105105105100',
            '5111111111111118',
            '5123619745395853',
            '5138495125550554',
            '5274576394259961',
            '5301745529138831',
            '5311531286000465',
            '5364587011785834',
            '5404000000000001',
            '5424000000000015',
            '5431111111111111',
            '5454545454545454',
            '5459886265631843',
            '5460506048039935',
            '5500000000000004',
            '5500939178004613',
            '5555555555554444',
            '5565552064481449',
            '5597507644910558',
            '6334580500000000',
            '6334900000000005',
            '633473060000000000',
            '6767622222222222222',
            '6767676767676767671',
            '5641820000000005',
            '6331101999990016',
            '6759649826438453',
            '4007000000027',
            '4012888818888',
            '4024007127653',
            '4222222222222',
            '4556069275201',
            '4556381812806',
            '4911830000000',
            '4916183935082',
            '4916603452528',
            '4929000000006',
            '4005550000000019',
            '4012888888881881',
            '4111111111111111',
            '4444333322221111',
            '4539105011539664',
            '4544182174537267',
            '4716914706534228',
            '4916541713757159',
            '4916615639346972',
            '4917610000000000',
            '4406080400000000',
            '4462000000000003',
            '4462030000000000',
            '4917300000000008',
            '4917300800000000',
            '4484070000000000',
            '4485680502719433'
        ));
 
        if ($validFormat & amp; & amp;
        $validExp & amp; & amp;
        $validCVV & amp; & amp;
        $passCheck & amp; & amp;
        !$testCard)
        {
            return array(
                "valid",
                $this - &gt;
                __ccType,
                $this - &gt;
                __ccNum,
                $this - &gt;
                __ccCVV
            );
        }
        else
        {
            $ERR = NULL;
            if (!$validFormat || !$passCheck) $ERR[] = "Invalid card number";
            if (!$validCVV) $ERR[] = "Invalid CVV2/CVC2 Number";
            if (!$validExp) $ERR[] = "Credit card has been expired";
            if ($testCard) $ERR[] = "Reserved card number";
            return $ERR;
        }
    }
}
?>

PHP Currency Converter

August 18, 2011 PHP, Programming

Here is another PHP code snippet from my library. This PHP function allows you to calculate exchange amounts between 49 countries and 33 currencies.

Function is based on the live conversion reference rates provided by European Central Bank.

Usage

  • First 3 parameters are required. First one is the origin currency and the second one is target currency.
  • First 2 parameters should be the same type. If you are doing a county code based conversion both must be country codes. If you are doing currency code based conversion, both should be currency codes.
  • 3rd parameter is the amount you want to be converted. Should be decimal digits without any currency signs or codes attached to it.
  • 4th parameter is optional and set as true by default. When enabled function will prepend or append the currency sign (or code) to the output amount. You may want to turn that off if you will use the returned amount in a calculation.
  • 5th and the last parameter is calculation precision. Controls the number of digits after the decimal point. Default is 5.

Usage Samples

  • currency_convert(“EUR”,”USD”,100)
  • currency_convert(“FR”,”GB”,98);
  • currency_convert(“AUD”,”CNY”,145,false,8);
  • currency_convert(“GR”,”DK”,3500,true,2);

Download

  • Download PHP code snippet
  • Code is PHP5 compatible but it should also work on PHP4 (Untested)

License

This code is free to use, distribute, modify and study. When referencing please link back to this website / post in any way e.g. direct link, credits etc. If you find this useful, please leave a comment and share using the buttons below!

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<?php
// Realtime currency converter by Pixel Envision (E.Gonenc)
// Version 1.0 - 18 August 2011
// Based on the live conversion reference rates provided by European Central Bank
// http://www.ecb.europa.eu/
function currency_convert($from, $to, $amount, $sign = true, $sensitivity = 5)
{
    $RATES = $BASE = $in = $out = $append = NULL;
 
    //Array of available countries & currencies
    $CURRENCY = array(
        "US" => "USD",
        "BE" => "EUR",
        "ES" => "EUR",
        "LU" => "EUR",
        "PT" => "EUR",
        "DE" => "EUR",
        "FR" => "EUR",
        "MT" => "EUR",
        "SI" => "EUR",
        "IE" => "EUR",
        "IT" => "EUR",
        "NL" => "EUR",
        "SK" => "EUR",
        "GR" => "EUR",
        "CY" => "EUR",
        "AT" => "EUR",
        "FI" => "EUR",
        "JP" => "JPY",
        "BG" => "BGN",
        "CZ" => "CZK",
        "DK" => "DKK",
        "EE" => "EEK",
        "GB" => "GBP",
        "HU" => "HUF",
        "LT" => "LTL",
        "LV" => "LVL",
        "PL" => "PLN",
        "RO" => "RON",
        "SE" => "SEK",
        "CH" => "CHF",
        "NO" => "NOK",
        "HR" => "HRK",
        "RU" => "RUB",
        "TR" => "TRY",
        "AU" => "AUD",
        "BR" => "BRL",
        "CA" => "CAD",
        "CN" => "CNY",
        "HK" => "HKD",
        "ID" => "IDR",
        "IN" => "INR",
        "KR" => "KRW",
        "MX" => "MXN",
        "MY" => "MYR",
        "NZ" => "NZD",
        "PH" => "PHP",
        "SG" => "SGD",
        "TH" => "THB",
        "ZA" => "ZAR"
    );
 
    if (strlen($from) == 2 && strlen($to) == 2)
    { //Operate using country code
        if (isset($CURRENCY[$from]))
        {
            $in = $CURRENCY[$from];
        }
        if (isset($CURRENCY[$to]))
        {
            $out = $CURRENCY[$to];
        }
    }
    elseif (strlen($from) == 3 && strlen($to) == 3)
    { //Operate using currency code
        if (in_array($from, $CURRENCY))
        {
            $in = $from;
        }
        if (in_array($to, $CURRENCY))
        {
            $out = $to;
        }
    }
    else
    {
        echo "Error: You should either use 2 digit country codes or 3 digit currency codes!";
    }
 
    if ($in && $out)
    { //Both currencies available, continue
        //Load live conversion rates and set as an array
        $XMLContent = file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
        if (is_array($XMLContent))
        {
            foreach ($XMLContent as $line)
            {
                if (ereg("currency='([[:alpha:]]+)'", $line, $currencyCode))
                {
                    if (ereg("rate='([[:graph:]]+)'", $line, $rate))
                    {
                        $RATES[$currencyCode[1]] = $rate[1];
                    }
                }
            }
        }
        if (is_array($RATES))
        {
 
            $RATES["EUR"] = 1; //Add EUR reference to array
            if ($in != "EUR")
            { //Normalize rate to given input
                $BASE = $RATES[$in];
                foreach ($RATES as $code => $rate)
                {
                    $RATES[$code] = round($rate / $BASE, $sensitivity);
                }
            }
 
            //Prepend or append the currency information
            if ($sign)
            {
                if ($out == "USD")
                {
                    echo "$";
                }
                elseif ($out == "EUR")
                {
                    echo "&euro;";
                }
                elseif ($out == "GBP")
                {
                    echo "&pound;";
                }
                elseif ($out == "JPY")
                {
                    echo "&yen;";
                }
                else
                {
                    $append = $out;
                }
            }
 
            echo round($amount * $RATES[$out], $sensitivity); //Output the converted amount
            if ($append)
            {
                echo " " . $append;
            }
 
        }
        else
        {
            echo "Error: Unable to load conversion rates!";
        }
 
    }
    else
    {
        echo "Error: Either one or both of given currencies are not available for conversion!";
    }
}
 
echo currency_convert("EUR", "USD", 1);
?>

Realtime lip-sync code snippet for Flash using AS3

August 17, 2011 Flash, Programming, Tips & Tricks

One of the flash projects I have been working on has required a lip sync talking. Dialogues were dynamic so frame by frame matching was out of the question. So, I ended up with the following action script 3 code which I’m sharing with you here…

It processes the input sound in real time, which returns the different values based on the sound volume and also outputs the sound itself.

You can use those values to match up mouth animation frames as provided in the sample. But you may also simulate the effect using a single mouth image and scaling it based on the values returned by the function…

Usage

  • FLA project is compatible with Flash CS4, contains sample speech & mouth animation images.
  • speech() is the the sound file linked from the library.
  • mouth is the animation clip that contains mouth drawings.

Downloads

  • Sample SWF file for preview.
  • Download FLA project

License

This code is free to use, distribute, modify and study. Mouth animation and the images provided in the sample FLA is NOT free to use in anyway. When referencing please link back to this website / post in any way e.g. direct link, credits etc. If you find this useful, please leave a comment and share using the buttons below!

ActionScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
- Copyright 2011 Pixel Envision (E.Gonenc)
- http://www.pixelenvision.com/
- support@pixelenvision.com
*/
 
var left: Number;
 
function processSound(event: SampleDataEvent): void {
  var bytes: ByteArray = new ByteArray();
  playerObject.sourceSnd.extract(bytes, 4096);
  bytes.position = 0;
  while (bytes.bytesAvailable & gt; 0) {
    left = bytes.readFloat() * 128;
    if (left & lt; 0) {
      left = -left;
    }
    var scale: Number = left * 2;
  }
  event.data.writeBytes(bytes);
 
  //Define mouth animation here
  if (scale & lt; 1) {
    mouth.gotoAndStop(1);
  } else if (scale & lt; 10) {
    mouth.gotoAndStop(2);
  } else if (scale & lt; 25) {
    mouth.gotoAndStop(3);
  } else if (scale & lt; 50) {
    mouth.gotoAndStop(4);
  } else {
    mouth.gotoAndStop(5);
  }
  //Define mouth animation here
 
  trace(scale);
}
 
var playerObject: Object = new Object();
playerObject.sourceSnd = new speech();
playerObject.outputSnd = new Sound();
playerObject.outputSnd.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound);
playerObject.outputSnd.play();
stop();

Finding visitors real IP using PHP

August 16, 2011 PHP, Programming

Third PHP snippet I’m sharing from my library is code that tries to get most accurate real IP of the visitor. There are few headers with the IP information but those can be populated with many different ip’s based on customers route to your server. This script evolved in time and I believe it returns a very accurate source IP based on the information given in the request headers. But if you find a bug or a way to enhance it more, let me know!

License

This code is free to use, distribute, modify and study. When referencing please link back to this website / post in any way e.g. direct link, credits etc. If you find this useful, please leave a comment and share using the buttons below!

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
function realip()
{
 
    $ip = trim($_SERVER['REMOTE_ADDR']);
 
    if ($_SERVER["HTTP_CLIENT_IP"])
    {
 
        if (preg_match("~\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}~", trim($_SERVER["HTTP_CLIENT_IP"])) && !preg_match("~^((0|10|127|169\.254|172\.(1[6-9]|2[0-9]|3[0-1])|192\.0\.2|192\.168|255\.255\.255)\.)~", trim($_SERVER["HTTP_CLIENT_IP"])))
        {
            $ip = trim($_SERVER["HTTP_CLIENT_IP"]);
        }
 
    }
    elseif ($_SERVER["HTTP_X_FORWARDED_FOR"])
    {
 
        foreach (explode(",", $_SERVER["HTTP_X_FORWARDED_FOR"]) as $key)
        {
 
            if (preg_match("~\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}~", trim($key)) && !preg_match("~^((0|10|127|169\.254|172\.(1[6-9]|2[0-9]|3[0-1])|192\.0\.2|192\.168|255\.255\.255)\.)~", trim($key)))
            {
                $ip = trim($key);
                break;
            }
 
        }
 
    }
    return ($ip);
}
 
$IP = realip();
?>

PHP e-mail validation code snippet

August 15, 2011 PHP, Programming

Validation of email

This is the second PHP snippet I’m sharing from my library. It is not very complicated but get’s the job done. It both checks for the email syntax (REGEX) and existence of the email domain by checking MX & A records…

License

This code is free to use, distribute, modify and study. When referencing please link back to this website / post in any way e.g. direct link, credits etc. If you find this useful, please leave a comment and share using the buttons below!

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$email = "test@domain.com";
 
if (!preg_match("/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)*\.\w{2,8}$/i", $email))
{
 
    //E-mail syntax is invalid
    
}
elseif (!checkdnsrr(array_pop(explode("@", $email)) , "MX") & amp; & amp;
!checkdnsrr(array_pop(explode("@", $email)) , "A"))
{
 
    //Email server is not valid
    
}
else
{
 
    //E-mail is valid
    
}
?>

ZIP (POSTAL) Code Validation Regex & PHP code for 12 Countries

August 14, 2011 PHP, Programming

For the last couple of years, I’ve been mostly doing PHP coding. As a result, I have small library of code snippets of my own. Those are simple but useful PHP codes that might save some time on your work!

First one I’m sharing here today is the combination of regular expression and the PHP code to do ZIP code (or Postal Code) validation for following 12 countries: United States of America, United Kingdom, Germany, Canada, France, Italy, Australia, Netherlands, Spain, Denmark, Sweden & Belgium.

Code is provided in PHP but the REGEX codes are universal and those can be used with other programming languages.

License

This code is free to use, distribute, modify and study. When referencing please link back to this website / post in any way e.g. direct link, credits etc. If you find this useful, please leave a comment and share using the buttons below!

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
$country_code = "US";
$zip_postal = "11111";
 
$ZIPREG = array(
    "US" => "^\d{5}([\-]?\d{4})?$",
    "UK" => "^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$",
    "DE" => "\b((?:0[1-46-9]\d{3})|(?:[1-357-9]\d{4})|(?:[4][0-24-9]\d{3})|(?:[6][013-9]\d{3}))\b",
    "CA" => "^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ])\ {0,1}(\d[ABCEGHJKLMNPRSTVWXYZ]\d)$",
    "FR" => "^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$",
    "IT" => "^(V-|I-)?[0-9]{5}$",
    "AU" => "^(0[289][0-9]{2})|([1345689][0-9]{3})|(2[0-8][0-9]{2})|(290[0-9])|(291[0-4])|(7[0-4][0-9]{2})|(7[8-9][0-9]{2})$",
    "NL" => "^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$",
    "ES" => "^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$",
    "DK" => "^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$",
    "SE" => "^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$",
    "BE" => "^[1-9]{1}[0-9]{3}$"
);
 
if ($ZIPREG[$country_code])
{
 
    if (!preg_match("/" . $ZIPREG[$country_code] . "/i", $zip_postal))
    {
        //Validation failed, provided zip/postal code is not valid.
        
    }
    else
    {
        //Validation passed, provided zip/postal code is valid.
        
    }
 
}
else
{
 
    //Validation not available
    
}
?>

PHP Cache Warmer (Preloader) for W3 Total Cache

August 3, 2011 PHP, Programming

If you haven’t noticed yet, this website is powered by WordPress and speed is optimized using W3 Total Cache… Previously I was using WP Super Cache but recently decided to try W3 Total Cache as it’s feature set (minify, cdn, etc.) is looking better. For my setup it actually worked better so I kept it as my caching plugin.

But it took me a while to figure out it’s “Cache Preload” option is not working well or at least not working as I expected. “Automatically prime the page cache” was checked but pages were not in cache…

After searching a bit I found the culprit. W3 Total Cache relies on internal cron of WordPress and it’s only triggered by site activity. If your site has no visitors for a while loading the pages will be slower because: 1. W3TC will check if the current page is cache and if it’s expired. 2. Needs to clean up that expired page and re-generate a current copy. 3. Finally serve that file.

My first attempt to fix that was trying to put a real cron job for wp-cron.php but that didn’t worked well. Cron was working but W3TC still failed to prime the cache. There are couple of threads about that at the wordpress support forums.

Optimus Cache Prime (OCP) is a smart cache preloader for websites with XML sitemaps. It crawls all URLs in a given sitemap so the web server builds cached versions of the pages before visitors or search engine spiders arrive.

My next attempt was trying to use Optimus Cache Prime, a Phyton script written by Patrick Mylund Nielsen.

That was exactly what I needed… But…

My host had Python 2.4 installed and ocp.py required 2.5+

I have asked my  hosting (Inmotion) but they said they cannot change that on shared hosting and I should move to virtual private server (VPS) just for that… Yeah, sure!

Finally, I have decided to stop being lazy and created my own solution using PHP which I will be sharing here with you.

Idea

This PHP script has the same basic idea as Optimus Cache Prime and uses sitemap.xml as it’s source.

It will read the sitemap.xml file, parse the local URL’s listed in it. Then checks if the cache file for that url exists in W3TC. If the cache exists it will skip that url. But if not, it will visit the link using minimal resources causing the W3TC re-create cache for that page.

System Requirements

  • PHP5 (Required due to SimpleXML, you may change that to use with earlier versions of PHP)
  • W3 Total Cache
  • WP Super Cache (Not tested! But it should work)

Usage

  • Copy the code into a php file (warm.php) and place it in the site root where sitemap.xml exists.
  • Review/edit the configuration options inside the script.
  • Set a cron job to run that script every 5 minutes (or even every minute as the code is very easy on the system resources.)
  • Sample: */5 * * * * php -q /home/youraccount/public_html/warm.php
  • Thats it!

Features

  • Reads sitemap.xml as a file, saving a web server call.
  • Checks for the local cache file before trying to re-cache, saving resources.
  • Optionally uses priority tags in sitemap.xml
  • Configurable page limit per session, useful for larger sites.
  • Frees memory and stops executing as soon as possible to save further resources.
  • Failsafe to stop executing in case of an url or network problem.
  • New: Option to fix trailing slash cache creation problem.

Code & Download

  • Current version: Version 2.1 – 21 August 2011
  • Download warm.php

License

This code is free to use, distribute, modify and study. If you modify it please keep my copyright intact. When referencing please link back to this website / post in any way e.g. direct link, credits etc. If you find this useful, please leave a comment and share using the buttons below!

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php
// W3 TOTAL CACHE WARMER (PRELOADER) by Pixel Envision (E.Gonenc)
// Version 2.1 - 21 August 2011
//Configuration options
$priority = true; //Use priorities defined in sitemap.xml (true/false)
$ppi = 10; //Pages to be cached per interval
$delay = 0.5; // Delay in seconds between page checks, default is half a second
$quiet = true; // Do not output process log (true/false)
$trailing_slash = false; // Add trailing slash to URL's, that might fix cache creation problems (true/false)
$sitemap = "sitemap.xml"; //Path to sitemap file relative to the warm.php
// Defaults for W3TC
$index = "_index.html"; //Cache file to check
$rootp = "wp-content/w3tc/pgcache"; //Root of cache
//Do not change anything below this line unless you know what you are doing
ignore_user_abort(true);
set_time_limit(600);
 
$xml = simplexml_load_file($sitemap);
$UL = $UP = array();
foreach ($xml->url as $url_list)
{
    $UL[] = $url_list->loc;
    $UP[] = $url_list->priority;
}
unset($xml);
if ($priority == true)
{
    arsort($UP, $sort_flags = SORT_NUMERIC);
}
$i = 0;
foreach ($UP as $key => $val)
{
 
    $path = $rootp;
    $url = $UL[$key];
    $sub = explode("/", $url);
    if ($sub[3])
    {
        $path .= "/" . urldecode($sub[3]);
    }
    if ($sub[4])
    {
        $path .= "/" . urldecode($sub[4]);
    }
    if ($sub[5])
    {
        $path .= "/" . urldecode($sub[5]);
    }
    $path .= "/" . $index;
 
    if (file_exists($path))
    {
        if ($quiet != true)
        {
            echo "Priority: " . $val . " => Skipped: " . $path . "\n";
        }
    }
    else
    {
        if ($trailing_slash == true)
        {
            $url = rtrim($url, "/") . "/";
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_NOBODY, true);
        $ret = curl_exec($ch);
        curl_close($ch);
        if ($ret)
        {
            $i++;
        }
        else
        {
            echo "Unable to connect $url, exiting...";
            break;
        }
        usleep($delay * 1000000);
        if ($quiet != true)
        {
            echo "Priority: " . $val . " => Warmed: " . $path . " by visiting " . $url . "\n";
        }
    }
    if ($i < $ppi)
    {
        flush();
    }
    else
    {
        break;
    }
 
}
exit;
?>

  • Tags

    3ds Max Coming Soon CoronaSDK Featured Flash Lua MAXScript PHP Programming Reviews Tips & Tricks Unity 3D Windows Phone
  • Recent Comments

    • Yogesh Singh on ZIP (POSTAL) Code Validation Regex & PHP code for 12 Countries
    • Admin on Maxscript – Vray Cubemap Generator for Unity
    • charlie on Maxscript – Vray Cubemap Generator for Unity
    • Mastan on PHP Currency Converter
    • Rakesh Vishnoi on ZIP (POSTAL) Code Validation Regex & PHP code for 12 Countries
    • Find us on

      amazonandroidapplefacebooklinkedintwitterwindowsyoutube
    • Company Information

      Pixel Envision Limited is a company registered in England, company number: 09558675. Registered Office: Preston Park House, South Road, Brighton, East Sussex, BN1 6SB, United Kingdom

    • Privacy Policy
    Copyright © 2011-2020 Pixel Envision Ltd, all rights reserved.