Поиск

Найдена 21 статья по слову "php"

WordPress: Error establishing a database connection

Если у вас на wordpress после переноса сайта появляется строка “Error establishing a database connection”, хотя логин, пароль, название базы данных введены правильно, то попробуйте добавить в wp-config.php эту строчку. И все должно заработать ;)

define('WP_ALLOW_REPAIR', true);
php

Создание zip архива папки с вложенными папками в PHP

Для такой задачи потребуется рекурсивный обход вложенных папок, и добавление их в архив. Эту задачу (в данном случае) выполняет функция ZipDirectory, которая вызывается рекурсивно. Функция ZipFull же проверяет, возможно ли создать zip-архив, запускает ZipDirectory и закрывает файл при завершении обхода папок.

function ZipDirectory($src_dir, $zip, $dir_in_archive='') {
    $dirHandle = opendir($src_dir);
    while (false !== ($file = readdir($dirHandle))) {
        if (($file != '.')&&($file != '..')) {
            if (!is_dir($src_dir.$file)) {
                $zip->addFile($src_dir.$file, $dir_in_archive.$file);
            } else {
                $zip->addEmptyDir($dir_in_archive.$file);
                $zip = ZipDirectory($src_dir.$file.DIRECTORY_SEPARATOR,$zip,$dir_in_archive.$file.DIRECTORY_SEPARATOR);
            }
        }
    }
    return $zip;
}

function ZipFull($src_dir, $archive_path) {
    $zip = new ZipArchive();
    if ($zip->open($archive_path, ZIPARCHIVE::CREATE) !== true) {
        return false;
    }
    $zip = ZipDirectory($src_dir,$zip);
    $zip->close();
    return true;
}

Использование, например, следующее:

if (ZipFull('D:/test/','D:/result.zip')) {
    echo 'Архив успешно создан!';
} else {
    echo 'Ошибка при создании архива!';
}

Более подробно про ZipArchive вы можете почитать здесь - http://php.net/manual/en/ziparchive.open.php.

php

Как получить координаты в формате Excel из числового вида

Допустим, нам надо представить ячейку с координатами (5,4) в Excel-формате, т.е. как “E4”. Либо (27,3) как “AA3”. Эту задачу легко выполнить, если представить буквенный формат таблицы Excel в виде 26ричной системы счисления, состоящей из букв.

Т.е., нам потребуется словарь, мы можем представить его одной алфавитной строкой, и собственно, сам алгоритм, который несложен сам по себе.

Для того, чтобы получать правильные координаты ячейки Excel, будем использовать начало координат не (0,0), а (1,1), как в экселе.

Получился такой вот код:


function getExcelCell($x,$y) {
    if (($x < 1) || ($y < 1)) { return False; }
    $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $excelX = '';
    while ($x > 0) {
        $r = $x % 26;
        $x = (int)($x / 26);
        if ($r == 0) {
            $r = 26; $x = $x - 1;
        }
        $excelX = $alphabet[$r-1] . $excelX;
    }
    $excelCell = $excelX . $y;
    return $excelCell;
}

// Тест

for ($i = -10; $i < 1500; $i++) {
    $res = getExcelCell($i,$i);
    if ($res) {
        echo $res . "<br>";
    } else {
        echo 'Значение (' . $i . ', ' . $i . ') не может быть обработано!<br>';
    }
}

Как видите, в случае, если передаются отрицательные значения (или 0) в $x или $y, то функция возвращает False.

php

Красивая пагинация на битриксе / bitrix pagination

Сделал свою пагинацию на битриксе. Получилось вот так.
Минусы:
- Код некачественный. Если есть идеи по оптимизации, пишите в комментариях, поправлю.
- Игнорирует пагинацию в “обратном порядке”. Не увидел смысла в ней, поэтому отказался.

Тут можно изменять только один параметр:
$countPagesDisplay - это количество отображаемых страничек снизу (помимо первой, последней, стрелок и “…”).

Выглядит вот так:

http://localhost:8001/media/uploads/2018/11/09/pagination.png

<?
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();

if(!$arResult["NavShowAlways"])
{
    if ($arResult["NavRecordCount"] == 0 || ($arResult["NavPageCount"] == 1 && $arResult["NavShowAll"] == false))
    return;
}

// begin zadavaemie parametri

$countPagesDisplay = 3; // kolichestvo otobrajaemih stranic v paginacii

// end zadavaemie parametri

function addLeftBorder($lb) {
    if ($lb > 1) {
        $lb = $lb - 1;
    }
    return $lb;
}

