<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
        <channel>
        <title>Русский клуб Joomla/Программирование</title>
        <link>http://joomclub.net/ru/blog/programming/</link>
        <description><![CDATA[Блог посвящен программированию и разработке под cms Joomla!..]]></description>
        <language>ru</language>
        <managingEditor>vadim@joomline.ru</managingEditor>
        <webMaster>tena2000@mail.ru</webMaster>
        <generator>Alto CMS v.1.1.13</generator>
                    <item>
                <title>Подключение PHPStorm к удаленной базе данных</title>
                <guid isPermaLink="true">http://joomclub.net/ru/t/196/</guid>
                <link>http://joomclub.net/ru/blog/programming/196.html</link>
                <author>a.sedelnikov@gmail.com</author>
                <description><![CDATA[<p>Уже долгое время мне мозолила глаз вкладка «Database» в правом верхнем углу PHPStorm. Решил с ней разобраться в конце концов и подключить базу данных разрабатываемого сайта к проекту. Оказалось все не так сложно и, в результате, очень удобно.</p><a name="cut" rel="nofollow"></a> Настройки базы данных<p>Первым делом надо разрешить удаленный доступ к БД в панели управления хостингом, я подключал timeweb, там это делается во вкладке «Базы данных MySQL». Справа от подключаемой базы есть кнопка &quot;<span>Добавить доступ</span>&quot;, нажимаем ее и вводим IP с которого хотим подключаться к БД. Если IP у вас динамический, то его придется менять каждый раз. После введения IP он появится чуть выше кнопки. Для надежности я изменил к нему пароль, повторив пароль доступа с localhost, возможно этого делать не надо, а может и надо, по другому я не проверял.</p>Настройки SSH<p>Служба поддержки дала мне такие инструкции:</p><p>Далее, для подключения используйте следующие параметры:</p><p>hostname: nubes.timeweb.ru (это мой хост, у вас наверняка другой)<br/>
порт: 3306, стандартный.</p><p> Так у меня не заработало, пришлось подключать через SSH. Для этого SSH доступ должен быть включен у провайдера, а включается он по запросу.</p>Настройка PHPStorm<p>Для создания подключения к базе данных в PHPStorm откройте окно работы с БД, в меню View — Tool Windows — Database. В открывшейся вкладке кликните плюсик для создания нового подключения, в выпадающем меню выберите Datasource — MySQL. В открывшемся окне введите настройки:</p><ul><li>Host: localhost</li><li>Port: 3306</li><li>Database: имя_базы_данных</li><li>User: пользователь_базы_данных</li><li>Password: пароль_базы_данных</li></ul><p>Далее нажмите кнопку «Configure SSH» и ведите в открывшемся окне следующие данные:</p><ul><li>Use SSH Tunnel — поставить галку</li><li>Proxy Host: nubes.timeweb.ru (хост, на котором располагаются мои сайты)</li><li>Proxy User: Пользователь, у меня он совпадает с пользователем панели управления</li><li>Auth type: Password</li><li>Proxy Password: пароль пользователя.</li></ul><p>После ввода всех данных можно нажать кнопку «Test Connection» и, если все ввели правильно, то коннект состоится. Если возникли проблемы с подключением, то, возможно, у вас, как и у меня, небыли установлены драйверы MySQL, о чем у меня было написано в нижней части окна, чуть выше кнопок, и дана ссылка, при клике на которой драйвера загрузились и установились.</p><p>Работа с базой данных в PHPStorm оказалась удобной и полноценной, можно посмотреть структуру таблиц, их содержимое, а так-же делать любые запросы, phpMyAdmin можно не открывать.</p>]]></description>
                <pubDate>Sun, 16 Mar 2014 09:33:31 +0400</pubDate>
                            </item>
                    <item>
                <title>Правильный пакет установки Joomla.</title>
                <guid isPermaLink="true">http://joomclub.net/ru/t/171/</guid>
                <link>http://joomclub.net/ru/blog/programming/171.html</link>
                <author>vadim@joomline.ru</author>
                <description><![CDATA[<p>Сегодня обратились в поддержку, по поводу не корректного удаления пакета расширений Joomla. Я задался вопросом, а как собственно правильно должен выглядеть пакет установки расширения Joomla. Полез в документацию и хочу поделиться, на мой взгляд, ценной информацией. <a name="cut" rel="nofollow"></a> </p><p>Для чего нужен пакет установки Joomla?</p><p>Сейчас расширения Joomla обычно состоят из набора расширений: модули, плагины, компоненты, библиотеки. Устанавливать весь этот набор по отдельности не удобно, гораздо проще загрузить один архив в инсталлятор Joomla, а он уже все установит, так как надо. Собственно для этого и были придуманы пакеты. Обычно они обозначаются как pkg_ .</p><p>Теперь маленькая ремарка. Раньше я воспринимал, установочный пакет, только с точки зрения удобной установки расширений Joomla, с сегодняшнего дня я его еще и воспринимаю, как инструмент удобного удаления расширений Joomla.</p><p>Дальше будет немного <a href="http://docs.joomla.org/Package" rel="nofollow">официальной документации</a> с моими комментариями.</p><p>Представим, что у нас есть директория с расширениями:</p><pre>-- pkg_helloworld.xml
 -- packages &lt;dir&gt;
     |-- com_helloworld.zip
     |-- mod_helloworld.zip
     |-- lib_helloworld.zip
     |-- plg_sys_helloworld.zip
     |-- tpl_helloworld.zip</pre><p>Над ней мы кладем фаил pkg_helloworld.xml -helloworld — это имя пакета, в котором и содержится вся информация по установке расширения.</p><p>  &lt;?xml version=«1.0» encoding=«UTF-8» ?&gt;<br/>
 &lt;extension type=«package» version=«1.6»&gt;<br/>
 &lt;name&gt;Hello World Package&lt;/name&gt;<br/>
 &lt;author&gt;Hello World Package Team&lt;/author&gt;<br/>
 &lt;creationDate&gt;May 2012&lt;/creationDate&gt;<br/>
 &lt;packagename&gt;helloworld&lt;/packagename&gt;<br/>
 &lt;version&gt;1.0.0&lt;/version&gt;<br/>
 &lt;url&gt;http://www.yoururl.com/&lt;/url&gt;<br/>
 &lt;packager&gt;Hello World Package Team&lt;/packager&gt;<br/>
 &lt;packagerurl&gt;http://www.yoururl.com/&lt;/packagerurl&gt;<br/>
 &lt;description&gt;Example package to combine multiple extensions&lt;/description&gt;<br/>
 &lt;update&gt;http://www.updateurl.com/update&lt;/update&gt;<br/>
 &lt;files folder=«packages»&gt;<br/>
   &lt;file type=«component» id=«helloworld» &gt;com_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«module» id=«helloworld» client=«site»&gt;mod_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«library» id=«helloworld»&gt;lib_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«plugin» id=«helloworld» group=«system»&gt;plg_sys_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«template» id=«helloworld» client=«site»&gt;tpl_helloworld.zip&lt;/file&gt;<br/>
 &lt;/files&gt;<br/>
 &lt;/extension&gt;</p><p>Вот так выглядит фаил pkg_helloworld.xml</p><p>Что в этом файле важно?</p><p>&lt;extension type=«package» version=«1.6»&gt; — это тип расширения пакет.</p><p>&lt;packagename&gt;helloworld&lt;/packagename&gt; — собственно само название пакета оно должно совпадать с названием файла pkg_helloworld.xml, то есть правильное название helloworld.</p><p>Теперь перейдем к самому телу пакета установки:</p><p> &lt;files folder=«packages»&gt;<br/>
   &lt;file type=«component» id=«helloworld» &gt;com_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«module» id=«helloworld» client=«site»&gt;mod_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«library» id=«helloworld»&gt;lib_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«plugin» id=«helloworld» group=«system»&gt;plg_sys_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«template» id=«helloworld» client=«site»&gt;tpl_helloworld.zip&lt;/file&gt;<br/>
 &lt;/files&gt;</p><p>На что тут стоит обратить внимание:</p><p>&lt;files folder=«packages»&gt; — если папка с расширениями называется «packages», если она называется по другом, то следовательно название надо изменить, если же ее нет, xml установки лежит в одном уровне с расширениями для установке то вся конструкция будет выглядеть вот так:</p><p> &lt;files&gt;<br/>
   &lt;file type=«component» id=«helloworld» &gt;com_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«module» id=«helloworld» client=«site»&gt;mod_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«library» id=«helloworld»&gt;lib_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«plugin» id=«helloworld» group=«system»&gt;plg_sys_helloworld.zip&lt;/file&gt;<br/>
   &lt;file type=«template» id=«helloworld» client=«site»&gt;tpl_helloworld.zip&lt;/file&gt;<br/>
 &lt;/files&gt;</p><p>Теперь об самих расширениях:</p><p>&lt;file type=«component» id=«helloworld» &gt;com_helloworld.zip&lt;/file&gt;</p><p>Обязательно надо указать тип расширения «type» — в данном примере этот тип это «component».</p><p>Так же следует указать id расширения, его вы можете найти в xml самого расширения, которое устанавливаете.</p><p>Специфические параметры для плагинов:</p><p>Для плагинов требуется указать группу расширения group=«system».</p><p>После того как вы все сделали правильно, вы можете как установить все расширения одной операцией, так и удалить все установленные расширения, удалив просто пакет установки расширения.</p>]]></description>
                <pubDate>Thu, 09 Jan 2014 22:21:52 +0400</pubDate>
                            </item>
                    <item>
                <title>Отправка формы с файлом без перезагрузки страницы (ajax jQuery).</title>
                <guid isPermaLink="true">http://joomclub.net/ru/t/103/</guid>
                <link>http://joomclub.net/ru/blog/programming/103.html</link>
                <author>a.sedelnikov@gmail.com</author>
                <description><![CDATA[<p>На одном из проектов мне потребовалось сделать отправку формы, содержащей файл,  посредством ajax. Напрямую эта задача не решается, по этому пришлось делать двойную загрузку: сначала происходит загрузка файла, результат загрузки сообщается скрипту и скрипт движется дальше, отправляя саму форму.</p><p>Код формы может быть любой, например такой:</p>&lt;div <a name="cut" rel="nofollow"></a> &gt;<pre class="prettyprint"><code>&lt;form action=&quot;#&quot; class=&quot;vacancy_form&quot;&gt; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&lt;input type=&quot;text&quot; name=&quot;l_name&quot; class=&quot;a-name&quot; data-validate=&quot;validate(required)&quot;&gt; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&lt;input type=&quot;text&quot; name=&quot;f_name&quot; class=&quot;b-name&quot; data-validate=&quot;validate(required)&quot;&gt; <br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;input type=&quot;file&quot; name=&quot;resume&quot; data-validate=&quot;validate(required)&quot;&gt; <br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;button class=&quot;btn yel_btn&quot;&gt;Откликнуться&lt;/button&gt; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type=&quot;hidden&quot; name=&quot;filename&quot; value=&quot;&quot;/&gt; <br />&lt;/form&gt; </code></pre><p>Скрипт:</p><p><pre class="prettyprint"><code>var iframe = $('&lt;iframe id=&quot;upload_iframe&quot; name=&quot;upload_iframe&quot; style=&quot;width:0;height:0;border:0;&quot;&gt;&lt;/iframe&gt;'); <br />&nbsp; &nbsp; &nbsp; &nbsp; var hidForm = $('&lt;form style=&quot;display:none;&quot; target=&quot;upload_iframe&quot; enctype=&quot;multipart/form-data&quot; action=&quot;/ajax/?function=upload_file&quot; method=&quot;post&quot; name=&quot;upload-form&quot;/&gt;'); <br />&nbsp; &nbsp; &nbsp; &nbsp; $('body').append(iframe).append(hidForm); <br />&nbsp; &nbsp; &nbsp; &nbsp; iframe.load(function(){ <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var data = $(this).contents().text(); <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (data === undefined || data == '') return; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iframe.remove(); <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hidForm.remove(); <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = JSON.parse(data); <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (data.error == '1') <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; alert(data.content); <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; form.find('input[name=filename]').val(data.file); <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $.ajax({ <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url: '/ajax/?function=vacancy', <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type: &quot;POST&quot;, <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dataType:&quot;json&quot;, <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data: form.serialize(), <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; success: function(data){ <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ... <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); <br />&nbsp; &nbsp; &nbsp; &nbsp; }); <br />&nbsp; &nbsp; &nbsp; &nbsp; var realFile = form.find('input[name=resume]'), <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; realFileVal = realFile.val(), <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; realFile = form.find('input[name=resume]'), <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newFile = realFile.clone(); <br />&nbsp; &nbsp; &nbsp; &nbsp; realFile.replaceWith(newFile); <br />&nbsp; &nbsp; &nbsp; &nbsp; hidForm.append(realFile).val(realFileVal); <br />&nbsp; &nbsp; &nbsp; &nbsp; hidForm.submit(); </code></pre><br>
</p><p>Скрипт был почерпнут на просторвх интернета и переделан под свои нужды. Скрипт создает ифрейм и дополнительную форму чтобы не маяться с передачей атрибутов в основную форму. Вспомогательная форма берет из основной инпут файла с его значением, отправляет на сервер строкой hidForm.submit();. После загрузки файла вступает событие  iframe.load, в которое сервер передает информацию о загрузке файла и путь до загруженного файла на сервере, Далее полученный путь прописывается в input[name=filename] и происходит передача основной формы через  $.ajax. На выходе получаем загруженный файл и переданную форму.</p>]]></description>
                <pubDate>Thu, 30 May 2013 13:19:46 +0400</pubDate>
                            </item>
                    <item>
                <title>Ajax изменение сортировки контента в универсальном модуле Flexicontent</title>
                <guid isPermaLink="true">http://joomclub.net/ru/t/91/</guid>
                <link>http://joomclub.net/ru/blog/programming/91.html</link>
                <author>a.sedelnikov@gmail.com</author>
                <description><![CDATA[<p> Способ подходит для любого модуля и для любого компонента.</p><p>Кто видел универсальный модуль Флекси изнутри, тот поймет, почему я не полез в него, а сделал в обход.</p><p>Была задача, сделать в модуле табы при нажатии на которые происходила бы новая выборка контента с другими параметрами сортировки или отбора.</p> <a name="cut" rel="nofollow"></a> <p>Итак, по порядку.</p><p>1. Создаем табы по которым будет осуществляться переход, ссылку в табе нужно привести к такому виду: <br>
</p><p><pre class="prettyprint"><code>&lt;a href=&quot;#&quot; data-order=&quot;popular&quot; data-module=&quot;103&quot; class=&quot;tabs-nav-link&quot;&gt;Топ&lt;/a&gt;</code></pre></p><p>где data-order — параметр сортировки в этом табе, data-module — ид модуля (могут быть копии одного модуля, по этому для точного определения нужен именно ид). Получить ид модуля можно так <pre class="prettyprint"><code>&lt;?php echo $module-&gt;id; ?&gt;</code></pre> в коде модуля это срабатывает.</p><p>2. Скрипт обрабатывающий аякс (на jQuery):</p><p><pre class="prettyprint"><code>jQuery(function($) {<br />&nbsp; $('.tabs-nav-link').click(function(){<br />&nbsp; var module = $(this).attr('data-module');<br />&nbsp; var order = $(this).attr('data-order');<br /><br />&nbsp; var parent = $(this).parents('div.index-news-contayner');<br />&nbsp; $('li.tabs-nav-item', parent).removeClass('tabs-nav-item_state_active');<br />&nbsp; $(this).parent().addClass('tabs-nav-item_state_active')<br />&nbsp; $.ajax({<br />&nbsp; type: &quot;POST&quot;,<br />&nbsp; url: '/index.php?option=com_flexicontent&amp;controller=other&amp;task=news_ajax&amp;module='+module+'&amp;order='+order,<br />&nbsp; dataType: 'html',<br />&nbsp; success: function (data){<br />&nbsp; $('div.section-unit', parent).html(data);<br />&nbsp; }<br />&nbsp; });<br />&nbsp; return false;<br />&nbsp; });<br />});</code></pre></p><p>Скрипт вешает на ссылку с классом <pre class="prettyprint"><code>tabs-nav-link</code></pre>обработчик, запускающий аякс-запрос при нажатии на ссылку. Контейнер для вывода полученного контента в данном случае  <pre class="prettyprint"><code>div.section-unit</code></pre>.</p><p>Обработчик обращается в контроллер  <pre class="prettyprint"><code>other</code></pre> компонента Флексиконтент в котором находится функция, поставляющая контент.</p><p>Тело функции:</p><p><pre class="prettyprint"><code>function news_ajax(){<br />&nbsp; $db = JFactory::getDbo();<br />&nbsp; $input = new JInput();<br />&nbsp; $moduleId = $input-&gt;getInt('module', 0);<br />&nbsp; $order = $input-&gt;getString('order', 'default');<br /><br />&nbsp; $query = $db-&gt;getQuery(true);<br />&nbsp; $query-&gt;select('params');<br />&nbsp; $query-&gt;from('#__modules');<br />&nbsp; $query-&gt;where('`id` = ' . $moduleId);<br />&nbsp; $db-&gt;setQuery($query, 0, 1);<br />&nbsp; $result = $db-&gt;loadResult();<br /><br />&nbsp; $params = new JRegistry();<br />&nbsp; $params-&gt;loadString($result);<br /><br />&nbsp; if($order != 'default'){<br />&nbsp; $params-&gt;set('ordering', $order);<br />&nbsp; }<br /><br />&nbsp; $params-&gt;set('layout', $params-&gt;get('layout', 'default').'-inner');<br /><br />&nbsp; require(JPATH_BASE.'/modules/mod_flexicontent/mod_flexicontent.php');<br />&nbsp; die;<br />&nbsp; }</code></pre></p><p>Как видите все просто, по полученным данным я загружаю параметры модуля, меняю нужные параметры на пришедшие из запроса и вывожу модуль на печать. Стоит отметить что для таких выкрутасов я разбил шаблон модуля на два — обертка с заголовками, табами и т.п. и тело контента, которое подлежит перезагрузке. В основной шаблон подключен шаблон контента, а при перезагрузке я использую только внутренний шаблон, который в функции переназначается. В моем случае это основной — default.php и внутренний — default-inner.php.<br>
</p>]]></description>
                <pubDate>Tue, 25 Dec 2012 14:47:35 +0400</pubDate>
                            </item>
                    <item>
                <title>Определение корневой категории для компонентов, использующих таблицу категорий Joomla</title>
                <guid isPermaLink="true">http://joomclub.net/ru/t/90/</guid>
                <link>http://joomclub.net/ru/blog/programming/90.html</link>
                <author>a.sedelnikov@gmail.com</author>
                <description><![CDATA[<p>Часто надо знать корневую категорию в которой находится пользователь, например для того, чтобы оформить модули в соответствии с цветовой гаммой раздела, ну и для чего-нибудь еще, придумайте сами.</p><p>Написал функцию, определяющую корневую категорию, пригодна для любого компонента, использующего таблицу категорий Joomla, для хранения своих категорий.</p><p>Функция получилась очень простая из-за того, что в категориях использованы nested sets, которые существенно облегчают процесс выборки как вверх так и вниз по дереву.</p><p>Тело функции:</p> <a name="cut" rel="nofollow"></a> <pre class="prettyprint"><code>function getRootCat($catid){<br />&nbsp; static $id;<br /><br />&nbsp; if(empty($id)){<br />&nbsp; $db = JFactory::getDBO();<br />&nbsp; $query = $db-&gt;getQuery(true);<br /><br />&nbsp; $query-&gt;select('parent.id');<br />&nbsp; $query-&gt;from('#__categories as child');<br />&nbsp; $query-&gt;from('#__categories as parent');<br />&nbsp; $query-&gt;where('child.id = '.(int)$catid);<br />&nbsp; $query-&gt;where('parent.rgt &gt;= child.rgt');<br />&nbsp; $query-&gt;where('parent.lft &lt;= child.lft');<br />&nbsp; $query-&gt;where('parent.level = 1');<br />&nbsp; $db-&gt;setQuery($query);<br />&nbsp; &nbsp; &nbsp; &nbsp;$id = $db-&gt;loadResult();<br />&nbsp; }<br />&nbsp; return $id;<br />&nbsp; }</code></pre><p>Входящий параметр один — ид текущей категории. Выход тоже один — ид корневой категории.</p>]]></description>
                <pubDate>Tue, 25 Dec 2012 13:58:13 +0400</pubDate>
                            </item>
            </channel>
    </rss>
