понедельник, 27 декабря 2010 г.

Парсер простого HTML

Убирает не закрыте, не нужные теги и атрибуты. Выводит отчет.
Код - пример #1
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
<?php
 
error_reporting(-1);
 
class MyHtmlTidy
{
    const
        TAG  = '<(?:"[^"]*"|\'[^\']*\'|[^\'">])*>',
        ATTR = '\w++\s*=\s*"[^"]++"|\w++\s*=\s*\'[^\']++\'|\w++\s*=\s*[^\s]++';
 
    private
        $_goodTags  = array('b', 'i', 'u', 's', 'p', 'a', 'img', 'br', 'hr'),
        $_selfClose = array('img', 'br', 'hr'),
        $_goodAttrs = array(
                      'a'   => array('href', 'title'),
                      'img' => array('src', 'alt')),
        $_nest      = array();
 
    public
        $errors = array();
 
    public function preparse($html)
    {
        $this->_nest = array();
        $this->errors = array();
        $text = preg_replace_callback('/('.self::TAG.')/Uus', array($this, '_replace'), $html);
        if (!empty($this->_nest)) {
            $this->errors[] = 'Unclosed tags ' . implode(', ', $this->_nest);
            $text .= '</' . implode('></', array_reverse($this->_nest)) . '>';
        }
        return $text;
    }
 
    private function _replace($matches)
    {
        $tag = $matches[1];
 
        preg_match('/^<\/?(\w++)/', $tag, $m);
        $tagName = strtolower($m[1]);
        $isSelfClosed = $tag{strlen($tag) - 2} == '/';
        $attrs = trim(substr($tag, strlen($m[0]), ($isSelfClosed ? -2 : -1)));
 
        if (!in_array($tagName, $this->_goodTags)) {
            $this->errors[] = 'Tag ' . $tagName . ' is deprecated';
            return '';
        }
 
        // Closing tag
        if ($tag{1} == '/') {
            if (empty($this->_nest) || end($this->_nest) != $tagName) {
                $this->errors[] = 'Odd close tag ' . $tagName;
                return '<' . $tagName . '></' . $tagName . '>';
            }
            array_pop($this->_nest);
            return '</' . $tagName . '>';
        }
 
        // Open tag or self-closing tag
        $isSelfClosed = $isSelfClosed || in_array($tagName, $this->_selfClose);
 
        if (!$isSelfClosed) {
            $this->_nest[] = $tagName;
        }                       
 
        if (!isset($this->_goodAttrs[$tagName])) {
            // No attributes at all
            if (strlen($attrs)) {
                $this->errors[] = 'Tag ' . $tagName . ' cannot have attributes';
            }
            $attrs = '';
        } else {
            // Check every attribute
            preg_match_all('/'.self::ATTR.'/Uus', $attrs, $m);
            $attrs = $m[0];
            foreach ($attrs as $i => $attr) {
                $p = strpos($attr, '=');
                $attrName = strtolower(trim(substr($attr, 0, $p)));
                if (!in_array($attrName, $this->_goodAttrs[$tagName])) {
                    $this->errors[] = 'Wrong ' . $tagName . ' attribute ' . $attrName;
                    unset($attrs[$i]);
                } else {
                    $attrs[$i] = $attrName . '=' . trim(substr($attr, $p + 1));
                }
            }
            $attrs = count($attrs) ? (' ' . implode(' ', $attrs)) : '';
        }
   
        return '<' . $tagName . $attrs . ($isSelfClosed ? '/>' : '>');
    }
}
 
$t = new MyHtmlTidy();
 
$html = <<<HTML
<p class='blabla'>dslkldsldslsd<br>
kjksdjsdk<a href="http://thesite.name/path" target="_new" title="ololo" onclick="javascript:doit('xxx')">djdkjdk</a>
<img src=0.gif alt='pysh-pysh'>
ds;lsd;; <b>skjskjsk kjdkjdkd
HTML;
 
header('Content-type: text/plain');
 
echo $html;
echo "\n===========================\n";
 
$preparsed = $t->preparse($html);
if (!empty($t->errors)) {
    echo implode("\n", $t->errors);
    echo "\n===========================\n";
}
echo $preparsed;
Выводит:
Код - пример #1
<p class='blabla'>dslkldsldslsd<br>
kjksdjsdk<a href="http://thesite.name/path" target="_new" title="ololo" onclick="javascript:doit('xxx')">djdkjdk</a>
<img src=0.gif alt='pysh-pysh'>
ds;lsd;; <b>skjskjsk kjdkjdkd
===========================
Tag p cannot have attributes
Wrong a attribute target
Wrong a attribute onclick
Unclosed tags p, b
===========================
<p>dslkldsldslsd<br/>
kjksdjsdk<a href="http://thesite.name/path" title="ololo">djdkjdk</a>
<img src=0.gif alt='pysh-pysh'/>
ds;lsd;; <b>skjskjsk kjdkjdkd</b></p>
Скопипаситл с пыхи