function addRightBorder($rb,$max) {
    if ($rb < $max) {
        $rb = $rb + 1;
    }
    return $rb;
}

$i = 1;
$left_border = $arResult["NavPageNomer"];
$right_border = $arResult["NavPageNomer"];
$max = $arResult["NavPageCount"];

while($i < $countPagesDisplay) {
    if($i % 2 == 0) {
        $lb = $left_border;
        $left_border = addLeftBorder($left_border);
        if ($left_border == $lb) {
            $rb = $right_border;
            $right_border = addRightBorder($right_border, $max);
            if ($right_border == $rb) {
                $i = $countPagesDisplay;
            }
        }
    } else {
        $rb = $right_border;
        $right_border = addRightBorder($right_border, $max);
        if ($right_border == $rb) {
            $lb = $left_border;
            $left_border = addLeftBorder($left_border);
            if ($left_border == $lb) {
                $i = $countPagesDisplay;
            }
        }
    }
    $i++;
}
$arResult["nStartPage"] = $left_border;
$arResult["nEndPage"] = $right_border;

//echo "<pre>"; print_r($arResult);echo "</pre>";

$strNavQueryString = ($arResult["NavQueryString"] != "" ? $arResult["NavQueryString"]."&amp;" : "");
$strNavQueryStringFull = ($arResult["NavQueryString"] != "" ? "?".$arResult["NavQueryString"] : "");

?>
<div class="paginator">

<font class="text">

<?if ($arResult["NavPageNomer"] > 1):?>

    <?if($arResult["bSavePage"]):?>
        <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=($arResult["NavPageNomer"]-1)?>">&larr;</a>
        <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=1">1</a>
    <?else:?>
        <?if ($arResult["NavPageNomer"] > 2):?>
            <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=($arResult["NavPageNomer"]-1)?>">&larr;</a>
        <?else:?>
            <a href="<?=$arResult["sUrlPath"]?><?=$strNavQueryStringFull?>">&larr;</a>
        <?endif?>
        <?if ($arResult["nStartPage"] != 1):?>
            <a href="<?=$arResult["sUrlPath"]?><?=$strNavQueryStringFull?>">1</a>
        <?endif?>
    <?endif?>

<?else:?>
    &larr;&nbsp;
<?endif?>

<?if ($arResult["nStartPage"] > 2):?>
    <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=($arResult["nStartPage"]-1)?>">...</a>
<?endif?>

<?while($arResult["nStartPage"] <= $arResult["nEndPage"]):?>
    <?if ($arResult["nStartPage"] == $arResult["NavPageNomer"]):?>
        <span><?=$arResult["nStartPage"]?></span>
    <?elseif($arResult["nStartPage"] == 1 && $arResult["bSavePage"] == false):?>
        <a href="<?=$arResult["sUrlPath"]?><?=$strNavQueryStringFull?>"><?=$arResult["nStartPage"]?></a>
    <?else:?>
        <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=$arResult["nStartPage"]?>"><?=$arResult["nStartPage"]?></a>
    <?endif?>
    <?$arResult["nStartPage"]++?>
<?endwhile?>

<?if ($arResult["nEndPage"] < ($arResult["NavPageCount"] - 1)):?>
    <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=($arResult["nEndPage"]+1)?>">...</a>
<?endif?>

<?if($arResult["NavPageNomer"] < $arResult["NavPageCount"]):?>
    <?if($arResult["nEndPage"] < $arResult["NavPageCount"]):?>
        <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=$arResult["NavPageCount"]?>"><?=$arResult["NavPageCount"]?></a>
        <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=($arResult["NavPageNomer"]+1)?>">&rarr;</a>
    <?else:?>
        <a href="<?=$arResult["sUrlPath"]?>?<?=$strNavQueryString?>PAGEN_<?=$arResult["NavNum"]?>=<?=($arResult["NavPageNomer"]+1)?>">&rarr;</a>
    <?endif?>
<?else:?>
    &nbsp;&rarr;
<?endif?>

</div>
bitrix

Делаем теги и ссылки к ним в статьях битрикса

Можно решить эту задачу так. Для этого в конец компонента bitrix:news (скопировав его) следует вставить функцию:

<?
function addLinkForTag($tagname) {
    $taglink = str_replace(' ','+',$tagname); // Пробелы должны заменяться плюсами
    return '<a href="/search/?tags='.$taglink.'">'.$tagname.'</a>'; // Добавляем ссылку. Внимание, у вас ссылка может быть не "/search/", а какая-либо другая!
}
?>

