/ Gists / PHP

Gists - PHP

On gists

Token for JWT / Bearer

PHP

token-fn.php #

<?php

$currentTime = time();
$timeWindow = 500; // token expiration
$expectedToken = hash_hmac('sha256', $currentTime - ($currentTime % $timeWindow), 'OUR_ANY_SECRET');

// echo hash_equals($expectedToken, $anyTokenFromGetorPost);

On gists

Closure modifier

PHP

example.php #

<?php
//  TransportListResolver
	public function getList(Order\Order $order, ?\Closure $transportListResolverModifier = null): array
	{
		$orderItems = $order->getItems($order::ITEM_PRODUCT);

		$transportListResolver = $this->transport->getTransportSelectionResolver()
			->getBaseSelection()
			->setCountry($order->delivery__country_id)
			->setUserGroups($this->user->isLoggedIn() ? $this->user->getRoles() : NULL)
			->setWeight($order->getUniqueWeights())
			->setOnlyForProduct($this->transport->listTransportOnlyForProduct($orderItems))
			->setDistance(isset($order->distance) ? $order->distance : null);

		if ($transportListResolverModifier) {
			$transportListResolverModifier($transportListResolver);
		}

		$list = array_filter(
            $transportListResolver->toArray(),
            fn($transport) => !$transport->transport_carrier->mandatory_type_choice
				|| $this->transportTypeChoice->listTransportChoiceOnlyForProduct($transport->id, $orderItems)
				|| $this->transportTypeChoice->listTransportChoiceOnlyForProduct($transport->id, $orderItems) === null
			);

		return $list;
	}
	


// usage in another class
// we can modify object via closure
$transportList = $this->transportListResolver->getList($order, function (TransportEshopOrderSelectionResolver $transportListResolver) {
			$transportListResolver->setWithChoiceNeeded(true);
	});
	
	

On gists

Multiple params in fn - Solution

PHP DOC PHP Patterns

index.php #

<?php

// 1 config object
class FooConfig {
    public int $param1 = 0;
    public int $param2 = 0;
    public string $param3 = '';
    public string $param4 = '';
    public bool $param5 = false;
    public ?int $param6 = null;
    public int $param7 = 0;
    public string $param8 = '';
}

function Foo(FooConfig $config): void {
    // Použití: $config->param1, $config->param2, atd.
}

// Použití
$config = new FooConfig();
$config->param1 = 1;
$config->param2 = 5;
$config->param3 = "aaa";
$config->param4 = "bbb";
$config->param5 = false;
$config->param6 = null;
$config->param7 = 22;
$config->param8 = "ok";



// 2 array
/**
 * @param array{
 *   param1: int,
 *   param2: int,
 *   param3: string,
 *   param4: string,
 *   param5: bool,
 *   param6: mixed,
 *   param7: int,
 *   param8: string
 * } $params
 */
function Foo(array $params): void {
    // Použití: $params['param1'], $params['param2'], atd.
}

// Použití
Foo([
    'param1' => 1,
    'param2' => 5,
    'param3' => "aaa",
    'param4' => "bbb",
    'param5' => false,
    'param6' => null,
    'param7' => 22,
    'param8' => "ok"
]);



// 3 builder
class FooBuilder {
    private array $params = [];

    public function setParam1(int $value): self {
        $this->params['param1'] = $value;
        return $this;
    }

    public function setParam2(int $value): self {
        $this->params['param2'] = $value;
        return $this;
    }

    // Další metody pro nastavení parametrů...

    public function build(): Foo {
        return new Foo($this->params);
    }
}

class Foo {
    public function __construct(array $params) {
        // Inicializace s parametry
    }
}

// Použití
$foo = (new FooBuilder())
    ->setParam1(1)
    ->setParam2(5)
    ->setParam3("aaa")
    ->setParam4("bbb")
    ->setParam5(false)
    ->setParam6(null)
    ->setParam7(22)
    ->setParam8("ok")
    ->build();
    
    
    
  // 4 named   PHP 8+
  function Foo(
    int $param1 = 0,
    int $param2 = 0,
    string $param3 = '',
    string $param4 = '',
    bool $param5 = false,
    $param6 = null,
    int $param7 = 0,
    string $param8 = ''
) {
    // Funkční logika
}

// Použití
Foo(
    param1: 1,
    param2: 5,
    param3: "aaa",
    param4: "bbb",
    param5: false,
    param6: null,
    param7: 22,
    param8: "ok"
);



