Использование preg_replace_callback в методе класса

<?php
/**
 * Использование preg_replace_callback в методе класса
 * автор: Nc_Soft
 * 03.01.09
 */

/*
Предположим, что надо сделать замену для смайлов
смайлы будут иметь вид <ЧИСЛО> и заменять это будем на <img src="/smile/ЧИСЛО.jpg" alt="" />
доп условия:
	-число замен не более 3
	-число в смайле должно соответствовать некоторому условию (в примере это диаппазон от 1 до 15)
*/

class Smile {

	//учитываем число замен
	private $smiles=0;

	//функция печати смайлов
	 function print_smiles($text) {
		return preg_replace_callback('|<(\d+)>|',array($this,'scb'),$text);
	}

	//функция обратного вызова для регулярки
	private function scb($v) {
		if ($this->smiles<3 && $v[1]>=1 && $v[1]<=15) {
			$this->smiles++;
			return '<img src="/smile/'.$v[1].'.jpg" alt="" />';
		}
		return $v[0];
	}
}

//пример
$s=new Smile();
echo $s->print_smiles('<1> <23><3><5><4>');

?>
3 января 2009, 03:56

Вывод файлов определенного типа при помощи SPL

<?php
/**
 * Вывод файлов определенного типа при помощи SPL
 * автор: Nc_Soft
 * 10.12.08
 */

/*напишем фильтр
для этого надо расширить FilterIterator, реализовав метод
accept()
*/
class F_FileIterator extends FilterIterator
{
	private $ext;
	private $it;

	function __construct(DirectoryIterator $it,$ext)
	{
		parent::__construct($it);
		$this->it=$it;
		$this->ext=$ext;
	}

	function accept()
	{
		return (pathinfo($this->current(),PATHINFO_EXTENSION)==$this->ext) ? true : false;
	}
}

//а теперь выведем из текущей директории только php файлы
$d=new F_FileIterator(new DirectoryIterator('./'), 'php');

foreach ($d as $v)
{
	echo "$v<br />\n";
}
?>
10 декабря 2008, 12:08

Подключение по https через CURL с посылкой сертификата

<?php
/**
 * Подкдючение по https через CURL с посылкой сертификата
 * автор: Nc_Soft
 * 19.11.08
 */

//!необходимо скачать сертификат ( в примере это WebMoneyCA.crt )

$ch=curl_init('https://w3s.webmoney.ru/asp/XMLInvoice.asp');
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
curl_setopt($ch, CURLOPT_CAINFO, 'WebMoneyCA.crt');
echo curl_exec($ch);

?>
19 ноября 2008, 20:38

Подключение по https через CURL

<?php
/**
 * Подкдючение по https через CURL
 * автор: Nc_Soft
 * 19.11.08
 */

//чтобы просто получить страницу!
$ch=curl_init('https://www.icq.com/register/');
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
echo curl_exec($ch);

?>
19 ноября 2008, 20:34

Удаленное определение степени gzip сжатия

<?php 
/** 
 * Удаленное определение степени gzip сжатия 
 * автор: Nc_Soft 
 * 15.11.08 
 */ 

//экзаменуемая страница 
$url='http://example.com'; 
$ch=curl_init($url); 
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
$bez=curl_exec($ch); 
curl_close($ch); 
$bez=strlen( $bez ); 

$ch=curl_init($url); 
curl_setopt($ch,CURLOPT_HTTPHEADER,array('Accept-Encoding: gzip, deflate')); 
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
$s=curl_exec($ch); 
curl_close($ch); 
$s=strlen( $s ); 

echo (1-$s/$bez)*100; 
echo '%'; 

?>
15 ноября 2008, 02:53

Переменная в шаблоне preg_replace

<?php
/**
 * Переменная в шаблоне preg_replace
 * автор: Nc_Soft
 * 14.11.08
 */

/*
источник: http://www.umi-cms.ru/company/vacansy/developer_php5/
задача:
Изменяя только переменные $foo и $bar выполнить функцию phpinfo в preg_replace.
*/
$foo = "the";
$bar = "THE";

$zoo = <<< END
Once upon tHe time were thE three bears...
END;

echo preg_replace("/{$foo}/im", $bar, $zoo);