И для тех же статей (при условии, что все стандартно) в компоненте bitrix:news.list можно написать что-либо подобное:

<?foreach($arItem["FIELDS"] as $code=>$value):?> // Это уже было - стандартный перебор свойств каждой новости
    <small>
    <?
    if (GetMessage("IBLOCK_FIELD_".$code) == 'Теги') { // Желательно написать как-нибудь по другому, но на данный момент идей как правильно - нет :)
        if(CModule::IncludeModule("search")) { // Необходимо подключить модуль поиска. Без него работать не будет
            $tags_array = tags_prepare($value, "s1"); // Распиливаем теги в массив
            echo GetMessage("IBLOCK_FIELD_".$code).': '; // Выводим название "Теги"
            $tags_array = array_map("addLinkForTag",$tags_array); // Применяем функцию для создания ссылок для элементов массивов
            $result_tags = implode(", ", $tags_array); // Соединяем все обратно в одну строку
            echo $result_tags; // Выводим результат
        }
    } else { // Если у нас не Тег, то просто выводим как обычно "ключ" : "значение" (эта строка была по умолчанию)
        echo GetMessage("IBLOCK_FIELD_".$code).': '.$value;
    }
    ?>
    </small>
    <br />
<?endforeach;?>

Затем создаем страницу в битриксе и вставляем в нее компонент поиска bitrix:search.page. Собственно, ссылка на него и будет ссылкой, на которую надо поменять мой “/search/”.

bitrix

Обработка отправления почты в bitrix

Возникла задача - отправлять письмо о заказе, кроме клиента, на два разных ящика. Притом, ящики должны были чередоваться (в той организации два конкурирующих менеджера). Сразу возник алгоритм, что при отправке письма проверять, четный или нечетный ID заказа, и в зависимости от этого, отправлять письмо на тот, или иной ящик.
Больше всего времени пришлось затратить на поиск документации, к какому событию привязывается отправление почты. В оф. документации поиск ничего не дал - но, оказалось, что плохо искал, т.к. там эта информация была.

Для написания пригодилось знать следующее:

Событие http://dev.1c-bitrix.ru/api_help/main/events/onbeforeeventadd.php вызывается в момент добавление почтового события в таблицу b_event. Как правило, задача обработчика данного события - изменить или добавить какое-либо значение, передаваемое в макросы почтового шаблона.

Порядок выполнения страницы (в данном случае не слишком пригодилось, но однозначно полезная информация).

Почтовая система

Итак, сам код. Его надо разместить в /bitrix/php_interface/init.php.

<?
AddEventHandler("main", "OnBeforeEventAdd", array("MailCheredator", "OnBeforeEventAddHandler"));

class MailCheredator {
    function OnBeforeEventAddHandler(&$event, &$lid, &$arFields) {
        $arFields["SALE_EMAIL"] = "sale_mail@example.ru";
        $arFields["BCC"] = "";
        if (intval($arFields["ORDER_ID"]) % 2 == 1) {
            $arFields["EMAIL"] = $arFields["EMAIL"]. ",email1@example.ru";
        } else {
            $arFields["EMAIL"] = $arFields["EMAIL"]. ",email2@example.ru";
        }
    }
}
?>

Здесь,
SALE_EMAIL - в моем случае, адрес, с которого отправляется письмо (у вас может быть другой!).
BCC - сюда отправляются копии письма, которые не должен видеть тот, кому отправляется письмо (можно было email1 и email2 сюда записать).
EMAIL - адрес, куда отправится письмо. Можно перечислять через запятую.

bitrix

Просмотр всех свойств элемента инфоблока

Пригодится для просмотра в API битрикса всех данных об элементах инфоблока. А потом найденное можно будет изменить. Подробности можно прочитать тут: http://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getlist.php

<?
$arFilter = Array(
    "IBLOCK_ID"=>IntVal(2), //id инфоблока
    "ACTIVE"=>"Y", // только активные
    "SECTION_ID"=>38, // id раздела в инфоблоке
    "INCLUDE_SUBSECTIONS"=>"Y" // чтобы включались подразделы
);
$res = CIBlockElement::GetList(Array("SORT"=>"ASC", "PROPERTY_PRIORITY"=>"ASC"), $arFilter);
while($ob = $res->GetNextElement())
{
    $arFields = $ob->GetFields();
    echo $arFields["NAME"]."<br />";
    print_r($arFields);
    $arProps = $ob->GetProperties();
    print_r($arProps);
    echo "<br /><br />";
}
?>
bitrix