воскресенье, 26 декабря 2010 г.

Пример нейронной сети на PHP

ИИ всегда интересовал меня. Если верить фантастам да и статьям из эпохи первых компьютеров, в наше время мы должны уже жить вместе с роботами с искусственным интеллектом. Но до сих пор, на сколько мне известно, разумного, мыслящего ИИ не создано.

Чтобы немного представить как работает нейронанная сеть, можно воспользоваться ниже приведенным примером:
Код - пример #1
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
/*
  Пример нейронной сети, которая учится отличать
  маленькие русские буквы от всех остальных.
  Язык - php.
  Пожалуйста, не удаляйте этот текст при копировании. (c) Секрет. Realme.ru
*/
class S { // глаза сети. Каждый глазик видит свою часть данных.
  var $input=0;
}
class A { // нейроны
  var $inputWeights=array(); // нейрон связан с каждым глазом с разной силой.
  var $active=0;
/*
  нейрон получает от всех глаз данные, единицу или ноль.
  Умножаем на силу связи глаз-нейрон, считаем среднее,
  сравниваем с 0.2 - это число выбрано интуитивно.
  Если поставить 1, сети потребуется в 4-5 раз больше обучающих примеров.
*/
  function think($s){
    reset($this->inputWeights);
    $this->active=0;
    while($temp=each($s)) {
       $temp2=each($this->inputWeights);
       $this->active+=($temp[1]->input)*$temp2[1];
    }
    $this->active/=count($s);
    $this->active=($this->active > 0.2);
  }
/*
при создании нейрона связываем с глазами случайным образом.
*/
  function __construct($s){
    $this->inputWeights=array();
    reset($s);
    while($temp=each($s)) {
       $this->inputWeights[]=mt_rand(0,100)/100;
    }
  }
}

class R {  // Решатель. Смотрит, что пришло от нейронов, считает среднее, выдаёт ответ.
  var $answer=array();
  function think($a){
    $this->answer=array();
    while($temp=each($a)) {
       $this->answer[]=$temp[1]->active;
    }
    return ((array_sum($this->answer)/count($this->answer)) > 0.5);
  }
}

$s=array();
$a=array();

// В символе восемь бит. Сделаем 8 глаз.
for($q=0;$q<8;$q++) $s[$q]=new S();
/*
 Cделаем 20 нейронов. Собственно, для решения этой задачи достаточно
 одного нейрона, он нормально обучается. Стоит 20 просто для примера.
*/
for($q=0;$q<20;$q++) $a[$q]=new A($s);
$r=new R(); 

$correct=0;
for($ww=0;$ww<10000;$ww++){ // просто цикл.

$input=rand(0,255);
/*
  Буква ё сложная для обучения, у неё код символа далеко от остальных русских букв.
  Поэтому увеличим частоту её выпадания.
*/
if (rand(1,100)==1) $input=ord('ё');
// правильный ответ нужен для процесса обучения.
$answer=((($input<=ord('я'))AND($input>=ord('а')))OR(ord('ё')==$input));
// ну или preg_match('/[а-яё]/',$input);, кому так понятнее.

for($q=0;$q<8;$q++) $s[$q]->input=($input & pow(2,$q)) >> $q;  // глазки смотрят.
for($q=0;$q<20;$q++) $a[$q]->think($s); // нейроны думают.
/*
  Процесс обучения.
  Для каждого нейрона смотрим, ответил ли он правильно.
  Почему нейрон ошибается? Потому что не знает, от каких глаз данные важнее.
  Например, если старший бит ноль, то русской буквой символ точно быть не может.
  Этого нейрон не поймёт, но научиться, что данные от старшего бита важнее, он может.
  Изменяем силу связи с теми глазами, которые видели единицу.
  Единицы от одних глаз станут влиять на результат сильнее, от других - слабее.
*/
for($q=0;$q<20;$q++) if ($a[$q]->active != $answer) {
  foreach($a[$q]->inputWeights as $k=>$v){
    if ($s[$k]->input) {
      $a[$q]->inputWeights[$k]+=(($answer)?0.01:-0.01);
    }
  }
}
$think=$r->think($a);
// считаем, сколько раз подряд ответили верно.
if ($think == $answer) {
  $correct++;
} else {
  $correct=0;
}
echo (int)$think;
echo (int)$answer;
echo ' '.chr($input).'';
if ($correct>500) {
  echo "Для обучения сети потребовалось $ww обучающих примеров.";
  break;
}
}