/*
решение взято с http://kay.habrahabr.ru/blog/44590/
*/
$foo = "the/ie\0"; 
$bar = "phpinfo()";

echo preg_replace("/{$foo}/im", $bar, $zoo);

/*
ошибка в отсутствии фильтрации шаблона,
исправленный вариант:
*/
$foo = preg_quote($foo, '/');
echo preg_replace("/{$foo}/im", $bar, $zoo);

?>
14 ноября 2008, 14:59

Проверка хоста

<?php
/**
 * Проверка хоста
 * автор: Nc_Soft
 * 12.11.08
 */

//используется функция checkdnsrr, если ее нет (винда), то юзаем виндовскую nslookup
if(!function_exists('checkdnsrr')){
	function checkdnsrr($host, $type=''){
		if(!empty($host)){
			$type = (empty($type)) ? 'MX' :  $type;
			exec('nslookup -type='.$type.' '.escapeshellcmd($host), $result);
			$it = new ArrayIterator($result);
			foreach(new RegexIterator($it, '~^'.$host.'~', RegexIterator::GET_MATCH) as $result){
				if($result){
					return true;
				}
			}
		}
		return false;
	}
}

//проверим адрес
$url='http://wen.ru/forum';

if (checkdnsrr(parse_url($url,PHP_URL_HOST)))
{
	echo 'хост верен';
}
else 
{
	echo 'хост неверен';
}

//проверим кривой адрес
$url='http://gfghhrwen.ru/forum';

if (checkdnsrr(parse_url($url,PHP_URL_HOST)))
{
	echo 'хост верен';
}
else 
{
	echo 'хост неверен';
}

/*
все материалы на
http://php.net/checkdnsrr
*/
?>
12 ноября 2008, 22:22

Установка часового пояса

<?php
/**
 * Установка часового пояса
 * автор: Nc_Soft
 * 04.11.08
 */

/*
Знакома ситуация, когда часы у хостера работают в другом часовом поясе?
Конечно, можно править время во всех скриптах, аля time()+n*3600
но есть способ проще!
*/ 

//например, для Москвы добавьте эту строчку
putenv('TZ=Europe/Moscow');

//проверка
echo date('r');

/*
Посмотреть все зоны можно, например, тут http://www.timezoneconverter.com/
Конечно, это может сработать не на всех хостингах...
*/
4 ноября 2008, 15:35

Применение ON DUPLICATE KEY

<?php
/**
 * Применение ON DUPLICATE KEY
 * автор: Nc_Soft
 * 01.11.08
 */

/*
Допустим, у нас имеется таблица online юзеров, вот такая:
id | time
id - первичный или укальный ключ
нам надо обновлять время последнего пребывания юзера на сайте, либо добавить запись  в таблицу
*/

//Как это обычно делают в 2 запроса (НЕПРАВИЛЬНО!)
if (false===mysql_query("INSERT INTO online SET id='{$_SESSION['id']}', time=NOW() "))
{
	//если предыдущий запрос не прошел, то запись в таблице с ключом id уже есть, обновляем
	mysql_query("UPDATE online SET time=NOW() WHERE id='{$_SESSION['id']}' ");
}

//а теперь покажем как сделать правильно
mysql_query("INSERT INTO online SET id='{$_SESSION['id']}', time=NOW() ON DUPLICATE KEY UPDATE time=NOW() ");

/*
Как видите, применение ON DUPLICATE KEY позволяет уменьшить число запросов к бд
*/
1 ноября 2008, 13:14

Определение компьютер или мобильное устройство

<?php
/**
 * Определение компьютер или мобильное устройство
 * автор: waplog.net
 * 30.10.08
 */

/*в оригинальном скрипте ваплога (http://waplog.net/ru/html/faq.shtml)
есть один по моему мнению недочет: пустой юзер-агент считается мобилой
поэтому эта версия с доп условием !$h_ua
*/
$h_ua = str_replace('windows ce', '', strtolower($_SERVER['HTTP_USER_AGENT']));
if (
	!$h_ua ||
    strpos($h_ua, 'windows') !== false	||
	strpos($h_ua, 'linux') !== false	||
	strpos($h_ua, 'bsd') !== false		||
	strpos($h_ua, 'x11') !== false		||
	strpos($h_ua, 'unix') !== false		||
	strpos($h_ua, 'macintosh') !== false	||
	strpos($h_ua, 'macos') !== false)
{
	// it's computer - not show counter
} else {
	// it's mobile phone - show counter
	echo "your waplog counter code...";
}

