Задача.
Есть основной файл и файлы шаблонов, причем все имеют расширение csv. Как можно быстро обработать файл на основе шаблонов?
В php5 есть специализированные функции str_getcsv(), fgetcsv() и fputcsv(), которые адаптированы для работы с такого рода файлами. Но можно обойтись и без этих функций. Во время такого рода манипуляций часто сталкивался с ошибками, которые необходимо учитывать - извлекаемые значения из массивов порой содержали неожиданные знаки табуляции, или строка состояла из символов в перемешку с NULL-символами... Поэтому обращение к шаблонам, разобранных на соответствующие массивы, сопровождались казусами, например - использование неопределенных массивов. Отсюда вывод - нужно использовать trim() как фильтр от таких "неожиданностей" и isset() - как подобие отлова исключительной ситуации с попыткой извлечения значения из массива по неопределенному индексу. В остальном все сработало неплохо :)
Пример (download).
<?php ## manipulation with csv-files (base of device tags)
/***********open source and target csv-files*****************************************
// 13010000.csv
$f = fopen("c:\\php\\scripts\\in\\devices.csv", "rb");
// pattern.csv
$pattern = fopen("c:\\php\\scripts\\templates\\pattern.csv", "rb");
// BTDevices_Adresses.csv
$btdevices = fopen("c:\\php\\scripts\\templates\\BTDevices_Adresses.csv", "rb");
// output.csv
$output = fopen("c:\\php\\scripts\\out\\output.csv", "wb");
//***********transfer data from file to string and clean all NULL************************
function transfer($file) {
// read file to $hash from $buffer. Take max length of Double Integer
while(($buffer = fgets($file, 64536)) !== FALSE) {
$hash[] = $buffer;
}
// sort $hash and clean from '\0'
for($k = 0; $k < count($hash); $k++) {
// cleaned massive
$strbox[$k] = " ";
for($i = 0, $j = 0; $j < strlen($hash[$k]); $j++) {
if($hash[$k][$j] == "\0") {
continue;
}
else {
$strbox[$k][$i] = $hash[$k][$j];
$i++;
}
}
}
// Clean buffer
$buffer = NULL;
return $strbox;
}
//**********transfer all files****************************************************
// device.csv
$box_f = transfer($f);
// pattern.csv
$box_patt = transfer($pattern);
// BTDevices_Adresses.csv
$box_btd = transfer($btdevices);
// create accessories arraies
//********$template_array ********Array[:TEMPLATES][$i] = Signal Alias ***********
// parse string into an array
for($i = 0; $i < count($box_patt); $i++) {
$temp[] = explode(",", $box_patt[$i]);
}
// create Array[:TEMPLATES][$i] = Signal Alias
$template_array = Array();
for($col = 0; $col < count($temp[0]); $col++) {
$template_name = NULL;
$template_name = $temp[0][$col];
for($str = 1; $str < count($temp); $str++) {
$tem = NULL;
$tem = $temp[$str][$col];
$template_array[$template_name][] = $tem;
}
}
//************************************************ $btd *********************** Array[:Tagname] = ShortDesc *****************
// create Array[:Tagname] = ShortDesc
// ...немного схалтурил, так как нужно искать по индексам или иначе.
// Сие допустимо, так как структура файла - исходника нам известна
// parse string into an array. $i = 0 - header string have to miss
for($i = 1; $i < count($box_btd); $i++) {
list(, $shortdesc,,,,,,, $tagname) = explode(",", $box_btd[$i]);
$btd[$tagname] = $shortdesc;
$shortdesc = NULL;
$tagname = NULL;
}
//**********$engunits ****************Array[:Tagname] = EngUnits *****************
// create Array[:Tagname] = EngUnits
// ...немного схалтурил, так как нужно искать по индексам или иначе.
// Сие допустимо, так как структура файла - исходника нам известна
// parse string into an array. $i = 0 - header string have to miss
for($i = 1; $i < count($box_btd); $i++) {
list(,,,, $engunit,,,, $tagname) = explode(",", $box_btd[$i]);
$engunits[$tagname] = $engunit;
$engunit = NULL;
$tagname = NULL;
}
// create main array ($arr is base on input file)
//**********************$arr ****************************************************
// parse string into an array
for($i = 0; $i < count($box_f); $i++) {
$arr[] = explode(",", $box_f[$i]);
}
print_r($arr);
//***********************processing $arr and rewrite needly values*********************
// for change values of $arr in loop we get array by ref
$count_row = 0;
foreach($arr as &$row) {
foreach($row as $elem => $value) {
// ':TEMPLATE'
if((strpos($value, ':TEMPLATE')) !== false) {
// reset array
$signal_aliases = Array();
// find template name of device
list(,$templ) = explode("=", $value);
$trimmed_templ = trim($templ);
// defined signal aliases of find template
// $template_array is array that content link :TEMPLATE -> Array(Template signal aliases)
if(isset($template_array[$trimmed_templ])) {
$signal_aliases = $template_array[$trimmed_templ];
}
}
// ':Tagname'
if((strpos($value, ':Tagname')) !== false) {
// initialization
$index = 1;
$stop = true;
// reset array $tags
$tags = Array();
//
while($stop) {
$tag = trim($arr[$count_row + $index][$elem]);
if($tag !== "") {
$tags[] = $tag;
$index++;
}
if($tag == "") {
$stop = false;
}
}
}
// 'ShortDesc'
if((strpos($value, 'ShortDesc')) !== false) {
// initialization
$position = $count_row + 1;
$indexx = 0;
while($indexx < count($tags)) {
$tag_item = trim($tags[$indexx]);
if(isset($btd[$tag_item])) {
$short_desc = trim($btd[$tag_item]);
$arr[$position + $indexx][$elem] = $short_desc;
}
$indexx++;
}
}
// 'Signal_alias.Desc'
if((strpos($value, '.Desc')) !== false) {
// find index field 'ShortDesc'
list($item,) = explode(".", $value);
$item = trim($item);
//
if(in_array($item, $signal_aliases)) {
$pos = $count_row + 1;
$indexxx = 0;
while($indexxx < count($tags)) {
$new_tag_item = trim($tags[$indexxx]);
if(isset($btd[$new_tag_item])) {
$new_item = ". ".str_replace("_", " ", $item).".";
$item_for_push = $btd[$new_tag_item].$new_item;
$arr[$pos + $indexxx][$elem] = $item_for_push;
}
$indexxx++;
}
}
}
}
$count_row++;
}
//**************transfer from massive to string and write to output csv-file*****************
// for catch mini bug 'ая;'. It`s may be control symbols
$str = ltrim(implode(",", $arr[0]), "ая;");
fputs($output, $str);
// build output file
for($i = 1; $i < sizeof($arr); $i++) {
$str = implode(",", $arr[$i]);
fputs($output, $str);
}
//***********************close handles of source and target csv-files*********************
fclose($f);
fclose($pattern);
fclose($btdevices);
fclose($output);
?>
.htaccess. Правило перенаправления ссылок
Задача. Ссылки в адресной строке не должны быть вида http://mysite.ru/index.php?param=target, а должны выглядеть так http://mysite.ru/target.
Для реализации можно воспользоваться следующим способом. Необходимо создать .htaccess, где нужно прописать следующее правило, правило перенаправления. Соответственно, для ограничения поля влияния .htaccess, его нужно разместить в той директории, где нужно распространить сие правило (поддиректории также будут подподать в это поле влияния).
Я сделал так:
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ http://mysite.ru/index.php?param=$1
Для реализации можно воспользоваться следующим способом. Необходимо создать .htaccess, где нужно прописать следующее правило, правило перенаправления. Соответственно, для ограничения поля влияния .htaccess, его нужно разместить в той директории, где нужно распространить сие правило (поддиректории также будут подподать в это поле влияния).
Я сделал так:
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ http://mysite.ru/index.php?param=$1
php5. Debuging...
Иногда, для отлова своей же ошибки (!), приходится тратить много времени, казалось бы все хорошо, но почему-то все идет не так как мы того хотели бы. Что же мешает быстродействию отлова (debug)? Лень. Например, для того, чтобы понять, что же происходит, в определенных кусках кода проставляем команду вывода содержимого какой-нибудь переменной, бывает, нужно проставить таких меток более десятка, вот здесь и нужно проявить усидчивость, нужно их по-человечески прописать, чтобы при дальнейшем анализе было понятно, что идет не так!
MySQL Command Line Client. Not launch on WinOS
Если не запускается MySQL Command Line Client, нужно немного подкрутить в my.ini в блоке [mysql]: добавить строчечку вида character-sets-dir="C:/mysql5/share/charsets/". По-сути, здесь прописан путь до кодировок (используются правые "слэши")
PHP5. Обращение к переменным родительского класса. Два способа
Как можно получить доступ дочернего класса к переменным родительского класса?
Способ первый: необходимо несколько условий. 1 - переменные в родительском классе должны быть объявлены как protected, 2 - при объявлении дочернего конструктора, необходимо также объявить родительский конструктор, 3 - соответственно, обращаемся к переменной родительского класса как ко внутренней переменной $this->variable;
Способ второй: 1 - переменные в родительском классе могут быть закрытыми (private), 2 - необходимо создать методы, позволяющие получить доступ к переменным из дочернего класса, 3 - при объявлении дочернего конструктора, необходимо также объявить родительский конструктор, 4 - соответственно, обращаемся к переменной родительского класса через соответствующие методы parrent::getVariable();
Ниже приведен пример использования двух спобов обращения к переменным родительского класса.
<?php ##Обращение к переменным родительского класса. Два способа
// Родительский класс
class Item {
// Для первого способа необходим уровень конфиденциальности - protected
protected $name;
private $code;
// Консруктор родительского класса
function __construct( $name = "Item", $code = 0 ) {
$this->name = $name;
$this->code = $code;
}
// Для второго способа создаем метод
function getName() {
return $this->name;
}
// Также создаем метод для второго метода
function getCode() {
return $this->code;
}
}
// Дочерний класс
class PriceItem extends Item {
private $temp;
// Конструктор родительского класса
function __construct( $name, $code, $temp = "temp" ) {
// Обязательное объявление родительского конструктора
parent::__construct( $name, $code );
// Обращаемся к переменным родительского класса вторым способом - parent:getName() и getCode()
$this->temp = "temp = ".$temp." name = ".parent::getName()." code = ".parent::getCode();
}
// Для вывода результата обращения к переменным родительского класса первым способом
function getParentName() {
return $this->name;
}
// Для вывода результата обращения к переменным родительского класса вторым способом
function getIt() {
return $this->temp;
}
}
// Инстанцируем объект
$Item = new PriceItem(Name, 1616);
// Выводим результаты
print $Item->getIt();
print "<br />";
print $Item->getParentName();
?>
Способ первый: необходимо несколько условий. 1 - переменные в родительском классе должны быть объявлены как protected, 2 - при объявлении дочернего конструктора, необходимо также объявить родительский конструктор, 3 - соответственно, обращаемся к переменной родительского класса как ко внутренней переменной $this->variable;
Способ второй: 1 - переменные в родительском классе могут быть закрытыми (private), 2 - необходимо создать методы, позволяющие получить доступ к переменным из дочернего класса, 3 - при объявлении дочернего конструктора, необходимо также объявить родительский конструктор, 4 - соответственно, обращаемся к переменной родительского класса через соответствующие методы parrent::getVariable();
Ниже приведен пример использования двух спобов обращения к переменным родительского класса.
<?php ##Обращение к переменным родительского класса. Два способа
// Родительский класс
class Item {
// Для первого способа необходим уровень конфиденциальности - protected
protected $name;
private $code;
// Консруктор родительского класса
function __construct( $name = "Item", $code = 0 ) {
$this->name = $name;
$this->code = $code;
}
// Для второго способа создаем метод
function getName() {
return $this->name;
}
// Также создаем метод для второго метода
function getCode() {
return $this->code;
}
}
// Дочерний класс
class PriceItem extends Item {
private $temp;
// Конструктор родительского класса
function __construct( $name, $code, $temp = "temp" ) {
// Обязательное объявление родительского конструктора
parent::__construct( $name, $code );
// Обращаемся к переменным родительского класса вторым способом - parent:getName() и getCode()
$this->temp = "temp = ".$temp." name = ".parent::getName()." code = ".parent::getCode();
}
// Для вывода результата обращения к переменным родительского класса первым способом
function getParentName() {
return $this->name;
}
// Для вывода результата обращения к переменным родительского класса вторым способом
function getIt() {
return $this->temp;
}
}
// Инстанцируем объект
$Item = new PriceItem(Name, 1616);
// Выводим результаты
print $Item->getIt();
print "<br />";
print $Item->getParentName();
?>
Subscribe to:
Posts
(
Atom
)