var_dump($s);
var_dump($a);
var_dump($r);
Пример взял вот отсюда

среда, 22 декабря 2010 г.

1kb javascript = 3d елка + снежинки

Код - пример #1
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
<html>
<body>
    <canvas id="c" height="446" width="446"></canvas>
 
    <script type="text/javascript">
    var b = document.body;
    var c = document.getElementsByTagName('canvas')[0];
    var a = c.getContext('2d');
    document.body.clientWidth; // fix bug in chrome.

    M = Math;
    Q = M.random;
    J = [];
    U = 16;
    T = M.sin;
    E = M.sqrt;
    for (O = k = 0; x = z = j = i = k < 200;) with(M[k] = k ? c.cloneNode(0) : c) {
        width = height = k ? 32 : W = 446;
        with(getContext('2d')) if (k > 10 | !k) for (font = '60px Impact', V = 'rgba('; I = i * U, fillStyle = k ? k == 13 ? V + '205,205,215,.15)' : V + (147 + I) + ',' + (k % 2 ? 128 + I : 0) + ',' + I + ',.5)' : '#cca', i < 7;) beginPath(fill(arc(U - i / 3, 24 - i / 2, k == 13 ? 4 - (i++) / 2 : 8 - i++, 0, M.PI * 2, 1)));
        else for (; x = T(i), y = Q() * 2 - 1, D = x * x + y * y, B = E(D - x / .9 - 1.5 * y + 1), R = 67 * (B + 1) * (L = k / 9 + .8) >> 1, i++<W;) if (D < 1) beginPath(strokeStyle = V + R + ',' + (R + B * L >> 0) + ',40,.1)'),
        moveTo(U + x * 8, U + y * 8),
        lineTo(U + x * U, U + y * U),
        stroke();
        for (y = H = k + E(k++) * 25, R = Q() * W; P = 3, j < H;) J[O++] = [x += T(R) * P + Q() * 6 - 3, y += Q() * U - 8, z += T(R - 11) * P + Q() * 6 - 3, j / H * 20 + ((j += U) > H & Q() > .8 ? Q(P = 9) * 4 : 0) >> 1]
    }
    setInterval(function G(m, l) {
        A = T(D - 11);
        if (l) return (m[2] - l[2]) * A + (l[0] - m[0]) * T(D);
        a.clearRect(0, 0, W, W);
        J.sort(G);
        for (i = 0; L = J[i++]; a.drawImage(M[L[3] + 1], 207 + L[0] * A + L[2] * T(D) >> 0, L[1] >> 1)) {
            if (i == 2e3) a.fillText('ЕУЫЕ!', U, 345);
            if (! (i % 7)) a.drawImage(M[13], ((157 * (i * i) + T(D * 5 + i * i) * 5) % W) >> 0, ((113 * i + (D * i) / 60) % (290 + i / 99)) >> 0);
        }
        D += .02
    },
    1)

    </script>
</body>
</html> 
По моему офигенско! смотреть лучше в Chrome
Демка

среда, 15 декабря 2010 г.

Удобный класс для парсинга HTML на PHP

Сам класс с примерами работы:
Код - пример #1
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
<?php

$html = gzdecode(file_get_contents('http://habrahabr.ru/'));

$saw = new nokogiri($html);
var_dump($saw->get('a.habracut')->toArray());
/* На выходе: Array(6) { [0]=> array(3) { 
 ["class"]=> string(8) "habracut"
 ["href"]=> string(56) "http://habrahabr.ru/blogs/google_chrome/110099/#habracut"
 ["#text"]=> string(29) "Читать дальше >" } [1]=> ....
*/ 
var_dump($saw->get('ul.panel-nav-top li.current')->toArray());
/* На выходе: array(2) {
 ["class"]=> string(7) "current" ["a"]=> array(3) {
 ["href"]=> string(20) "http://habrahabr.ru/"
 ["class"]=> string(8) "disabled"
 ["#text"]=> string(10) "Посты" } }
*/ 
var_dump($saw->get('#sidebar dl.air-comment a.topic')->toArray());
/* На выходе: array(50) {
 [0]=> array(3) { ["class"]=> string(5) "topic"
 ["href"]=> string(36) "http://habrahabr.ru/blogs/os/110045/"
 ["#text"]=> string(63) "ФБР внедряло backdoor'ы в IPSec код OpenBSD (?)" } [1]=> array(3) { ["cl
*/
var_dump($saw->get('a[rel=bookmark]')->toArray());
/* На выходе: array(10) {
 [0]=> array(4) {
 ["rel"]=> string(8) "bookmark"
 ["href"]=> string(47) "http://habrahabr.ru/blogs/google_chrome/110099/"
 ["class"]=> string(5) "topic" ["#text"]=> string(100) "Google объявил Chrome готовым..." }
 [1]=> array(4) {
 ["rel"]=
*/

