Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Last revisionBoth sides next revision
fuss:php [2017/11/12 21:42] – [Zip Directory and Download] officefuss:php [2017/12/08 15:46] office
Line 1: Line 1:
 +====== Wizardry and Steamworks JavaScript Libraries ======
 +
 +^ Name       ^ Link ^ Description ^
 +| ''was.php'' | [[php/composer/packages/was.php|was.php]] | General Purpose Library |
 +
 +====== Latitude Longitude and Mercator Coordinates ======
 +
 +The following snippets, adapted from [[http://blogs.msdn.com/greg_schechter|Greg Schechter's MSN Blog]] can be used to convert between Latitude and Longitude and mercator coordinates. This can be used with a mercator projection map such as the following map:
 +
 +{{fuss_php_world_mercator_projection.png?512|Mercator projection map. }}
 +
 +===== Latitude Longitude to Pixel =====
 +
 +The function ''wasGeoToMercatorPoint'' takes as input:
 +
 +  * latitude
 +  * longitude
 +  * map width
 +  * map height
 +  * left-most map (''0'' if  using the whole map of the world)
 +  * right-most map (''0'' if  using the whole map of the world)
 +
 +and returns an array containing the $(x,y)$ map coordinate.
 +
 +<code php>
 +function wasGeoToMercatorPoint($latitude, $longitude, $mapWidth, $mapHeight, $mapLeft=0, $mapTop=0) {
 +  $x = $mapLeft + ($longitude + 180) * $mapWidth / 360;
 +  $y = $mapTop + ($mapHeight/2) * (1-(log(tan(deg2rad($latitude)/2 + M_PI/4))) / M_PI);
 +  return array($x, $y);
 +}
 +</code>
 +
 +===== Pixel to Latitude and Longitude =====
 +
 +The function ''wasGeoToMercatorPoint'' takes as input:
 +
 +  * ''x'' - pixel location
 +  * ''y'' - pixel location
 +  * map width
 +  * map height
 +  * left-most map (''0'' if  using the whole map of the world)
 +  * right-most map (''0'' if  using the whole map of the world)
 +
 +and returns the latitude and longitude corresponding to the $(x,y)$ pixel on the map.
 +
 +<code php>
 +function wasMercatorPointToGeo($x, $y, $mapWidth, $mapHeight, $mapLeft=0, $mapTop=0) {
 +  $f = (($x-$mapLeft) * 360 / $mapWidth) - 180;
 +  $l = rad2deg (2 * atan ( exp ( M_PI * (1 - 2 * ($y-$mapTop)/$mapHeight ) ) ) - M_PI/2);
 +  return array($l, $f);
 +}
 +</code>
 +
 +====== Get Client IP ======
 +
 +The variable:
 +<code php>
 +$_SERVER['REMOTE_ADDR']
 +</code>
 +contains the address that the client connects from.
 +
 +The variable:
 +<code php>
 +$_SERVER['HTTP_X_FORWARDED_FOR']
 +</code>
 +contains the IP, if the client is using a proxy server.
 +
 +====== Get Server IP ======
 +
 +The variable:
 +<code php>
 +$_SERVER['SERVER_ADDR']
 +</code>
 +contains the IP address that the server is listening on.
 +
 +====== Remove Empty Strings From Array ======
 +
 +Filter the array through the built-in ''strlen'' function:
 +
 +<code php>
 +$clean_array = array_filter($dirty_array, 'strlen');
 +</code>
 +
 +====== Re-Index Array ======
 +
 +<code php>
 +$clean_array = array_values($dirty_array);
 +</code>
 +
 +====== JSON like Javascript Wrapper ======
 +
 +<code php>
 +#colin.mollenhour.com
 +function json_decode_nice($json, $assoc = FALSE){ 
 +    $json = str_replace(array("\n","\r"),"",$json); 
 +    $json = preg_replace('/([{,]+)(\s*)([^"]+?)\s*:/','$1"$3":',$json); 
 +    return json_decode($json,$assoc); 
 +
 +</code>
 +
 +====== Create UUID ======
 +
 +<code php>
 +<?php
 +class UUID {
 +  /**
 +   * Generates version 1: MAC address
 +   */
 +  public static function v1() {
 +    if (!function_exists('uuid_create'))
 +      return false;
 +
 +    uuid_create(&$context);
 +    uuid_make($context, UUID_MAKE_V1);
 +    uuid_export($context, UUID_FMT_STR, &$uuid);
 +    return trim($uuid);
 +  }
 +
 +  /**
 +   * Generates version 3 UUID: MD5 hash of URL
 +   */
 +  public static function v3($i_url) {
 +    if (!function_exists('uuid_create'))
 +      return false;
 +
 +    if (!strlen($i_url))
 +      $i_url = self::v1();
 +
 +    uuid_create(&$context);
 +    uuid_create(&$namespace);
 +
 +    uuid_make($context, UUID_MAKE_V3, $namespace, $i_url);
 +    uuid_export($context, UUID_FMT_STR, &$uuid);
 +    return trim($uuid);
 +  }
 +
 +  /**
 +   * Generates version 4 UUID: random
 +   */
 +  public static function v4() {
 +    if (!function_exists('uuid_create'))
 +      return false;
 +
 +    uuid_create(&$context);
 +
 +    uuid_make($context, UUID_MAKE_V4);
 +    uuid_export($context, UUID_FMT_STR, &$uuid);
 +    return trim($uuid);
 +  }
 +
 +  /**
 +   * Generates version 5 UUID: SHA-1 hash of URL
 +   */
 +  public static function v5($i_url) {
 +    if (!function_exists('uuid_create'))
 +      return false;
 +
 +    if (!strlen($i_url))
 +      $i_url = self::v1();
 +
 +    uuid_create(&$context);
 +    uuid_create(&$namespace);
 +
 +    uuid_make($context, UUID_MAKE_V5, $namespace, $i_url);
 +    uuid_export($context, UUID_FMT_STR, &$uuid);
 +    return trim($uuid);
 +  }
 +}
 +?>
 +</code>
 +
 +====== Format Current Time to MySQL DateTime Format ======
 +
 +<code php>
 +$mysqldate = date( 'Y-m-d H:i:s' );
 +</code>
 +
 +====== Change Owner and Group Recursively ======
 +
 +<code php>
 +///////////////////////////////////////////////////////////////////////////
 +//  Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3      //
 +///////////////////////////////////////////////////////////////////////////
 +function wasChown($path, $uid, $gid) {                                     
 +  switch(filetype($path)) {                                                
 +    case 'dir':                                                            
 +      if(($dir = opendir($path)) ==== false) break;                         
 +      while(false !== ($file = readdir($dir))) {
 +        if($file == '.' || $file == '..') continue;
 +        wasChown($path.'/'.$file, $uid, $gid);
 +      }
 +    case 'file':
 +      chown($path, $uid);  
 +      chgrp($path, $gid);  
 +      break;
 +  }
 +}
 +
 +</code>
 +
 +====== Prepared Statements ======
 +
 +Prepared statements are preferable where users can otherwise inject arbitrary code. In ''PHP'', ''PDO'' is a good library that can be used to created prepared statements and thereby alleviate the need to sanitise user-input.
 +
 +The following example for ''PHP'' and ''MySQL'' will insert a record into a table ''profile'' with the structure such as:
 +
 +^ ''Killer''      ^ ''ID''     ^
 +| ''Chris Myass'' | ''372453'' |
 +
 +The varaibles ''DATABASE'', ''HOST'', ''USERNAME'' and ''PASSWORD'' have to be defined and the variables ''killer'' and ''id'' have to be sent via POST:
 +
 +<code php>
 +$db = new PDO('mysql:dbname=DATABASE;host=HOST', USERNAME, PASSWORD);
 +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 +
 +try {
 +    $q = $db->prepare("INSERT INTO Profile(Killer, ID) VALUES(:killer, :id)");
 +    $q->execute(
 +        array(
 +            ':killer' => $_POST['killer'],
 +            ':name' => $_POST['id']
 +        )
 +    );
 +} catch (PDOException $e) {
 +    die($e->getMessage);
 +}
 +</code>
 +
 +Upon a failure to insert the row, the ''catch'' block triggers and the script dies while printing out the error message.
 +
 +====== Print Unicode Characters ======
 +
 +There are several variants to print unicode characters using ''PHP'', one of them is to use:
 +<code php>
 +mb_convert_encoding('&#x2665;', 'UTF-8', 'HTML-ENTITIES');
 +</code>
 +
 +where ''&#x2665;'' is the html entity corresponding to a ''♥'' character.
 +
 +Another variant is to use:
 +<code php>
 +html_entity_decode('&#x2665;', 0, 'UTF-8')
 +</code>
 +
 +which will also print the ''♥'' character.
 +
 +A very fast, yet ugly method of printing unicode characters is to use JSON:
 +<code php>
 +$unicodeChar = '\u2665';
 +echo json_decode('"'.$unicodeChar.'"');
 +</code>
 +
 +which is fast compared to the previous variants.
 +
 +====== Using Database Transactions ======
 +
 +Transactions ensure [[fuss/databases#a.c.i.d.|ACID properties]].
 +
 +<code php>
 +try {
 +    // Set the error mode to exceptions.
 +    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 +    
 +    // Begin the transaction
 +    $db->beginTransaction();
 +
 +    // A set of queries; if one fails, an exception should be thrown.
 +    // The transaction guarantees the atomicity of multiple queries.
 +    $db->query('first query');
 +    $db->query('second query');
 +    $db->query('third query');
 +
 +    // If we arrive here, it means that no exception was thrown
 +    // i.e. no query has failed, and we can commit the transaction
 +    $db->commit();
 +} catch (Exception $e) {
 +    // An exception has been thrown so we rollback the transaction.
 +    $db->rollback();
 +}
 +</code>
 +====== Recursively Pretty-Print Node Names and Values ======
 +
 +Using DOM we can traverse an entire XML structure and print out the nodes and their values in PHP.
 +
 +<code php>
 +# recurse over all nodes
 +function traverse(DomNode $node, $level = 0) {
 +    # print the current node
 +    print_node($node, $level);
 +    # if there are sub-nodes
 +    if ($node->hasChildNodes()) {
 +        # for each sub-node
 +        foreach($node->childNodes as $child) {
 +            # if it is a node
 +            if ($child->nodeType == XML_ELEMENT_NODE) {
 +                # recurse all sub-nodes
 +                traverse($child, $level + 1);
 +            }
 +        }
 +    }
 +}
 +
 +# determine if a node has children
 +function hasChild($parent) {
 +    if ($parent->hasChildNodes()) {
 +        foreach($parent->childNodes as $child) {
 +            if ($child->nodeType == XML_ELEMENT_NODE)
 +                return true;
 +        }
 +    }
 +    return false;
 +}
 +
 +# print the node with indenting
 +function print_node(DomNode $node, $level) {
 +    # print indenting
 +    do {
 +        print "\t";
 +    } while (--$level > -1);
 +
 +    # print tag name
 +    if ($node->nodeType == XML_ELEMENT_NODE) {
 +        print $node->tagName;
 +        if (!hasChild($node)) {
 +            print " -> ";
 +            print $node->nodeValue;
 +        }
 +    }
 +    print "\n";
 +}
 +
 +# create a new DOM document
 +$doc = new DomDocument("1.0");
 +# load an XML file
 +$doc->loadXML(file_get_contents('Corrade.ini'));
 +# the root is the first child
 +$root = $doc->firstChild;
 +# traverse the XML
 +traverse($root);
 +</code>
 +
 +====== Atomic Read and Write ======
 +
 +Since file-operations are generally not atomic operations, we can encase read and write operations using ''flock''. Thus, we obtain the equivalent of ''file_put_contents'':
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function atomized_put_contents($file, $data) {
 +    $fp = fopen($file, "w+");
 +    if (flock($fp, LOCK_EX)) {
 +        fwrite($fp, $data);
 +        fflush($fp);
 +        flock($fp, LOCK_UN);
 +    }
 +    fclose($fp);
 +}
 +</code>
 +
 +and the equivalent of ''file_get_contents'':
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function atomized_get_contents($file) {
 +    $fp = fopen($file, "r+");
 +    $ct = '';
 +    if (flock($fp, LOCK_SH)) {
 +        if (filesize($file)) {
 +            $ct = fread($fp, filesize($file));
 +        }
 +        flock($fp, LOCK_UN);
 +    }
 +    fclose($fp);
 +    return $ct;
 +}
 +</code>
 +
 +Note that ''atomized_get_contents'' is used like a generator function (requires PHP 5.5 where generators were introduced) and that whilst the functions are not atomic, the atomicity of the read and write operations is guaranteed provided the underlying system respects the file locks.
 +====== Permute Array Elements ======
 +
 +Given an array of elements these functions permute the array a certain number of times in both forward and reverse directions.
 +
 +===== Reverse =====
 +
 +The ''wasReversePermuteArrayElements'' function permutes the elements of an array in reverse.
 +
 +Given an array containing the elements:
 +<code>
 +a b c
 +</code>
 +
 +and calling the ''wasReversePermuteArrayElements'' function with the ''times'' parameter set to ''1'', we obtain an array containing the elements:
 +<code>
 +b c a
 +</code>
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function wasReversePermuteArrayElements($input, $times) {
 +    if ($times == 0) return $input;
 +    return wasReversePermuteArrayElements(
 +        array_merge(
 +            array_slice(
 +                $input,
 +                1
 +            ),
 +            array_slice(
 +                $input,
 +                0,
 +                1
 +            )
 +        ),
 +    --$times
 +    );
 +}
 +</code>
 +===== Forward =====
 +
 +The ''wasForwardPermuteArrayElements'' function permutes the elements of an array forward.
 +
 +Given a array string containing the elements:
 +<code>
 +a b c
 +</code>
 +
 +and calling ''wasForwardPermuteArrayElements'' function with the ''times'' parameter set to ''1'', we obtain the elements:
 +<code>
 +c a b
 +</code>
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function wasForwardPermuteArrayElements($input, $times) {
 +    if ($times == 0) return $input;
 +    return wasForwardPermuteArrayElements(
 +        array_merge(
 +            array_slice(
 +                $input,
 +                -1,
 +                1
 +            ),
 +            array_slice(
 +                $input,
 +                0,
 +                -1
 +            )
 +        ),
 +        --$times
 +    );
 +}
 +</code>
 +====== Cryptographic Functions ======
 +
 +The following is a list of cyphers implemented in PHP by Wizardry and Steamworks:
 +
 +{{indexmenu>fuss/php/cryptography/cyphers}}
 +
 +that can be used to encrypt and decrypt data.
 +
 +====== Map a Value in a Given Range to a Different Range ======
 +
 +The ''mapValueToRange'' takes as input a ''value'' with a range between ''xMin'' and ''xMax'' and scales the ''value'' in a range given by ''yMin'' and ''yMax'':
 +
 +<code php>
 +##########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function mapValueToRange($value, $xMin, $xMax, $yMin, $yMax) {
 +    return $yMin + (
 +        (
 +            $yMax - $yMin
 +        ) 
 +        *
 +        (
 +            $value - $xMin
 +        )
 +        /
 +        (
 +            $xMax - $xMin
 +        )
 +    );
 +}
 +</code>
 +
 +As an example, you can map an RGB component in the interval $[0, 255]$ to a $[0, 1]$ range by issuing:
 +<code php>
 +echo mapValueToRange(128, 0, 255, 0, 1);
 +</code>
 +
 +which will return approximately ''0.50196078431373''.
 +
 +====== Array Stride ======
 +
 +One of the problems in programming is frequently the need to return a indexed sub-set of elements from a given set. For example, given the set $S$:
 +
 +\begin{eqnarray*}
 +S &=& {1, 2, 3, 4, 5}
 +\end{eqnarray*}
 +
 +we want to obtain the sub-set $s$:
 +
 +\begin{eqnarray*}
 +s &=& \{x|x=i+s,i \in \mathbb{N} \}
 +\end{eqnarray*}
 +
 +where:
 +
 +  * $i$ is the index of the current element
 +  * $s$ is a given stride offset.
 +
 +This can be elegantly accomplished in PHP with the function ''wasArrayStride'':
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function wasArrayStride($a, $s) {
 +    return array_filter($a, 
 +        function($e, $i) use($s) {
 +            return $i % $s == 0;
 +        },
 +        ARRAY_FILTER_USE_BOTH
 +    );
 +}
 +</code>
 +
 +As an example, running:
 +<code php>
 +$a = array("a", "b", "c", "d", "e", "f");
 +var_dump(wasArrayStride($a, 2));
 +</code>
 +
 +will return:
 +<code>
 +a c e
 +</code>
 +
 +Note that if you wanted to obtain every third element, as in the sequence:
 +<code>
 +c f
 +</code>
 +
 +then you would call something like:
 +<code php>
 +var_dump(
 +    wasArrayStride(
 +        array_slice(
 +            $a, 
 +            2
 +        ), 
 +        3
 +    )
 +);
 +</code>
 +====== Convert Hexadecimal Color string to RGB ======
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function wasHexToRGB($hexStr, $toString = false, $seperator = ',') {
 +    $hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr);
 +    $rgbArray = array();
 +    switch(strlen($hexStr)) {
 +        case 6:
 +            $colorVal = hexdec($hexStr);
 +            $rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
 +            $rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
 +            $rgbArray['blue'] = 0xFF & $colorVal;
 +            break;
 +        case 3:
 +            $rgbArray['red'] = hexdec(
 +                str_repeat(substr($hexStr, 0, 1), 2));
 +            $rgbArray['green'] = hexdec(
 +                str_repeat(substr($hexStr, 1, 1), 2));
 +            $rgbArray['blue'] = hexdec(
 +                str_repeat(substr($hexStr, 2, 1), 2));
 +            break;
 +        default:
 +            return false;
 +    }
 +    return $toString ? implode($seperator, $rgbArray) : $rgbArray;
 +}
 +</code>
 +
 +You can then make a call such as:
 +<code php>
 +var_dump(hex2RGB(wasColorHash("Kira Komarov"), true));
 +</code>
 +====== Create Color from String ======
 +
 +Sometimes one needs to create a color to represent some data - for instance, to assign an unique color to a name. One very simple way to do that is to hash the string using some algorithm such as MD5 or SHA and then extract three pairs of two hexadecimal numbers from the hash. A good position is the start, the middle and the end which is what the ''wasColorHash'' function does:
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      ##
 +###########################################################################
 +function wasColorHash($a) {
 +  $hash = sha1($a);
 +  $size = strlen($hash);
 +
 +  return substr($hash, 0, 2).
 +         substr($hash, $size/2, 2).
 +         substr($hash, $size-2, 2);
 +}
 +</code>
 +
 +This gives us a total of ''16777215'' possible variations and, given a good hash, that would mean a ''0.000005960465%'' probability to select an unique color from the range.
 +
 +====== Resize PNG Image ======
 +
 +The ''wasResizePNG'' function resizes a PNG image with ''libgd'' given:
 +
 +  * an existing image passed to the parameter ''$img'',
 +  * the width to resize the image to passed to the parameter ''$w'',
 +  * the height to resize the image to passed to the parameter ''$h''.
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3      ##
 +###########################################################################
 +function wasResizePNG($img, $w, $h) {
 +    $width = imagesx($img);
 +    $height = imagesy($img);
 +    $new = imagecreatetruecolor($w, $h);
 + imagecolortransparent(
 + $new,
 + imagecolorallocate(
 + $new,
 + 0,
 + 0,
 + 0
 + )
 + );
 + imagecopyresampled(
 + $new,
 + $img,
 + 0,
 + 0,
 + 0,
 + 0,
 + $w,
 + $h,
 + $width, 
 + $height
 + );
 + imagedestroy($img);
 +    return $new;
 +}
 +</code>
 +
 +====== Add PNG Image Border ======
 +
 +The ''wasAddBorderPNG'' adds a border to an existing image with a given size and color. The ''wasAddBorderPNG'' function takes as parameters:
 +  * an existing PNG image passed as parameter ''$img'',
 +  * the size of the border in pixels passed as parameter ''$size'',
 +  * the color of the border passed as an associative array of ''red'', ''green'', ''blue'' to values in the range $0..255$.
 +
 +<code php>
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3      ##
 +###########################################################################
 +function wasAddBorderPNG($img, $size, $color) {
 +    $width = imagesx($img);
 +    $height = imagesy($img);
 +   
 +    $img_adj_width = $width + (2 * $size);
 +    $img_adj_height = $height + (2 * $size);
 +
 +    $new = imagecreatetruecolor(
 + $img_adj_width,
 + $img_adj_height
 + );     
 + imagecolortransparent(
 + $new,
 + imagecolorallocate(
 + $new,
 + 0,
 + 0,
 + 0
 + )
 + );
 +
 + $color = imagecolorallocate(
 + $new,
 + $color['red'],
 + $color['green'],
 + $color['blue']
 + );
 +    imagefilledrectangle(
 + $new,
 + 0,
 + 0,
 + $img_adj_width,
 + $img_adj_height,
 + $color
 + );
 +    imagecopyresized(
 + $new,
 + $img,
 + $size,
 + $size,
 + 0,
 + 0,
 +    $width,
 + $height,
 + $width,
 + $height
 + );
 + imagedestroy($img);
 + return $new;
 +
 +}
 +</code>
 +
 +An example call is the following:
 +<code php>
 +$img = imagecreatefrompng('was.png');
 +
 +# Add a red 5-pixel border around the image.
 +$img = wasAddBorderPNG(
 +    $img,
 +    5,
 +    array(
 +        "red" => 255, 
 +        "green" => 0, 
 +        "blue" => 0
 +    )
 +);
 +</code>
 +
 +====== Stack ======
 +
 +A stack implementation in PHP can be found on the [[fuss/php/data_structures/stacks|PHP stack data-structure page]].
 +
 +====== Queue =======
 +
 +A queue implementation in PHP can be found on the [[fuss/php/data_structures/queues|PHP queue data-structure page]].
 +
 +====== Y-Combinator ======
 +
 +By expressing the $Y$ combinator using the $\omega$ combinator [[fuss/lambda_calculus#Implementing the Y-Combinator|as explained]], the $Y$ combinator can be implemented in PHP.
 +
 +<code php>
 +<?php
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3      ##
 +###########################################################################
 +
 +$w = function($f) {
 +    return $f($f);
 +};
 +$Y = function($g) use ($w) {
 +    return $w(
 +        function($f) use ($g, $w) {
 +            return $g(
 +                function ($x) use ($f, $w) {
 +                    $f = $w($f);
 +                    return $f($x);
 +                }
 +            );
 +        }
 +    );
 +};
 +</code>
 +
 +An example call, to calculate the factorial of $6$, would be:
 +
 +<code php>
 +$factorial = $Y(
 +    function($f) {
 +        return function($n) use($f) {
 +            return $n <= 1 ? 1 : $n * $f($n - 1);
 +        };
 +    }
 +);
 +
 +echo $factorial(6);
 +</code>
 +====== Set Perl-Compatible Regular Expressions (PCRE) Recursion Limit ======
 +
 +You might get errors similar to:
 +<code>
 +php5-fpm[12598]: segfault at 7ffd38fdfff8 ip 00007fe1ec22ad8d sp 00007ffd38fdfe50 error 6 in libpcre.so.3.13.1[7fe1ec217000+6c000]
 +</code>
 +
 +in which case, you should set a PCRE recursion limit. This can be achieved by editing your PHP configuration (''php.ini'') and setting ''pcre.recursion_limit'' to some value:
 +<code>
 +pcre.recursion_limit=100
 +</code>
 +
 +====== Pretty-Print Variable Dump ======
 +
 +This can be accomplished using ''var_export'' instead of ''var_dump'':
 +<code php>
 +echo '<pre>' . var_export($data, true) . '</pre>';
 +</code>
 +
 +====== Zip Directory and Download ======
 +
 +The following script will create a zip file from the directory specified in the configuration section by the variable ''ZIP_DIRECTORY'' and will force the browser to download the file with the filename specified by ''ZIP_FILE_NAME''.
 +
 +<code php>
 +<?php
 +###########################################################################
 +##  Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3      ##
 +###########################################################################
 +
 +###########################################################################
 +#                            CONFIGURATION                                #
 +###########################################################################
 +
 +# The directory to compress.
 +$ZIP_DIRECTORY = getcwd().'/data/';
 +# The downloaded Zip file name.
 +$ZIP_FILE_NAME = 'Corrade-'.basename(__DIR__).'.zip';
 +
 +###########################################################################
 +#                              INTERNALS                                  #
 +###########################################################################
 +
 +# Create temporary directory.
 +function tempdir() {
 +    $tempfile = tempnam(sys_get_temp_dir(),'');
 +    # you might want to reconsider this line when using this snippet.
 +    # it "could" clash with an existing directory and this line will
 +    # try to delete the existing one. Handle with caution.
 +    if (file_exists($tempfile))
 +        unlink($tempfile);
 +    mkdir($tempfile);
 +    if (is_dir($tempfile))
 +        return $tempfile;
 +}
 +
 +$tempDir = tempdir();
 +
 +if(empty($tempDir))
 +    exit('Could not create temporary directory');
 +
 +$tempFile = $tempDir.'/'.$ZIP_FILE_NAME;
 +
 +# Initialize archive object
 +$zip = new ZipArchive();
 +$zip->open($tempFile, 
 +  ZipArchive::CREATE | ZipArchive::OVERWRITE | ZipArchive::CHECKCONS);
 +
 +# Create recursive directory iterator
 +/** @var SplFileInfo[] $files */
 +$files = new RecursiveIteratorIterator(
 +    new RecursiveDirectoryIterator($ZIP_DIRECTORY),
 +    RecursiveIteratorIterator::LEAVES_ONLY
 +);
 +
 +foreach($files as $name => $file) {
 +    # Skip directories (they would be added automatically)
 +    if($file->isDir())
 +        continue;
 +        
 +    # Get real and relative path for current file
 +    $filePath = $file->getRealPath();
 +    $relativePath = substr($filePath, strlen($ZIP_DIRECTORY));
 +
 +    # Add current file to archive
 +    $zip->addFile($filePath, $relativePath);
 +}
 +
 +# Zip archive will be created only after closing object
 +$zip->close();
 +
 +if(!file_exists($tempFile))
 +    exit('Zip file was not created.');
 +    
 +# Set headers and send file.
 +header('Pragma: public');
 +header('Expires: 0');
 +header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
 +header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($tempFile)) . ' GMT');
 +header('Content-Type: application/force-download');
 +header('Content-Disposition: inline; filename="'.$ZIP_FILE_NAME.'"');
 +header('Content-Transfer-Encoding: binary');
 +header('Content-Length: ' . filesize($tempFile));
 +header('Connection: close');
 +readfile($tempFile);
 +
 +# Remove temporary directory and contents.
 +$files = new RecursiveIteratorIterator(
 +    new RecursiveDirectoryIterator($tempDir,
 +        RecursiveDirectoryIterator::SKIP_DOTS),
 +    RecursiveIteratorIterator::CHILD_FIRST
 +);
 +
 +foreach($files as $name => $file) {
 +  if($file->isDir()) {
 +      rmdir($file->getRealPath());
 +      continue;
 +  }
 +  
 +  unlink($file->getRealPath());
 +}
 +
 +rmdir($tempDir);
 +
 +</code>
 +
 +This script is used to create zip files from the various releases to be found in the [[/secondlife/scripted_agents/corrade|Corrade]] Stitch repository.
  

fuss/php.txt · Last modified: 2022/04/19 08:28 by 127.0.0.1

Access website using Tor Access website using i2p Wizardry and Steamworks PGP Key


For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.