![](https://habrastorage.org/files/d3d/84f/d39/d3d84fd397a841c3bdac6ddde063af8d.jpg)
Не уверен, что это хорошая идея — признаваться в собственном непрофессионализме. Люди работают над своим имиджем, создают портфолио, зарабатывают авторитет и дорожат им. Я же легко признаюсь в свом полном непрофессионализме и даже авантюризме: я довольно часто рискую писать программы на неизвестных мне языках программирования. Однажды один из заказчиков спросил меня, как я пришел в разработку на java для Андроид, а я ему по глупости ответил: ну как, как? Да ведь if-ы и else везде одинаковые! Неудачная шутка. Впрочем, программирование для Андроид — это всего лишь эпизод.
Сейчас я расскажу совсем другую историю. История о том, как и почему я решился писать свою первую программу на PHP и MYSQL (SQL это ведь тоже язык? или нет?).
История совершенно практическая. У меня есть сайт, ему уже 7 лет.
Сайт когда-то давно был сделан на CMS Joomla 1.5. Туда было вложено много времени, труда и души. Время шло, нужно было делать апдейты, но это было очень трудно, так как по некоторые компоненты были несовместимы с новой Джумлой 1.6/1.7 а потом уже и 2.5. Для перехода с Joomla 1.5 в Joomla 2.5 так же нужно было менять шаблон. В общем, с горем пополам, я смог сделать апдейт, но было уже поздно. Как раз в то время Joomla 2.5 уже перестала поддерживаться в связи с выходом Joomla 3. Печальная история — все время нужно играть в догонялки.
Необходимость перейти на Joomla 3 очевидна уже давно. Но как это сделать, если есть компоненты, которые нельзя вот так просто взять и заменить? Один из важных компонентов моего сайта — система для публикации файлов для скачивания DOCman. Этот DOCman всегда было трудно апгрейдить, но последняя капля — он стал платным. Вроде и стоит не очень дорого, но надоело. Перемен — требуют наши сердца.
Нет, сперва я конечно потратил уйму времени на поиски более свежего DOCman, который все таки можно поставить на сайт. Не нашел. Зато нашел очень похожий по функциональности другой компонент PhocaDownload.
![](https://habrastorage.org/files/161/699/763/16169976305a4bdf84a5c7e59c2b2dc8.png)
Можно попробовать его использовать. Вот только как сделать миграцию?
Опять трата времени на поиск «мигратора».
![](https://habrastorage.org/files/5d4/267/6a2/5d42676a2e0c4452af2d7a84d0c69056.png)
И ведь нашел, только выглядит очень подозрительно, это java программа, которая у меня почему-то не заработала. Тогда у меня промелькнула мысль: а что если самому написать скрипт для переноса данных из базы DOCman в базы PhocaDownload?
Пожалуй, тут нужно описать рамки моих знаний связанных с веб-технологиями.
Первое. Я умею пользоваться Sypex Dumper и phpmyadmin на уровне домохозяйки. Ну то есть я могу сделать экспорт или импорт какой нибудь базы данных или таблицы. Могу смотреть базы данных и делать какие нибудь простые изменения в записях. Могу по ошибке дропнуть базу. Ну вот так — всего понемножку.
Второе. Понятно, что экперименты нельзя ставить на живом сайте. Я это и не буду делать и не собираюсь. У меня есть виртуальная машина с убунтой, где развернут apache+php+mysql. Ставил сам по обычным инструкциям из этих наших интернетов — инструкций много. Копию живого сайта я могу развернуть из архива в локальной виртуальной машине примерно минут за десять. Это важно, так как я понимаю, что если я буду писать в базы и чего-то по ошибке сломаю, то придется повторять все сначала: все сносить, и разворачивать с архива заново. Пять-десять минут на эксперимент с чистого листа — мне кажется, что это терпимо. Я даже написал простейший скрипт, который бы раскрывал архив:
#!/bin/sh
rm public_html -rf
unzip arch.zip
cp configuration.php public_html/
chown www-data:www-data public_html -R
Правда тут я поленился, скрипт только расжимает архив, а мог бы еще и базу MySql импортировать. Импорт делаю вручную — дело то не хитрое.
Третье. Я примерно представляю себе, что такое html/css/js, но, думаю, на уровне junior. Так же и с php. На php я знаю, что if-ы и else они примерно как в c/c++, с фигурными скобками, а c/c++ я думаю, что знаю (надеюсь, что знаю). Еще, про php я помню, что там есть echo «asdfasdf», которое и формирует текст html, который потом отображается в браузере. Пожалуй это и все.
Некоторое время я рассматривал таблицы баз данных докмэна и пфоки в phpmyadmin и сравнивал их. Структуры похожи, но не одинаковы. У меня даже был соблазн экспортировать таблицы в CSV и затем в экселе переставить столбцы в нужном порядке. Однако эти мысли я быстро прогнал: ведь результат ручных манипуляций трудно повторить в точности. Если я буду формировать в экселе новую таблицу и потом при импорте что-то пойдет не так, то опять все заново делать и опять можно где-то ошибиться. Если сделать скрипт, то его можно многократно попробовать на чистой базе, можно многократно отработать технологию миграции с DOCman на PhocaDownload.
Кратко, задачу можно изложить так:
- в таблице jx25_docman_categories есть список категорий документов, его нужно переместить в таблицу jx25_phocadownload_categories, но только некоторые поля имеют другие имена или есть поля, которые не имеют прямого соответствия (тогда их думаю/надеюсь можно просто пропустить).
- второй этап полностью аналогичен первому: нужно взять записи из таблицы jx25_docman и перенести их в jx25_phocadownload, опять некоторые поля называются иначе или их нет там или их нет тут.
- просмотреть все статьи и найти ссылки на скачивание DOCman и переделать их в ссылки на скачивание PhocaDownload. Этот этап вероятно самый сложный.
Вот с этими мыслями я и взялся за дело.
Как программировать на языке, которого не знаешь? Думаю ответ понятен всем: нужно гуглить или яндексить. По своему опыту скажу, что лучше гуглить и лучше на английском языке. Ответов на вопросы больше всего в stackoverflow или, скажем, на w3schools.com, и ответы там, конечно на английском.
Например, задаю вопрос: «read mysql table php»:
![](https://habrastorage.org/files/bb9/f3e/ef3/bb9f3eef3f2e4ea290525734f330fde1.png)
Первые же ссылки гугла уже сразу дают ответ на мой вопрос. Я создаю php файл conv.php в корне копии моего сайта в локальной виртуальной машине. Мне нужен файл, который я могу редактировать и который может запускать мой web сервер Apache:
cd /var/www/html/public_html/
sudo touch conv.php
sudo chown www-data:www-data conv.php
sudo chmod a+w conv.php
Теперь файл можно редактировать. Правило написания программ на неизвестном языке программирования такое: от простого к сложному маленькими шагами. Шаг первый — это вообще убедиться, что простейшая программа на php запускается и выдает то, что нужно:
<?php
echo "<!DOCTYPE html>";
echo "<html><head>";
echo "</head><body>";
echo "Hello World! Привет!";
echo "</body>";
echo "</html>";
?>
Из браузера подключаюсь к своей виртуальной машине и проверяю результат:
![](https://habrastorage.org/files/798/37a/f0e/79837af0eab64403977d8a277d56037d.png)
Океюшки.
Теперь программу можно усложнить и вписать в нее фрагмент кода для работы с базой данных, тот, который вот только что нагуглил:
<?php
echo "<!DOCTYPE html>";
echo "<html><head>";
echo "</head><body>";
echo "<p>Hello World! Привет!</p>";
$con=mysqli_connect("localhost","user","password","database");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM jx25_docman_categories");
while($row = mysqli_fetch_array($result))
{
$id = $row['id'];
$parent_id = $row['parent_id'];
$title = $row['title'];
$name = $row['name'];
echo "<p>".$id."*".$parent_id."*".$title."*".$name."</p>";
}
mysqli_close($con);
echo "</body>";
echo "</html>";
?>
Понятно, что код из статей гугла приходится копировать не слово в слово, но слегка модифицировав под свои нужды. В процессе адаптации кода вписываю в функцию mysqli_connect свои имя пользователя и пароль к базе и название своей базы. Попутно приходится гуглить всякие странные вопросы, например, «how to echo integer var on php», или «join strings php». Сохранил текст программы php — теперь попробую результат в браузере:
![](https://habrastorage.org/files/921/abd/0ba/921abd0ba662419cbe9fab3a80339432.png)
Оопс… Что-то пошло не так. Проблема с кодировкой, только кодировкой чего? У меня вроде бы в самой первой программе слово «Привет» верно отображалось, то есть видимо проблема не в странице, а в чтении из базы? Опять гуглим. Похоже где-то нужно вставить строку:
mysqli_query($con,"SET NAMES 'utf8'");
Вставил после открытия соединения с базой — и заработало! Я увидел список категорий в разделе загрузок!
Следующий сложный для меня этап: как произвести запись в строку таблицы mysql? Опять обращаюсь к гуглу. А что делать? Выхода нет — нужно смотреть как написать запрос к базе. Этот этап несколько сложнее, так как теперь я уже пытаюсь писать в базу данных. Одна неудачная команда и я испорчу базу. Придется ее восстановить из архива и делать новую попытку. В принципе, я обошелся всего двумя или тремя попытками. После этого у меня уже был вполне рабочий скрипт, который выполняет пункты 1) и 2) моего скромного ТЗ: переносит записи из таблицы jx25_docman_category в jx25_phocadownload_category и таблицы jx25_docman в jx25_phocadownload.
Привожу здесь полный текст этого скрипта:
<?php
echo "<!DOCTYPE html>";
echo "<html><head>";
echo "<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />";
echo "</head><body>";
echo "Hello World! Привет!";
$con=mysqli_connect("localhost","user","password","database");
mysqli_query($con,"SET NAMES 'utf8'");
sql_mode='STRUCT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
echo "Clear table jx25_phocadownload_categories";
mysqli_query($con,"DELETE FROM jx25_phocadownload_categories");
echo "Import table jx25_phocadownload_categories from jx25_docman_categories";
$result = mysqli_query($con,"SELECT * FROM jx25_docman_categories");
while($row = mysqli_fetch_array($result))
{
$id = $row['id'];
$parent_id = $row['parent_id'];
$title = $row['title'];
$name = $row['name'];
$alias = $row['alias'];
$descripton = $row['description'];
$published = $row['published'];
$ordering = $row['ordering'];
$access = $row['access'];
echo "<p>".$id."*".$parent_id."*".$title."*".$name."*".$alias."*".$description."*".$published."*".$ordering."*".$access."</p>";
$sql = "INSERT INTO jx25_phocadownload_categories ( ".
" id, parent_id, title, name, alias, description, published, ordering, access ) " .
"VALUES ( '".$id."','".$parent_id."','".$title."','".$name."','".$alias."','".$description."','".$published."','".$ordering."','".$access."')";
//echo "<p>".$sql."</p>";
mysqli_query($con,$sql);
}
echo "<p>***********************************</p>";
echo "Clear table jx25_phocadownload";
mysqli_query($con,"DELETE FROM jx25_phocadownload");
echo "Import table jx25_phocadownload from jx25_docman";
$result = mysqli_query($con,"SELECT * FROM jx25_docman");
while($row = mysqli_fetch_array($result))
{
$id = $row['id'];
$alias = "";
$approved = 1;
$catid = $row['catid'];
$dmname = $row['dmname'];
$dmdescription = $row['dmdescription'];
$dmdate_published = $row['dmdate_published'];
$dmfilename = $row['dmfilename'];
$ext = pathinfo($dmfilename,PATHINFO_EXTENSION);
$icon = "";
if( strlen($ext)==3 )
$icon = $ext.".png";
$published = $row['published'];
$dmcounter = $row['dmcounter'];
$access = $row['access'];
echo "<p>".$id."*".$dmfilename."</p>";
$sql = "INSERT INTO jx25_phocadownload ( ".
" id, catid, title, alias, filename, image_filename, description, date, publish_up, published, approved, hits, access ) " .
"VALUES ( '".$id."','".$catid."','".$dmname."','".$alias."','".$dmfilename."','".$icon."','" .$dmdescription."','".$dmdate_published."','".$dmdate_published."','".$published."','".$approved."','".$dmcounter."','".$access."')";
//echo "<p>".$sql."</p>";
mysqli_query($con,$sql);
}
mysqli_close($con);
echo "</body>";
echo "</html>";
?>
Конечно, кроме манипуляций с базой нужно сделать еще кое что в файловой системе. Например, по умолчанию DOCman хранит файлы в папке ./dmdocuments, а phoca хранит их в ./phocadownload. Значит нужно еще переименовать папку, ну еще позаботиться об иконках файлов. Phoca ищет иконки в ./images/phocadownload и следовательно туда нужно положить иконки для разных типов файлов zip.png, pdf.png, txt.png и так далее…
Теперь нужно выполнить следующую задачу: разные статьи сайта имеют ссылки для скачивания с использованием компонента DOCman. Если я удалю DOCman то и все ссылки на скачивание по всем страницам сайта (которых у меня около трехсот) перестанут работать. Ссылки выглядят на сайте вот так:
![](https://habrastorage.org/files/266/835/b15/266835b159714e078f90c6a0793e76a5.png)
А в тексте статьи это вот такой html код:
<a href="index.php?option=com_docman&task=doc_download&gid=181&Itemid=25" class="doclink"><img src="/components/com_docman/themes/default/images/icons/16x16/zip.png" alt="icon" border="0" /> Управление светодиодной лентой (<span class="small">79.68 Кбайт</span>)</a>
Код обычно вставляется в статью с помощью кнопки DOCLink.
Вот нужно просмотреть по базам данных, найти вот такой код и заменить его на аналогичный код пфоки. Для меня это кажется не очень простая задача.
Тут несколько сложностей. Во-первых, в статье может быть много ссылок на скачивание. Во-вторых ссылки на скачивание могут быть не только в теле статьи, но и в предварительном описании статьи, это то, что перед катом стоит, и еще ссылки могут быть даже в описаниях категорий. Кажется довольно опасным затрагивать столько статей, но выхода нет, нужно действовать.
Пожалуй не буду утомлять читателей всем списков моих запросов к гуглу. Такой метод программирования, когда чуть ли ни каждую строку кода приходится гуглить, ни в коей мере нельзя считать нормальным. Какое-то monkey-style программирование: мало понимания, но много попыток: попробовал => посмотрел работает ли.
Скажу, что в конце концов я смог сделать и второй скрипт, который модифицирует статьи сайта и заменяет док-линки на пфока-линки. Пожалуй единственная очень большая засада у меня получилась с вписыванием нового исправленного текста назад в запись таблицы. Честно скажу, тут потратил где-то пол дня на какую-то ерунду.
Все гугло-ответы, которые я находил показывали, что запрос нужно делать примерно вот так:
$sql="UPDATE Customers SET ContactName='Alfred Schmidt', City='Frankfurt' WHERE CustomerID=1;"
Этот пример взят отсюда: www.w3schools.com/sql/sql_update.asp
Однако, в моем случае такой запрос не работает! Я не могу таким способом исправлять поле, где хранится статья. Поле, где хранится текст статьи в таблице joomla называется fulltext, а это возможно/наверное/похоже на то — какое-то ключевое слово в mysql! Вот когда заключил имя поля в кавычки `fulltext` — все и заработало. И кто бы мог об этом подумать? И главное, что я не видел ни одного ссылки в гугле, которая бы про это рассказала. Понял я свою ошибку совершенно случайно, когда увидел, как запросы отображает phpmyadmin — уж там все имена полей в кавычках.
Вот мой скрипт, который просматривает все статьи и модифицирует ссылки на скачивание:
<?php
echo "<!DOCTYPE html>";
echo "<html><head>";
echo "<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />";
echo "</head><body>";
echo "Hello World! Привет!";
$con=mysqli_connect("localhost","user","password","database");
mysqli_query($con,"SET NAMES 'utf8'");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
function search_replace($text)
{
$pos = strpos( $text, "task=doc_download");
if($pos===false)
{
return "";
}
else
{
$begin = $pos;
while($begin>=0)
{
$ss = substr($text,$begin,3);
if($ss=="<a ") break;
$begin--;
}
$end = $pos;
while(1)
{
$ss = substr($text,$end,4);
if($ss=="</a>") { $end=$end+4; break; }
$end++;
}
$ss = substr($text,$begin,$end-$begin);
echo "<p>".$ss."</p>";
$gid_pos = strpos($ss,"gid=");
$gid = substr($ss,$gid_pos+4);
$gid_int = intval($gid);
$phoca_str = "{phocadownload view=file|id=".$gid_int."}";
echo "<p>".$phoca_str."</p>";
$a = substr($text,0,$begin);
$b = substr($text,$end);
return $a.$phoca_str.$b;
}
}
echo "Read table jx25_content";
$result = mysqli_query($con,"SELECT * FROM jx25_content");
$num=0;
while($row = mysqli_fetch_array($result))
{
$id = $row['id'];
$title = $row['title'];
$fulltext = $row['fulltext'];
$introtext = $row['introtext'];
$num=$num+1;
echo "<p><hr>".$num." ".$id." ".$title."</p>";
$text = $fulltext;
while( strlen($text)>0 )
{
$t = search_replace($text);
if( strlen($t)==0 ) break;
$text=$t;
}
if($text!=$fulltext)
{
$str = mysqli_real_escape_string($con,$text);
echo "*** strlen ".intval(strlen($str));
$sid = intval($id);
$sql = "UPDATE jx25_content SET `fulltext`='".$str."' WHERE id=".$sid;
$r = mysqli_query($con,$sql);
if($r) echo "***";
else echo "---";
}
}
echo "<p>***********************************</p>";
?>
Теперь PhocaDownload ссылки на сайте у меня выглядят вот так:
![](https://habrastorage.org/files/992/9cc/ee0/9929ccee06b743f692a7bac8d6610304.png)
Правда, пришлось еще немного допилить плагин PhocaDownload, чтобы показывало иконку файла и чтобы размер файлы был виден. Но это уже совсем другая история.
Таким образом:
- потрачено четыре вечера;
- получен бесценный опыт программирования на незнакомом языке;
- есть результат: смог самостоятельно мигрировать с DOCman на PhocaDownload!
Поделиться с друзьями
wOvAN
Мне кажется, это обычное дело писать программы на языке и в процессе его изучать. Первый результат будет долгим и комом, но второй уже будет лучше и тд.