/*
В целом, неплохой способ, пользуюсь сейчас им.
Я могу это утверждать, потому что перепробовал кучу разных методов :)
Единственный недостаток способа от ваплога: неучет мобильных устройств с платформой на линуксе. 
*/
?>
30 октября 2008, 19:51

Создание базы из дампа при помощи mysqli

<?php
/**
 * Создание базы из дампа при помощи mysqli
 * автор: Nc_Soft
 * 29.10.08
*/

/*
Часто бывает нужно загрузить sql-дамп, а в phpmyadmin лезть либо не хочется,
либо никак (с мобилы).
Что нам не хватает в обычном процедурном интерфейсе php-mysql?
Правильно, возможность совершить несколько запросов, разделенных ;
Сейчас я покажу как это сделать при помощи mysqli (разумеется, он должен быть на хостинге)
*/

//параметры доступа к бд
define('HOST','localhost');
define('USER','юзер');
define('DB','база');
define('PASS','пароль');

//коннектимся
$mysqli=new mysqli(HOST,USER,PASS,DB);
if (mysqli_connect_error()) die('access error');

//допустим, это файл дампа 
$dump='tables.sql';

//выполняем все запросы в дампе
$mysqli->multi_query(file_get_contents($dump));

//всё, база создана.
?>
29 октября 2008, 17:03

Определение принадлежности ip к диаппазону

<?php
/**
 * Определение принадлежности ip к диаппазону
 * автор: Nc_Soft
 * 28.10.08
 */

//пусть имеется диаппазон, допустим, Мегафона 83.149.0.0-83.149.7.255

//вспомогательная функция
function ext_ip2long($ip)
{
	return sprintf("%u",ip2long($ip));
}

//приведенный ip клиента
$ip=ext_ip2long($_SERVER['REMOTE_ADDR']);

//принадлежность
if (ext_ip2long('83.149.0.0')<=$ip && $ip<=ext_ip2long('83.149.7.255'))
{
	echo 'ip клиента принадлежит диаппазону';
}
else 
{
	echo 'ip клиента не принадлежит диаппазону';
}

/*
Почему же я стал городить доп-функцию, а не воспользовался
очевидным вариантом ip2long($ip) ?
Ответ в особенностях 32-битных систем:
echo ip2long('130.244.0.0') выдаст в 32 битной системе -2097938432
*/
?>
28 октября 2008, 01:38

Определение нагрузки сервера *nix (load averages)

<?php
/**
 * Определение нагрузки сервера (load averages)
 * автор: Nc_Soft
 * 13.10.08
 */

/*воспользуемся командой top, 
а чтобы можно было обработать вывод откроем канал*/
$la=popen('top','r');

//читаем первую строчку
$av=fgets($la);

//вытаскиваем текущую нагрузку (в %)
preg_match('|load averages:\s+(\d+\.\d+)|',$av,$arr);

//для порядка приводим к типу float
$average=(float)$arr[1];

//закрываем канал
pclose($f);

echo "текущая нагрузка: $average%";
?>
13 октября 2008, 10:13

Эффект "мокрого пола"

<?php
/**
 * Эффект "мокрого пола"
 * автор: MYPABEU (http://mypabeu.habrahabr.ru)
 * 30.09.08
 */

//путь к картинке
$img=imagecreatefrompng('c:/qqq.png');

//размер отраженного объекта в % от оригинала
$perc=50;

//максимальная прозрачность
$maxAlpha=120;

$src_height = imagesy($img);
$src_width = imagesx($img);
$dest_height = $src_height + ($src_height / (100/$perc));
$dest_width = $src_width;

$reflected = imagecreatetruecolor($dest_width, $dest_height);
imagealphablending($reflected, false);
imagesavealpha($reflected, true);