// Fluent
class FooParams {
    private int $param1 = 0;
    private int $param2 = 0;
    private string $param3 = '';
    private string $param4 = '';
    private bool $param5 = false;
    private $param6 = null;
    private int $param7 = 0;
    private string $param8 = '';

    public function param1(int $value): self {
        $this->param1 = $value;
        return $this;
    }

    public function param2(int $value): self {
        $this->param2 = $value;
        return $this;
    }

    // Další metody pro ostatní parametry...

    public function getParams(): array {
        return [
            'param1' => $this->param1,
            'param2' => $this->param2,
            // ...
        ];
    }
}

function Foo(array $params) {
    // Funkční logika
}

// Použití
$params = (new FooParams())
    ->param1(1)
    ->param2(5)
    ->param3("aaa")
    ->param4("bbb")
    ->param5(false)
    ->param6(null)
    ->param7(22)
    ->param8("ok");

Foo($params->getParams());

On gists

Splat operator

PHP

splat.php #

<?php


// rest ... a,b,c,d,e => []
function concatenate($transform, ...$strings) {
  $string = '';
  foreach($strings as $piece) {
    $string .= $piece;
  }
  return($transform($string));
}

echo concatenate("strtoupper", "I'm ", 20 + 2, " years", " old."); // I'M 22 YEARS OLD.


// spread ... []
function add($a, $b, $c) {
    return $a + $b + $c;
}

$operators = [2, 3];
echo add(1, ...$operators); // 6

On gists

Array to XML

PHP

class.php #


<?php

/**
 *
 * Array 2 XML class
 * Convert an array or multi-dimentional array to XML
 *
 * @author Kevin Waterson
 * @copyright 2009 PHPRO.ORG
 *
 */
class array2xml extends DomDocument
{

    public $nodeName;

    private $xpath;

    private $root;

    private $node_name;


    /**
    * Constructor, duh
    *
    * Set up the DOM environment
    *
    * @param    string    $root        The name of the root node
    * @param    string    $nod_name    The name numeric keys are called
    *
    */
    public function __construct($root='root', $node_name='node')
    {
        parent::__construct();

        /*** set the encoding ***/
        $this->encoding = "ISO-8859-1";

        /*** format the output ***/
        $this->formatOutput = true;

        /*** set the node names ***/
        $this->node_name = $node_name;

        /*** create the root element ***/
        $this->root = $this->appendChild($this->createElement( $root ));

        $this->xpath = new DomXPath($this);
    }

    /*
    * creates the XML representation of the array
    *
    * @access    public
    * @param    array    $arr    The array to convert
    * @aparam    string    $node    The name given to child nodes when recursing
    *
    */
    public function createNode( $arr, $node = null)
    {
        if (is_null($node))
        {
            $node = $this->root;
        }
        foreach($arr as $element => $value) 
        {
            $element = is_numeric( $element ) ? $this->node_name : $element;

            $child = $this->createElement($element, (is_array($value) ? null : $value));
            $node->appendChild($child);

            if (is_array($value))
            {
                self::createNode($value, $child);
            }
        }
    }
    /*
    * Return the generated XML as a string
    *
    * @access    public
    * @return    string
    *
    */
    public function __toString()
    {
        return $this->saveXML();
    }

    /*
    * array2xml::query() - perform an XPath query on the XML representation of the array
    * @param str $query - query to perform
    * @return mixed
    */
    public function query($query)
    {
        return $this->xpath->evaluate($query);
    }

} // end of class

?>

On gists

Transaction via callback ;)

Nette PHP

example.php #

<?php

// https://forum.nette.org/cs/22304-zavislost-jednoho-modelu-na-jinych

	/**
	 * @param Closure $callback
	 */
	private function doInTransaction(Closure $callback)
	{
		$this->isInTransaction = TRUE;
		$callback();
		$this->isInTransaction = FALSE;
	}
	
	
	// usage
	// any class
	private $isInTransaction = FALSE;
	
	
	
	/**
	 * @param int $id
	 * @param Player $owner
	 */
	public function __construct($id, Player $owner)
	{
		$this->id = $id;
		$this->owner = $owner;

		$this->doInTransaction(function () use ($owner) {
			$owner->receiveItem($this);
		});
	}



	/**
	 * @param Player $newOwner
	 */
	public function changeOwner(Player $newOwner)
	{
		if ($this->owner !== $newOwner) {
		  $this->doInTransaction(function () use ($newOwner) {
				$this->owner->giveItem($this);
				$this->owner = $newOwner;
				$this->owner->receiveItem($this);
			});
		}
	}

On gists

Google Spread Sheet via Google_Client

PHP Libs PHP

index.php #

