Програмен код на PHP

Codeception

Лесен и достъпен начин за тестване на вашият код. Предимно за PHP приложения, но не е задължително.

Ако използвате Codeception може да покриете по всякакъв начин вашия код с unit, functional или acceptance тестове.

Документацията им е добре написана и лесно можете да започнете с първите си тестове.

Само като пример (с Composer) бих дал няколко команди които ще създадът всичко необходимо за създаване и изпълнение на Codeceptio тестове:

composer require codeception/codeception --dev
vendor/bin/codecept bootstrap
codecept generate:cept acceptance First
vendor/bin/codecept run

Това ще ви добави библиотеката, чрез Composer.
След това ще създаде стартова версия с unit, functional и acceptance тестови конфигурации.
Генерираме тестов файл с формат Cept за acceptance suit и име First.
Накрая пускаме проверка за всички тестове, които нямат никакви проверки, но все пак всички основни файлове са създадени и може да започнете доректно с покриването на вашия код.

След лекцията ми на RuseConf 2017, реших да дам малко повече публичност на начините за тестове. С тази публикация започвам серия от най-добри практики при писане не стандартни тестове.

Codeception има примерни тестове за много видове проекти, както и за фреймуърковете, които поддържат – Zend, Yii, Phalcon, Doctrene, Laravel, Simpfony, Silex..
Избрах да направя разширена версия на тестовете им на Laravel, за да покажа добри практики за по-напреднали тестове. Можете да я намерите в Github: https://github.com/ibpavlov/codeception-laravel5-advanced

, , , , ,

Няма коментари

JSON_NUMERIC_CHECK round-fix

Ако искате автоматично да преобразувате низове в числа при json_encode тогава един от начините е с JSON_NUMERIC_CHECK.

Но при него има доста често срещани проблеми като изрязването на телефоните и големите числа.

Това се отнася най-вече за запазени в някакъв обект, база от данни, или други които са пресметнати и са представени в консистентен формат. Например: при запазване на числата +123, 0123, 123 винаги ще се запазят като 123. Когато взимаме тези данни ние знаем, че подадените ни данни ще са вече изчислени, обработени и +123 не може да срещнем ако числото наистина не е низ от символи.

Ето една реализация на същата функционалност както при JSON_NUMERIC_CHECK, която не създава такива проблеми. Числата се заменят само ако не са толкова големи и ако не започват с „+“ или „0“ (т.е. са изчислени числа).


Опростената версия на кода:

function stringToNumeric(&$element)
{
    if(is_string($element) && is_numeric($element)) {
        //Check if normal int or float and change format
        if (ctype_digit($element) && strval(intval($element)) === $element) {
            $element = intval($element);
        } elseif(strval(doubleval($element)) === $element) {
            $element = doubleval($element);
        }
    }
}

function arrayStringsToNumeric(&$array) 
{
    array_walk_recursive($array, "stringToNumeric");
}

function jsonNumericEncode($data, $options = 0, $depth = 512)
{
    //if Has Numberic check and is_array do proper check
    if(($options & JSON_NUMERIC_CHECK) == JSON_NUMERIC_CHECK && is_array($data)) {
        //Remove numeric check
        $options = $options ^ JSON_NUMERIC_CHECK;
        //Make proper type
        array_walk_recursive($data, "stringToNumeric");
    }
    json_encode($data, $options, $depth);
}
jsonNumericEncode

Функцията замества използването на JSON_NUMERIC_CHECK, но може и да се ползва директно като премахнете тази проверка.