/**
 * Description of nokogiri
 *
 * @author olamedia
 */
class nokogiri implements IteratorAggregate{
    protected $_source = '';
    /**
     * @var DOMDocument
     */
    protected $_dom = null;
    /**
     * @var DOMXpath
     * */
    protected $_xpath = null;
    public function __construct($htmlString = ''){
        $this->loadHtml($htmlString);
    }
    public static function fromHtml($htmlString){
        $me = new self();
        $me->loadHtml($htmlString);
        return $me;
    }
    public static function fromDom($dom){
        $me = new self();
        $me->loadDom($dom);
        return $me;
    }
    public function loadDom($dom){
        $this->_dom = $dom;
        $this->_xpath = new DOMXpath($this->_dom);
    }
    public function loadHtml($htmlString = ''){
        $dom = new DOMDocument('1.0', 'UTF-8');
        $dom->preserveWhiteSpace = false;
        if (strlen($htmlString)){
            libxml_use_internal_errors(TRUE);
            $dom->loadHTML($htmlString);
            libxml_clear_errors();
        }
        $this->loadDom($dom);
    }
    function __invoke($expression){
        return $this->get($expression);
    }
    public function get($expression){
        if (strpos($expression, ' ') !== false){
            $a = explode(' ', $expression);
            foreach ($a as $k => $sub){
                $a[$k] = $this->getXpathSubquery($sub);
            }
            return $this->getElements(implode('', $a));
        }
        return $this->getElements($this->getXpathSubquery($expression));
    }
    protected function getXpathSubquery($expression){
        $query = '';
        if (preg_match("/(?P<tag>[a-z0-9]+)?
                        (\[(?P<attr>\S+)=(?P<value>\S+)\])?
                        (#(?P<id>\S+))?
                        (\.(?P<class>\S+))?/ims", $expression, $subs)){
            $tag = $subs['tag'];
            $id = $subs['id'];
            $attr = $subs['attr'];
            $attrValue = $subs['value'];
            $class = $subs['class'];
            if (!strlen($tag))
                $tag = '*';
            $query = '//'.$tag;
            if (strlen($id)){
                $query .= "[@id='".$id."']";
            }
            if (strlen($attr)){
                $query .= "[@".$attr."='".$attrValue."']";
            }
            if (strlen($class)){
                //$query .= "[@class='".$class."']";
                $query .= '[contains(concat(" ", normalize-space(@class), " "), " '.$class.' ")]';
            }
        }
        return $query;
    }
    protected function getElements($xpathQuery){
        $newDom = new DOMDocument('1.0', 'UTF-8');
        $root = $newDom->createElement('root');
        $newDom->appendChild($root);
        if (strlen($xpathQuery)){
            $nodeList = $this->_xpath->query($xpathQuery);
            if ($nodeList === false){
                throw new Exception('Malformed xpath');
            }
            foreach ($nodeList as $domElement){
                $domNode = $newDom->importNode($domElement, true);
                $root->appendChild($domNode);
            }
            return self::fromDom($newDom);
        }
    }
    public function toXml(){
        return $this->_dom->saveXML();
    }
    public function toArray($xnode = null){
        $array = array();
        if ($xnode === null){
            $node = $this->_dom;
        }else{
            $node = $xnode;
        }
        if ($node->nodeType == XML_TEXT_NODE){
            return $node->nodeValue;
        }
        if ($node->hasAttributes()){
            foreach ($node->attributes as $attr){
                $array[$attr->nodeName] = $attr->nodeValue;
            }
        }
        if ($node->hasChildNodes()){
            if ($node->childNodes->length == 1){
                $array[$node->firstChild->nodeName] = $this->toArray($node->firstChild);
            }else{
                foreach ($node->childNodes as $childNode){
                    if ($childNode->nodeType != XML_TEXT_NODE){
                        $array[$childNode->nodeName][] = $this->toArray($childNode);
                    }
                }
            }
        }
        if ($xnode === null){
            return reset(reset($array)); // first child
        }
        return $array;
    }
    public function getIterator(){
        $a = $this->toArray();
        return new ArrayIterator($a);
    }
}
Ошибки html игнорируются.
Распознаются вложеные теги (через пробел), а также конструкции вида .class, #id и [attr=value]
Создание из строки: nokogiri::fromString($htmlString); или new nokogiri($htmlString);
Создание из DomDocument: nokogiri::fromDom($dom);

Требования:
DOM, libxml, php 5.3 (вероятно работает и со многими старыми версиями)
HTML на входе должен быть в кодировке UTF-8
Код - пример #1
1
2
3
foreach ($saw->get('#sidebar a.topic') as $link){
    var_dump($link['#text']);
}
Предыдущие версии можно найти здесь. Скопипастил с хабра

mFram - мини MVC фреймворк PHP

mFram - мой мини фреймворк на PHP

Зачем:

  1. Чтобы лучше разобраться с MVC, ООП и патернами проектирования
  2. Он очень простой, легкий и быстрый, особенно для меня
  3. Я немного разбирался с Zend Framework, Yii, на Code Igniter даже чегото кодил ) но в каждом из них мне что то нравиться и что то нет
  4. Я привык к шаблонизатору Smarty поэтому он здесь по умолчанию, можно его убрать и поставить например Twig и пр.
  5. Мне понравился css framework blueprint и он тоже здесь есть
  6. Мне нравиться мой стиль и формат кода :) нравиться когда первая буква переменной (префикс) означает ее тип:

a - массив s - строка i - число f - число дробное o - объект h - указатель (handler)

http://code.google.com/p/mfram/

Как прибавить к дате месяцы PHP, MySQL

Прибавить корректно месяцы к текущей дате средствами PHP не тривиальная задача.
Код - пример #1
1
date("d-m-Y",mktime(0,0,0,date("m")+1,date("d"),date("Y"));
Такой вариант возможен, если количество месяцев не перевалит за 12, т.е надо писать функцию...

А вот на SQL гораздо проще все, поподробнее можно посмотреть тут.
Код - пример #1
1
NOW() + INTERVAL 3 MONTH

понедельник, 13 декабря 2010 г.

Лучшая функция xml2array php

Код - пример #1
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
function xml2array(&$string) {
    $parser = xml_parser_create();
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parse_into_struct($parser, $string, $vals, $index);
    xml_parser_free($parser);
    $mnary=array();
    $ary=&$mnary;
    foreach ($vals as $r) {
        $t=$r['tag'];
        if ($r['type']=='open') {
            if (isset($ary[$t])) {
                if (isset($ary[$t][0])) $ary[$t][]=array(); else $ary[$t]=array($ary[$t], array());
                $cv=&$ary[$t][count($ary[$t])-1];
            } else $cv=&$ary[$t];
            if (isset($r['attributes'])) {foreach ($r['attributes'] as $k=>$v) $cv['_a'][$k]=$v;}
            $cv['_c']=array();
            $cv['_c']['_p']=&$ary;
            $ary=&$cv['_c'];
        } elseif ($r['type']=='complete') {
            if (isset($ary[$t])) { // same as open
                if (isset($ary[$t][0])) $ary[$t][]=array(); else $ary[$t]=array($ary[$t], array());
                $cv=&$ary[$t][count($ary[$t])-1];
            } else $cv=&$ary[$t];
            if (isset($r['attributes'])) {foreach ($r['attributes'] as $k=>$v) $cv['_a'][$k]=$v;}
            
            if (isset($r['value'])) $cv['_v'] = $r['value'];
        } elseif ($r['type']=='close') {
            $ary=&$ary['_p'];
        }
    }    
    
    _del_p($mnary);
    return $mnary;
}
function _del_p(&$ary) {
    foreach ($ary as $k=>$v) {
        if ($k==='_p') unset($ary[$k]);
        elseif (is_array($ary[$k])) _del_p($ary[$k]);
    }
}
Скопипастил с себе подобного блога

Функция закрытия незакрытых тегов в HTML

Код - пример #1
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
/**
 * close all open xhtml tags at the end of the string
 *
 * @param string $html
 * @return string
 * @author Milian Wolff <mail@milianw.de>
 */
 
function closetags($html) {
    #put all opened tags into an array
    preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
    $openedtags = $result[1];
    
    #put all closed tags into an array
    preg_match_all('#</([a-z]+)>#iU', $html, $result);
    $closedtags = $result[1];
    $len_opened = count($openedtags);
    
    # all tags are closed
    if (count($closedtags) == $len_opened) {
        return $html;
    }
    $openedtags = array_reverse($openedtags);
    
    # close tags
    for ($i=0; $i < $len_opened; $i++) {
        if (!in_array($openedtags[$i], $closedtags)){
            $html .= '</'.$openedtags[$i].'>';
        } else {
            unset($closedtags[array_search($openedtags[$i], $closedtags)]);
        }
    }
    return $html;
}

imTimer профайлер для PHP

Когда то он находился на блоге imbolc, которого уже давно нет. Вот поэтому blogspot рулит. Думаю блоги эти будут жить пока есть Google :)
Код - пример #1
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
function imTimer($name= 'default', $mode= ''){
    static $timers= array();
    $now=microtime(true);
    if(!isset($timers[$name])){
        $timers[$name]= $now;
        return 0;
    }
    $ret= $now - $timers[$name];
    if($mode == 'reset')
        $timers[$name]= $now;
    return round($ret, 5);
}