imagecopy($reflected, $img, 0, 0, 0, 0, $src_width, $src_height);
$reflection_height = $src_height / 2;
for($y=$src_height; $y<$dest_height; $y++)
{
	$alpha = (($y-$src_height)/($dest_height-$src_height))*$maxAlpha;

	for($x=0; $x<$src_width; $x++)
	{
		$rgba = imagecolorat($img, $x, $src_height - ($y-$src_height+1));
		$rgba = imagecolorsforindex($img, $rgba);
		$rgba = imagecolorallocatealpha($reflected, $rgba['red'], $rgba['green'], $rgba['blue'], $alpha);
		imagesetpixel($reflected, $x, $y, $rgba);
	}
}
$img = $reflected;

header('Content-type:image/png');
imagepng($img);

?>
30 сентября 2008, 15:53

Перекодировка из двухбайтового юникода в utf-8

<?php 
/** 
 * Перекодировка из двухбайтового юникода в utf-8 
 * автор: nc_soft 
 * 18.09.08 
 *  
 */ 

//может быть встречались с таким в j2me? 
$s='\u041f\u0440\u0435\u0432\u0435\u0434 \u041a\u0440\u0435\u0432\u0435\u0434\u043a\u043e!'; 

//чтобы перекодировать в нормальный вид можно пошаманить вот так 
echo preg_replace('#\\\\u([0-9a-f]{4})#se','iconv("UTF-16BE","UTF-8",pack("H4","$1"))',$s); 

/*надеюсь, кому-то пригодится, хотя эти заметки я пишу в основном для себя :)*/

//upd: способ номер 2
print_r( json_decode('["'.$s.'"]') );
18 сентября 2008, 18:07

Вычисление квадратного корня

<?php
/**
 * Вычисление квадратного корня
 * автор: Nc_Soft
 * 01.09.08
 */

//Задача: вычислить квадратный корень числа $n
$n=2;

//Конечно, можно воспользоваться стандартной функцией
echo sqrt($n);

/**
 * Но учитывая, что сегодня 1 сентября мы воспользуемся методом Ньютона — Рафсона :)
 */

//точность вычислений
$eps=0.0001;

//начальное приближение
$sqr = $n/2;

while (abs($sqr - ($n/$sqr)) > $eps) 
{
	$sqr = 0.5 * ($sqr + ($n/$sqr));
}

echo "<br />Квадратный корень из $n равен $sqr";
1 сентября 2008, 21:03

XSLT трансформация

<?php
/**
 * XSLT трансформация
 * автор: Nc_Soft
 * 19.07.08
 */

/*
пример трансформирует xml документ source.xml по шаблону
style.xsl
*/
$path_xml = "source.xml";
$path_style = "style.xsl";

// грузим XML документ
$xml = new DOMDocument;
$xml->load($path_xml);

//грузим шаблон
$xsl = new DOMDocument;
$xsl->load($path_style);

// создаем xslt обработчик
$proc = new XSLTProcessor;

//применяем таблицы
$proc->importStyleSheet($xsl);

//выводим результат
echo $proc->transformToXML($xml);

?>
19 июля 2008, 21:07

Оптимизация типов полей в таблице MYSQL

<?php
/**
 *Оптимизация типов полей в таблице MYSQL
 *автор: Nc_Soft
 *17.07.08
*/

/*
Для того, чтобы проверить, а оптимально ли вы подобрали типы полей есть 
очень полезный запрос (делайте в PhpMyAdmin или в прогах типа Navicat)
*/

SELECT * FROM table_name PROCEDURE ANALYSE();

/*
Анализировать желательно уже рабочую таблицу с заполненными данными, 
интересен прежде всего последний столбец, в котом система предлагает свои варианты
типов полей.
Естественно, это все имеет лишь рекоммендательный характер.
*/
17 июля 2008, 22:30

Перенаправление запросов к несуществующим файлам

#
# Перенаправление запросов к несуществующим файлам
# автор: nc_soft
# 04.07.08
#

#бывает удобно, когда запросы к несуществующим файлам 
#перенаправляются к какому-то определенному, на этом, кстати,
#и построена модель MVC

RewriteEngine on

RewriteBase / 

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d

RewriteRule ^(.*)$ index.php/$1

#теперь все левые запросы пойдут в index.php c $SERVER['REQUEST_URI']
4 июля 2008, 11:21

3D Captcha

<?php
/**
 * 3D Captcha
 * автор: KAndy (http://kandy.habrahabr.ru/)
 * 30.07.08
*/