function prepareJsonData($data)
{
    //if Has Numberic check and is_array do proper check
    if((is_array($data) && !empty($data)) {
        //Make proper type
        array_walk_recursive($data, "stringToNumeric");
    }
}
$data = prepareJsonData($data);
json_encode($data);

Така накрая в данните може да получите

{
    "phone": "+525526262",
    "number: 12512521, 
    "phone2": "0025542424252",
    "money": 22.23
}

вместо

{
    "phone": 525526262,
    "number: 12512521, 
    "phone2": 25542424252,
    "money": 22.23
}

Има и друго решение, което според мен не е толкова ефективно. Можете да продължите с използването на JSON_NUMERIC_CHECK, но да промените малко данните за да се запазят все пак като низ от символи:

function prepareJsonWithNumberCheck(&$data) {
array_walk_recursive($data, function(&$element) {
    //Check if big int or number and add space
    $same = strval(intval($element)) == $element;
    if (ctype_digit($element) && !$same) {
        $element = "" . $element . " ";
    } elseif(!$same && !preg_match('/^(\+|0)[0-9]+$/', $element)) {
        $element = "" . $element . " ";
    }
});
}

, , ,

Няма коментари

Активна навигация

Ако имате статична или динамична навигация, много пъти при изкарването и в нов файл трябва да се предвиди как ще се проверява дали линка трябва да е активен за текущата страница.

Вместо да добавям някакъв сложен код към навигацията съм разработил проста функция, която просто трябва да се извика с името на линка.


Простата версия на кода:

function active ($find, $exact = FALSE)
{
	if ( $exact ) {
		$server = explode('/', $_SERVER['REQUEST_URI']);
		$uri = $server[count($server) - 1];
		if ( strcmp($uri, $find) == 0 ) {
			return 'class="active"';
		}
	} else if ( strpos($_SERVER['REQUEST_URI'], $find) !== FALSE ) {
		return 'class="active"';
	}

    return "";
}

Сложната, която работи с масив:

function active ($find, $exact = FALSE)
{
    if(is_array($find)) {
        $server = explode('/', $_SERVER['REQUEST_URI']);
        if(!empty($find))
            foreach($find as $element) {
                if ( $exact ) {
                    $uri = $server[count($server) - 1];
                    if ( strcmp($uri, $element) == 0 ) {
                        return 'class="active"';
                    }
                } else if ( strpos($_SERVER['REQUEST_URI'], $element) !== FALSE ) {
                    return 'class="active"';
                }
            }
    } else {
        if ( $exact ) {
            $server = explode('/', $_SERVER['REQUEST_URI']);
            $uri = $server[count($server) - 1];
            if ( strcmp($uri, $find) == 0 ) {
                return 'class="active"';
            }
        } else if ( strpos($_SERVER['REQUEST_URI'], $find) !== FALSE ) {
            return 'class="active"';
        }
    }

    return "";
}

Ако при линковете има други класове, може да се замени ‘class=“active“‘ с „active“.

Пример за използване:


Няма коментари

FPDF полезни функции

FPDF е клас на php за изработка на pdf документи. Чрез него може да направите точно каквото пожелаете.
За разлика от конвертирането на HTML към PDF, което не може да се контролира точно как ще се покаже, чрез FPDF имате пълен контрол.

Пълния контрол е свързан с много функции, по-дълго програмиране, но по-добър ефект.

Ето и няколко добри помощни функции, както и трикове за по-лесна употреба и контрол:

Задаване на разстояние между буквите (letter spacing):

function SetCharSpacing( $s_w , $s_l = 0) {
	$this->s_w = $s_w;
	$this->s_l = $s_l;
	$this->_out(
		'BT '.
		sprintf('%.3f Tc ', $this->s_w * $this->k).
		sprintf('%.3f Tw ', $this->s_l * $this->k).
		'ET '
	);
}

Изместване на текущата X, или Y позиция (без текст, без нов ред).

function Spacer($space) {
   $this->SetX($this->x + $space);
}

function SpacerY($space) {
    $this->y += $space;
}

Взимане дължината на реда:

function GetLineWidth() {
    return $this->w - $this->rMargin - $this->x;
}

Текст с булет за листа:

function SimpleListItem($w, $h, $txt, $border=0, $align='J', $fill=false, $listChar = '•') {
   $this->Spacer(6.4);
    $fs = $this->FontSizePt;
    $this->SetFont($this->FontFamily, '', 10);
    $this->Cell(6.4,3.5,$listChar);
    $this->SetFont($this->FontFamily, '', $fs);
    $this->MultiCell($w,$h,$txt,$border,$align,$fill);
}


Чекбокс, който се изразява в квадратче, което може да има тикче. Подобно на HTML chechbox, което се управлява само от една булева променлива

function Checkbox($checked = true) {
    $this->Rect($this->x,$this->y+0.4,4.1,3.8);
    if($checked) {
        $file = "images/checked.png";
        $w=3.5;
        $ax = $this->x+0.2;
        $ay = $this->y+0.6;
        $this->Image($file, $ax, $ay, $w, NULL, $type, $link);
    }
    $this->SetX($this->x + 4.1);
}

Има и други функции и класове, които са доста полезни:
Таблица, http://www.vonderborn.com/extended-tables-with-fpdf.php
HTML код, http://www.fpdf.de/downloads/addons/41/

Няма коментари

  1. Няма коментари.
(will not be published)