// пример использования

// запускаем
imTimer();

... // здесь типа много кода

imTimer('temp');

function temp() {
... // кучка говнокода
}
// выводим время выполнения функции temp
echo imTimer('temp');

... // еще код

// выводим время выполнения всего скрипта
echo imTimer();

Notice, Warning логирование ошибок PHP

Как-же отключить эти варнинги, нотисы, чтоб работа скрипта php не ломала дизайн сайта и при этом, сохраняя возможность, давать разработчику отзывы. Это просто, хотя многие не знают как. Если у вас свой сервер, настройте php.ini по примеру моих настроек:
Код - пример #1
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
; Показывать все ошибки, включая нотисы, варнинги
error_reporting = E_ALL | E_STRICT

; Не показывать ошибки
display_errors = Off

; Отключить вывод ошибок при старте выполнения php, ошибки при выполнении на клиенте.
display_startup_errors = Off

; Записывать ошибки в логи
log_errors = On

; размер файла ошибок
log_errors_max_len = 1024

; Не записывать повторяющиеся ошибки
ignore_repeated_errors = On

; Это повторные ошибки, которые впрочем можно и включить, теперь они нам не страшны (Off)
ignore_repeated_source = On

; Логгировать утечки памяти
report_memleaks = On

; Трассировка ошибок (дебагинг). Это больше полезно разработчикам php систем вроде cms
track_errors = Off

; Формат вывода ошибок в виде html. Нам ссылки не нужны, мы пишем в текстовый файл
html_errors = Off

; Путь к файлу ошибок.
error_log =  "\apache\logs\php_error.log"
.htaccess если у вас хостинг и нет доступа к php.ini

В php скрипте включить выключить можно так:
Код - пример #1
1
2
ini_set("display_errors", "0");
error_reporting(E_ALL);

четверг, 9 декабря 2010 г.

Авторизация PHP

Код - пример #1
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
// если пользователь не авторизован
if (!isset($_SESSION['user_id'])) {
    // то проверяем его куки
    // вдруг там есть логин и пароль к нашему скрипту
 
    if (isset($_COOKIE['login']) && isset($_COOKIE['password'])) {
        // если же такие имеются
        // то пробуем авторизовать пользователя по этим логину и паролю
        $login = mysql_real_escape_string($_COOKIE['login']);
        $password = mysql_real_escape_string($_COOKIE['password']);
 
        // и по аналогии с авторизацией через форму:
 
        // делаем запрос к БД
        // и ищем юзера с таким логином и паролем
 
        $query = "SELECT `id`
                FROM `users`
                WHERE `login`='{$login}' AND `password`='{$password}'
                LIMIT 1";
        $sql = mysql_query($query) or die(mysql_error());
 
        // если такой пользователь нашелся
        if (mysql_num_rows($sql) == 1) {
            // то мы ставим об этом метку в сессии (допустим мы будем ставить ID пользователя)
 
            $row = mysql_fetch_assoc($sql);
            $_SESSION['user_id'] = $row['id'];
 
            // не забываем, что для работы с сессионными данными,
            // у нас в каждом скрипте должно присутствовать session_start();
        }
        else {
            // только мы не будем давай ссылку на форму авторизации
            // вдруг человек и не хочет был авторизованым
            // а пришел просто поглядеть на наши страницы как гость
        }
    }
}

jQuery - как получить value radio элемента

Код - пример #1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ========= 1 вариант ==========
Cтрана: <br />
<input type="radio" name="country" value="Russia" checked="checked">Россия <br />
<input type="radio" name="country" value="Other">Другая

...

var the_value = $(":radio[name=country]").filter(":checked");

// ========= 2 вариант ==========
<form id="radio_form">
  <fieldset>
    <label><input type="radio" name="color" value="red" checked="checked" />Red</label><br />
    <label><input type="radio" name="color" value="yellow" />Yellow</label><br />    
    <label><input type="radio" name="color" value="blue" />Blue</label><br />
    <label><input type="radio" name="color" value="purple" />Purple</label><br />
  </fieldset>
</form>

...

var the_value = $('#radio_form input:radio:checked').val();

среда, 8 декабря 2010 г.

Как удалить денвер