<?php
/*

https://www.nidup.io/blog/manipulate-google-sheets-in-php-with-api

*/

require './vendor/autoload.php'; 

// configure the Google Client
$client = new \Google_Client();
$client->setApplicationName('Google Sheets API');
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]); 
$client->setAccessType('offline');
// credentials.json is the key file we downloaded while setting up our Google Sheets API
$path = '***'; //google console admin need to generate this file
$client->setAuthConfig($path);

// configure the Sheets Service
$service = new \Google_Service_Sheets($client);
$spreadsheetId = '***'; // get with share with and see to url



// the spreadsheet id can be found in the url https://docs.google.com/spreadsheets/d/143xVs9lPopFSF4eJQWloDYAndMor/edit
$spreadsheet = $service->spreadsheets->get($spreadsheetId);
var_dump($spreadsheet);


// all values
$range = 'List 1'; // here we use the name of the Sheet to get all the rows
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);



// rows by range
$range = 'List 1!A1:F10';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);



// cells of column
$range = 'List1!B1:B21'; // the column containing the movie title
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);



// rows into json objects
$range = 'Sheet1';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$rows = $response->getValues();
// Remove the first one that contains headers
$headers = array_shift($rows);
// Combine the headers with each following row
$array = [];
foreach ($rows as $row) {
    $array[] = array_combine($headers, $row);
}
var_dump($array);
/*
$jsonString = json_encode($array, JSON_PRETTY_PRINT);
print($jsonString);

*/


// append new row
$newRow = [
    '456740',
    'Hellboy',
    'https://image.tmdb.org/t/p/w500/bk8LyaMqUtaQ9hUShuvFznQYQKR.jpg',
    "Hellboy comes to England, where he must defeat Nimue, Merlin's consort and the Blood Queen. But their battle will bring about the end of the world, a fate he desperately tries to turn away.",
    '1554944400',
    'Fantasy, Action'
];
$rows = [$newRow]; // you can append several rows at once
$valueRange = new \Google_Service_Sheets_ValueRange();
$valueRange->setValues($rows);
$range = 'List 1'; // the service will detect the last row of this sheet
$options = ['valueInputOption' => 'USER_ENTERED'];
$service->spreadsheets_values->append($spreadsheetId, $range, $valueRange, $options);



// update existing
$updateRow = [
    '456740',
    'Hellboy Updated Row',
    'https://image.tmdb.org/t/p/w500/bk8LyaMqUtaQ9hUShuvFznQYQKR.jpg',
    "Hellboy comes to England, where he must defeat Nimue, Merlin's consort and the Blood Queen. But their battle will bring about the end of the world, a fate he desperately tries to turn away.",
    '1554944400',
    'Fantasy, Action'
];
$rows = [$updateRow];
$valueRange = new \Google_Service_Sheets_ValueRange();
$valueRange->setValues($rows);
$range = 'Sheet1!A2'; // where the replacement will start, here, first column and second line
$options = ['valueInputOption' => 'USER_ENTERED'];
$service->spreadsheets_values->update($spreadsheetId, $range, $valueRange, $options);



// delete some row
$range = 'Sheet1!A23:F24'; // the range to clear, the 23th and 24th lines
$clear = new \Google_Service_Sheets_ClearValuesRequest();
$service->spreadsheets_values->clear($spreadsheetId, $range, $clear);


/** with text formatting */
$range = 'List 1!B4';
$params = [
    'ranges' => $range,
    'fields' => 'sheets.data.rowData.values',
    'includeGridData' => true,
];

$response = $service->spreadsheets->get($spreadsheetId, $params);
$data = $response->getSheets()[0]['data'][0]['rowData'][0]['values'][0];

$formattedValue = $data['formattedValue'];
$hyperlink = $data['hyperlink'];
$userEnteredFormat = $data['userEnteredFormat'];

var_dump($formattedValue);
var_dump($hyperlink);
var_dump($userEnteredFormat);

On gists

Delete recursively from child to parent

PHP AW

delete-recursively-from-child.ph #

<?php

	private function deleteDuplicateRecursive(Tables\Navigation $duplicateItem)
	{
		/*
		// OLD
		$findDescendants = function(Tables\Navigation $parent, array $stack = [], $level = 1) use (&$findDescendants) {
			$children = $this->navigation->getAdjacencyList($parent->domain_id)->getChildren($parent->id);
			
			foreach ($children as $child) {
				$stack[$level][] = $child;
				$stack = $findDescendants($child, $stack, $level + 1);
			} 
				
			return $stack;
		};

		// mazeme deti odspoda nahoru
		$descendants = $findDescendants($duplicateItem);

		foreach (array_reverse($descendants, true) as $level => $descendantArr) {
			foreach ($descendantArr as $descendant) {
				$this->deleteDuplicate($descendant);
			}
		}
		*/

    // NEW, better, shorter
		$children = $this->navigation->getAdjacencyList($duplicateItem->domain_id)->getChildren($duplicateItem->id);
		foreach ($children as $child) {
			$this->deleteDuplicateRecursive($child);
		}

		// na zaver i roota
		$this->deleteDuplicate($duplicateItem);
	}