CSRF token missing or incorrect (django)

После переноса сайта с хостинга jino на webfaction, при попытке отправки любой формы возникала ошибка “CSRF token missing or incorrect”. Т.е. даже залогиниться на сайт было невозможно (авторизация через админку работала нормально и на сайте после я этого был авторизован).

CSRF - это уязвимость, когда пользователи, переходя по обычной ссылке, запускают хакерский скрипт, который может от их имени передать какую-либо форму на абсолютно другой сайт (например, оставить от их имени комментарий на одном из форумов или еще что-нибудь). Сам хакер не сможет получить результат перехода по ссылке. Собственно, это и отличает CSRF от XSS (http://www.securitylab.ru/analytics/292473.php).

Все описания этой ошибки ссылаются на документацию - https://docs.djangoproject.com/en/dev/ref/contrib/csrf/, либо советом добавлять во всех формах {% csrf_token %} в темплейтах (у меня он везде добавлен) и проверить, есть ли в settings.py в MIDDLEWARE_CLASSES пункт 'django.middleware.csrf.CsrfViewMiddleware'. Это все было. И не помогало.

Выход нашел, когда сравнил MIDDLEWARE_CLASSES от вебфакшна и джино.

webfaction:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

jino:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
)

Поменяв на джиновские миддлвары - все запустилось и заработало нормально. Т.е., получилось, что ‘django.middleware.csrf.CsrfViewMiddleware’, в моем случае, не должна была быть в списке. Хотя, возможно, что после ее удаления, джанго просто не показывает ошибку, а уязвимость осталась. По крайней мере, на данный момент, проблему это решило. При следующей встрече, постараюсь решить эту проблему правильней, на данный момент знаний по этой теме не хватает.

django

Подключение TinyMCE в админку django

Для того, чтобы в админке подключить WYSIWYG-редактор TinyMCE необходимо проделать следующие операции.

  1. Скачиваем сам редактор TinyMCE: http://www.tinymce.com/download/download.php и заливаем на сервер (со стороннего url работать не будет).

  2. Устанавливаем django-tinymce (обязательно должен быть версии 1.5.1a2 или выше, в стабильной на момент написания статьи версии 1.5 он имеет баг, из-за которого не хочет работать без напильника):

pip install django-tinymce
  1. В settings.py вашего проекта записываем записываем следующие переменные:
TINYMCE_JS_URL = 'tiny_mce/tiny_mce.js'
TINYMCE_JS_ROOT = 'tiny_mce'
TINYMCE_DEFAULT_CONFIG = {'theme': "advanced", 'theme_advanced_toolbar_location' : "top", 'height': '400'}

TINYMCE_JS_URL - путь к tiny_mce.js - например, http://mysite.com/tinymce/tiny_mce.js (крайне желательно писать без домена, он здесь дан только для того, чтобы было понятно, относительно чего происходит запрос)

TINYMCE_JS_ROOT - путь к корневой папке, где лежит tiny_mce.js - например, http://mysite.com/tinymce/ (крайне желательно писать без домена)

TINYMCE_DEFAULT_CONFIG - конфигурация по умолчанию, подробности см. в официальной документации TinyMCE.

Также, в INSTALLED_APPS надо дописать 'tinymce':

INSTALLED_APPS = (
    ...
    'tinymce',
    ...
)
  1. В модель, в которой хотим включить редактор TinyMCE импортируем tinymce:
from tinymce import models as tinymce_models

Для самого класса модели пишем следующее

class MyModel(models.Model):
    myField = tinymce_model.HTMLField()

Т.е. мы заменяем models.TextField() на tinymce_model.HTMLField() в необходимых местах.

  1. В urls.py проекта добавляем (r'^tinymce/',include('tinymce.urls')):
urlpatterns = patterns('myproject.views',
    ...
    (r'^tinymce/', include('tinymce.urls')),
    (r'^admin/', include(admin.site.urls)),
)

Источники:
1. http://seobacks.ru/tinymce-django.html
2. http://django-tinymce.googlecode.com/svn/tags/release-1.5/docs/.build/html/index.html

django

Table X is marked as crashed and should be repaired

Это ошибка обычно возникает из-за неожиданной перезагрузки СУБД.

В PhpMyAdmin или MySQL-консоли выполните следующий запрос:

REPAIR TABLE `mytable`

где mytable - таблица, указанная в ошибке.

sql