/*
Прочитал на хабрахабре интересный топик
http://habrahabr.ru/blog/php/45463.html
понравилась реализация 
капчи, все четко и ничего лишнего, в стиле ооп
*/
 
$capthca = new Capthca3d(); 
$capthca->render(); 


class Capthca3d{ 
    const CHARS = 'WEafRTYIPAGHJKXBNM3479j'; 
    protected $hypot = 8; 
    protected $image = null; 
     
    protected $text = ''; 
     
    public function __construct() 
    { 
        $this->time = microtime(true); 
        $this->generateCode(); 
     
    } 
    protected function generateCode() 
    { 
        $chars = self::CHARS; 
        for($i =0; $i<3; $i++){ 
            $this->text .= $chars{ mt_rand(0,22)}; 
        } 
    } 
     
    public function getText() 
    { 
        return $this->text; 
    } 
    protected function getProection($x1,$y1,$z1) 
    { 
        $x = $x1 * $this->hypot;  
        $y = $z1 * $this->hypot; 
        $z = -$y1 * $this->hypot; 
         
        $xx = 0.707106781187;  
        $xy = 0; 
        $xz = -0.707106781187;  
         
        $yx = 0.408248290464;  
        $yy = 0.816496580928;  
        $yz = 0.408248290464; 
         
        $cx = $xx*$x + $xy*$y + $xz*$z; 
        $cy = $yx*$x + $yy*$y + $yz*$z+ 20 * $this->hypot; 
        return array( 
            'x' => $cx, 
            'y' => $cy 
            );  
    } 
     
    function zFunction($x,$y){ 
        $z = imagecolorat($this->image,$y/2,$x/2)>0?2.6:0; 
        if( $z != 0 ){ 
            $z += mt_rand(0,60)/100; 
        } 
        $z += 1.4 * sin(($x+$this->startX)*3.141592654/15)*sin(($y+$this->startY)*3.141592654/15); 
        return $z; 
    } 
    public function render()     
    { 
        $xx =30; 
         $yy =60; 
         
         $this->image = imageCreateTrueColor($yy * $this->hypot  , $xx * $this->hypot); 
         
        $whiteColor = imageColorAllocate($this->image,255,255,255); 
        imageFilledRectangle($this->image,0,0,$yy * $this->hypot  , $xx * $this->hypot,$whiteColor); 
         
        $textColor = imageColorAllocate($this->image,0,0,0); 
        imageString($this->image, 5, 3, 0, $this->text, $textColor); 
         
         
         $this->startX = mt_rand(0,$xx);     
         $this->startY = mt_rand(0,$yy); 
         
         $coordinates = array(); 
          
        for($x = 0; $x < $xx + 1; $x++){ 
            for($y = 0; $y < $yy + 1; $y++){ 
                $coordinates[$x][$y] = $this->getProection($x,$y,$this->zFunction($x,$y)); 
             } 
         } 
          
        for($x = 0; $x < $xx; $x++){ 
            for($y = 0; $y < $yy; $y++){ 
                 $coord = array(); 
                 $coord[] = $coordinates[$x][$y]['x']; 
                 $coord[] = $coordinates[$x][$y]['y']; 
                  
                 $coord[] = $coordinates[$x+1][$y]['x']; 
                 $coord[] = $coordinates[$x+1][$y]['y']; 
                  
                 $coord[] = $coordinates[$x+1][$y+1]['x']; 
                 $coord[] = $coordinates[$x+1][$y+1]['y']; 
                  
                 $coord[] = $coordinates[$x][$y+1]['x']; 
                 $coord[] = $coordinates[$x][$y+1]['y']; 
                 
                $c = (int) ($this->zFunction($x,$y)*32); 
                $linesColor = imageColorAllocate($this->image, $c, $c, $c); 
                imageFilledPolygon($this->image, $coord, 4, $whiteColor); 
                imagePolygon($this->image, $coord, 4, $linesColor); 
             } 
         } 
         
        $textColor = imageColorAllocate($this->image,0,0,0); 
        imageString($this->image, 5, 3, 0, $this->text, $whiteColor); 
        imageString($this->image, 1, 3, 0, (microtime(true)-$this->time), $textColor); 
        header('Content-Type: image/png'); 
         
        imagepng($this->image); 
        imagedestroy($this->image); 
    } 
}

?>
30 июня 2008, 11:45