Как деинсталлировать Денвер?
Комплекс полностью автономен и останется таковым. Поэтому для легальной деинсталляции Денвера достаточно просто удалить директорию, в которую вы его установили (По умолчанию –C:\WebServers ). При желании можете также стереть ярлыки с Рабочего стола и из Автозагрузки (если забудете, система сама об этом напомнит при следующей загрузке).

Если вы перед удалением Денвера не завершили его работу корректно (перезагрузившись или ярлыком остановки), то, вероятно, Вам придется вручную «почистить» файлС:\WINDOWS\system32\drivers\etc\hosts (в Windows NT/2000/XP/2003) или C:\WINDOWS\hosts (в WIndows 9x или Me), чтобы адреса [Не проверен] и test2.ru перестали вести на локальную машину, а «смотрели» в Интернет.

Таким образом, для деинсталляции Денвера достаточен следующий порядок действий:
1. Остановите Денвер 2. Если виртуальный диск создаётся по умолчанию, в Start -> Run нужно выполнить следующую команду (если необходимо, замените Z на Вашу букву виртуального диска): subst Z: /D 3. Удалите папку инсталляции Денвера (по умолчанию C:\WebServers) 4. Удалите, если необходимо, ярлык из Автозагрузки 5. Удалите ярлыки Запуска/Останова Комплекса

четверг, 11 ноября 2010 г.

Netbeans Горячие клавиши

Я работаю с IDE Netbeans и Notepad++

маст хэв - горячие клавиши для Netbeans

* Поиск и замена

Ctrl+F3 - Поиск слова, находящегося у курсора
F3/Shift+F3 - Поиск слудующего/предыдущего вхождения слова в файле
Ctrl+F/H - Поиск/Замена в файле
Alt+F7 - Поиск использований
Ctrl+Shift+F/H - Поиск/замена в проектах
Alt+Shift+U - Поиск результатов использования
Alt+Shift+H - Отключить подсветку результата поиска
Ctrl+R - Переименовать
Ctrl+U, then U - Конвертация выделенного текста в верхний регистр
Ctrl+U, then L - Конвертация выделенного текста в нижний регистр
Ctrl+U, then S - Инверсия регистра букв выделенного текста
Ctrl+Shift+V - Вставка отформатированного текста
Ctrl+I - Перейти в поле "Быстрый Поиск"

* Навигация по исходному коду