On gists

Normalizace dat

PHP AW

normalizace.php #

<?php 

// 1) single fns ..

$data = [
    '400,22 je super cislo a neobsahuje ani @',
    'Symbol @ je bezvič',
    '@@@ nebo XXX?',
    'Tady nic',
];

$NaNicToNeplati = function() {
    return null;
};

$NumberDashToDot = function($value) {
    if (preg_match('~\d+,\d+~', $value)) {
        return str_replace(',', '.', $value);
    }

    return null;
};

$RemoveZavinac = function($value) {
    if (preg_match('~@~', $value)) {
        return str_replace('@', '', $value);
    }

    return null;
};

$RemoveXXX = function($value) {
    if (preg_match('~X~', $value)) {
        return str_replace('X', 'maleX', $value);
    }

    return null;
};

$filters = [
    'NumberDashToDot' => $NumberDashToDot,
    'NaNicToNeplati' => $NaNicToNeplati,
    'RemoveZavinac' => $RemoveZavinac,
    'RemoveXXX' => $RemoveXXX,
];


 $evaluate = function($data, $filters) {
    $results = [];
    foreach ($data as $value) {
        $origValue = $value;
        $result = [
            'met' => [],
            'notMet' => [],
            'transformations' => [],
            'origValue' => $value,
            'finalValue' => null,
        ];

        foreach ($filters as $fnName => $fnClosure) {
            if ($valueNormalized = $fnClosure($value)) {
                $value = $valueNormalized;
                
                $result['met'][] = $fnName;
                $result['transformations'][$fnName] = $valueNormalized;
            } else {
                $result['notMet'][] = $fnName;
            }
        }

        
        $result['finalValue'] = $value;

        $results[] = $result;
    }

    return $results;

};

$results = $evaluate($data, $filters);

echo "<pre>";
print_r($results);
echo "</pre>";



// OOP
class DataTransformer
{
    private $filters;

    public function __construct(array $filters)
    {
        $this->filters = $filters;
    }

    public function transform(array $data): array
    {
        return array_map(function ($value) {
            $result = [
                'met' => [],
                'notMet' => [],
                'transformations' => [],
                'origValue' => $value,
                'finalValue' => null,
            ];

            foreach ($this->filters as $filter) {
                if ($filter->apply($value)) {
                    $result['met'][] = $filter->getName();
                    $result['transformations'][$filter->getName()] = $value;
                } else {
                    $result['notMet'][] = $filter->getName();
                }
            }

            $result['finalValue'] = $value;

            return $result;
        }, $data);
    }
}

interface FilterInterface
{
    public function apply(string &$value): bool;
    public function getName(): string;
}

class NumberDashToDotFilter implements FilterInterface
{
    public function apply(string &$value): bool
    {
        if (preg_match('~\d+,\d+~', $value)) {
            $value = str_replace(',', '.', $value);
            return true;
        }

        return false;
    }

    public function getName(): string
    {
        return 'NumberDashToDot';
    }
}

class RemoveZavinacFilter implements FilterInterface
{
    public function apply(string &$value): bool
    {
        if (strpos($value, '@') !== false) {
            $value = str_replace('@', '', $value);
            return true;
        }

        return false;
    }

    public function getName(): string
    {
        return 'RemoveZavinac';
    }
}

// Přidat další filtry podle potřeby

$data = [
    '400,22 je super cislo a neobsahuje ani @',
    'Symbol @ je bezvič',
    '@@@ nebo XXX?',
    'Tady nic',
];

$filters = [
    new NumberDashToDotFilter(),
    new RemoveZavinacFilter(),
    // Přidat další filtry podle potřeby
];

$transformer = new DataTransformer($filters);
$results = $transformer->transform($data);

echo "<pre>";
print_r($results);

On gists

Faster way than isset

PHP tricks - one liners PHP

isset.php #

<?php

/*
  if (isset($a['b'])) {
    $x = $a['b'];
    echo $x;
  }

*/

if ($x = ($a['b'] ?? null)) {
    echo $x;
}