Ctrl+O/Alt+Shift+O - Перейти к типу/файлу
Ctrl+Shift+T - Перейти к JUnit тесту
Alt+O - Перейти к источнику
Ctrl+B - Перейти к объявлению переменной
Ctrl+G - Перейти к строке, задав ее номер
Ctrl+Shift+M - Добавить/Удалить заметку
Ctrl+Shift+Period/Comma - Следующая/Предыдущая заметка
Ctrl+Period/Comma - Следующая/Предыдущая использование/ошибка компиляции
Ctrl+Shift+1/2/3 - Выделить в проектах/файлах/фаворитах
Ctrl+[ - Переместить курсор к открывающейся/закрывающейся скобке от соответствующей закрывающейся/открывающейся скобки
Ctrl+K/Ctrl+Shift K - Следующее/предыдущее совпадение слова
Alt+Left/Alt+Right/Ctrl+Q - Перейти к предыдущему/следующему/последнему редактированию
Alt+Up/Down - Следующее/предыдущее встречаемость данной переменной

* Программирование на языке Java

Alt+Insert - Сгенерировать код
Ctrl+Shift+I - Исправить все импорты класса
Alt+Shift+I - Исправить выделенный импорт класса
Alt+Shift+F - Отформатировать текст согласно кодинг-стайлу
Alt+Shift+Left/Right/Up/Down - Переместить строку влево/вправо/вверх/вниз на одну табуляцию
Ctrl+Shift+Up/Down - Скопировать и вставить текущую строку выше/ниже
Ctrl/Alt+F12 - Просмотр членов класса/всей иерархии класса
Ctrl+/ - Закомментировать/Раскомментировать текущую строку
Ctrl+E - Удалить текущую строку

При написании кода очень удобно использовать сокращения
часто повторяемых участков кода. Схема использования:
сокращение+Tab

* Сокращения для Java редактора

En - Enumeration
Ex - Exception
Ob - Object
Psf - public static final
Psfb - public static final boolean
Psfi - public static final int
Psfs - public static final String
St - String
ab - abstract
bo - boolean
br - break
ca - catch (
cl - class
cn - continue
df - default:
dowhile - do {} while (condition);
eq - equals
ex - extends
fa - false
fi - final
fl - float
forc - for (Iterator it = collection.iterator(); it.hasNext();) {Object elem = (Object) it.next();}
fore - for (Object elem : iterable) {}
fori - for (int i = 0; i < arr.length; i++) {}
fy - finally
ie - interface
ifelse - if (condition){}else {}
im - implements
iof - instanceof
ir - import
le - length
newo - Object name = new Object(args);
pe - protected
pr - private
psf - private static final
psfb - private static final boolean
psfi - private static final int
psfs - private static final String
pst - printStackTrace();
psvm - public static void main(String[] args){}
pu - public
re - return
serr - System.err.println ("|");
sout - System.out.println ("|");
st - static
sw - switch (
sy - synchronized
tds - Thread.dumpStack();
th - throws
trycatch - try {} catch (Exception e) {}
tw - throw
twn - throw new
wh - while (
whileit - while (it.hasNext()) {Object elem = (Object) it.next();}

Подсветка кода для Netbeans как в Notepad++

вторник, 9 ноября 2010 г.

Дебагинг в PHP

Есить куча вариантов дебага.

Самый простой
Код - пример #1
1
print_r($foo);
Получше:
Код - пример #1
1
2
echo '<pre>';
print_r($foo);
Я использую такую функцию:
Код - пример #1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function deb($str, $name = '') {
    $name = ($name)?$name:gettype($str);
    $aCol = array('#FFF082','#BAFF81','#BAFFD7','#F0D9D7');
    $color = $aCol[RAND(0,3)];
    echo "<PRE><div style='background-color: $color'><b>$name = <b>";
    if (is_array($str)) echo '<br>';
    print_r($str);
    echo "</div></PRE><br>";
}

// Пример использования

deb($foo);

// или

deb($foo, 'foo');

среда, 18 августа 2010 г.

Парсинг HTML, DOM

Свое знакомство с php я начал именно с парсинга, в дальнейшем для облегчения я попробовал использовать Simple HTML DOM Parser. С ним работать очень удобно, но он жрет очень много памяти, и там где происходит много итераций с его участием скрипт завершает свою работу с Fatal error из за не хватки памяти.
 
Вообщем нашел я ему замену, регулярка которая парсит содержимое элемента по указному id или class-у.
Код - пример #1
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
class ParsDom {

    public $sContent = '';
    
    public function getElement($sId = '', $sElem = 'div') {
        if (!$sId || !$this->sContent) return '';
        $aOut[0] = array();
        $sReg = "
        /
        <{$sElem}[^>]+\b(?:class|id)=[\"\']?{$sId}[\"\']?[^>]*>
         (?:
           (<{$sElem}[^>]*>*?<\/{$sElem}>)|
           .
         )*?
        <\/{$sElem}>
        /xsS";

        preg_match_all($sReg, $this->sContent, $aOut);

        if (isset($aOut[0]))
            return $aOut[0];
        else    
            return '';
    }
}

// Пример
$oParsDom = new ParsDom;

// Контент от куда будем парсить
$oParsDom->sContent = $sData;

// Парсим все DIV элементы с указаным id или классом
$aDiv = $oParsDom->getElement('class_or_id_name');

// Парсим все LI элементы с указаным id или классом
$aLi = $oParsDom->getElement('menu', 'li');

суббота, 7 августа 2010 г.

Жарко

Выходные. У нас жара, побиты все рекорды, температура за 40. Леса горят, вроде уже поменьше, т.к. меньше смога на улице.

Вчера посмотрел фильм Мухина "Максимум лжи и глупости" про высадку американцев на Луне. Говорит логичные вещи, у них не было возможности туда доставить космонавтов и обратно, т.к. не было таких мощных двигателей и до сих пор нет. Также привезенные 300кг лунного грунта никому не дают на анализ, а кому давали, установили, что он с земли.

Все парюсь с PHP. В который раз, переделываю механизм процессов, теперь на ООП. Все это трудно укладывается в голове, поэтому заюзал сервис "карт ума" и чего то там изобразив пытаюсь воплотить в коде, надеюсь получится и переписывать не придется.

Жена с детьми отдыхают на волге, ездят с родителями на острова, купаются. Ну ничего, еще немного, у меня будет отпуск и я первый раз поеду с семьей на море в Анапу.

Почему блоггер не сохраняет мое форматирование! Аргх... Приходится ручками раставлять теги br

пятница, 6 августа 2010 г.

Эксперимент с Sape 0

Прошло уже наверное пол года, после того как Яндекс забанил последние из моих ГС, которые, хоть и немного но приносили прибыль.

Как то у меня к этому всему охладело. Но, читая блоги, посматривая на topsape.ru захотелось попробовать...

Эксперимент будет такой:

Использую:
1. только фри домены 3-го уровня
2. фрихостинги
3. свои навыки php, делаю "кнопку бабло" о_О
4. Zebrum Lite, Satellite-X

Получаю профит!