В Unix и Linux (и, возможно, в OS X тоже) текущая Кодировка файловой системы задается параметром локали LC_CTYPE (см. функцию setlocale() http://php.net/manual/ru/function.setlocale.php). Например, он может иметь значение типа en_US.UTF-8, что означает кодировку UTF-8. Затем имена файлов и их пути могут быть созданы с помощью fopen() или получены с помощью dir() с этой кодировкой.
default_charset = "utf-8";
header('Content-Type: text/html; charset=utf-8');
header("Content-type: application/json; charset=utf-8");
<?xml version="1.0" encoding="UTF-8"?>
function utf8_for_xml($string)
{
return preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $string);
}
$safeString = utf8_for_xml($yourUnsafeString);
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<form accept-charset="utf-8">
htmlspecialchars($str, ENT_NOQUOTES, "UTF-8");
mysql_set_charset('utf8', $link);
$mysqli->set_charset("utf8");
- iconv http://www.php.net/manual/en/ref.iconv.php
- mbstring http://www.php.net/manual/en/ref.mbstring.php
[client]
default-character-set=UTF-8
[mysql]
default-character-set=UTF-8
[mysqld]
character-set-client-handshake = false #force encoding to uft8
character-set-server=UTF-8
collation-server=UTF-8_general_ci
[mysqld_safe]
default-character-set=UTF-8
Проверить можно следующим образом
mysql> show variables like 'char%';
| character_set_client | UTF-8
| character_set_connection | UTF-8
| character_set_database | UTF-8
| character_set_filesystem | binary
| character_set_results | UTF-8
| character_set_server | UTF-8
| character_set_system | UTF-8
| character_sets_dir | /usr/share/mysql/charsets/
Если соединяющийся клиент не имеет никакого способа определить кодировку для его связи с MySQL, после того, как соединение установлено, вы, возможно, должны выполнить следующую команду / запрос:
SET CHARACTER SET UTF8;
SET NAMES UTF8;
При определении размера полей varchar при моделировании базы данных не забывайте, что для символов UTF-8 может потребоваться до 4 байт на символ.
Обратите внимание, что Кодировка utf8 MySQL имеет максимум 3 байта и не может кодировать все символы юникода. Если вам нужно кодировать символы за пределами BMP (Basic Multilingual Plane), такие как emoji или другие специальные символы, вам нужно будет использовать другую кодировку, такую как utf8mb4 или любую другую кодировку, поддерживающую более высокие плоскости. Mysql откажется от любых символов, закодированных в 4 байтах (или больше). Кодировка utf8 (псевдоним utf8mb3).
https://dev.mysql.com/doc/refman/5.7/en/charset-unicode-utf8.html https://dev.mysql.com/doc/refman/5.7/en/charset-unicode-utf8mb4.html
charset_type = utf-8
sql_query_pre = SET CHARACTER_SET_RESULTS=UTF-8
sql_query_pre = SET NAMES UTF-8
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20),
PARTITION p3 VALUES LESS THAN (30)
);
PARTITION BY RANGE( TO_DAYS(order_date) ) (
PARTITION y2009m1 VALUES LESS THAN( TO_DAYS('2009-02-01') ),
PARTITION y2009m2 VALUES LESS THAN( TO_DAYS('2009-03-01') ),
PARTITION y2009m3 VALUES LESS THAN( TO_DAYS('2009-04-01') )
);
PARTITION BY LIST(store_id) (
PARTITION pNorth VALUES IN (3,5,6,9,17),
PARTITION pEast VALUES IN (1,2,10,11,19,20)
)
PARTITION BY HASH(store_id)
PARTITIONS 4;
PARTITION BY KEY(s1)
PARTITIONS 10;
setlocale(LC_ALL,'C.UTF-8');
basename("àxà"); // now returns "àxà", which is correct
pathinfo("àyà/àxà", PATHINFO_BASENAME); // now returns "àxà", which is correct
$lc = new LocaleManager();
$lc->doBackup();
$lc->fixLocale();
basename("àxà/àyà");
$lc->doRestore();
class LocaleManager
{
/** @var array */
private $backup;
public function doBackup()
{
$this->backup = array();
$localeSettings = setlocale(LC_ALL, 0);
if (strpos($localeSettings, ";") === false)
{
$this->backup["LC_ALL"] = $localeSettings;
}
// If any of the locales differs, then setlocale() returns all the locales separated by semicolon
// Eg: LC_CTYPE=it_IT.UTF-8;LC_NUMERIC=C;LC_TIME=C;...
else
{
$locales = explode(";", $localeSettings);
foreach ($locales as $locale)
{
list ($key, $value) = explode("=", $locale);
$this->backup[$key] = $value;
}
}
}
public function doRestore()
{
foreach ($this->backup as $key => $value)
{
setlocale(constant($key), $value);
}
}
public function fixLocale()
{
setlocale(LC_ALL, "C.UTF-8");
}
}
{include file="common/subheader.tpl" title=__("title") target="#id"}
<div id="id" class="collapse in">
</div>
Tygh::$app['session']['auth'];
проблема возникает из-за модуля product_variations, строка 1335
if (empty($data['appearance']['obj_prefix'])) {
$view->assign('no_capture', false);
}
можно решить, например, с помощью переписывания в шаблоне списков /overrides/blocks/list_templates/grid_list.tpl
{assign var="obj_id" value=$product.product_id}
{* где добавить строку *}
{assign var="obj_prefix" value="prefix"}
Использовать modernizr с детекцией touch'а
.no-touch a:hover { color: #06e; }
$(document)
.ready(function()
{
$.mobile.linkBindingEnabled = false;
});
function fnGetUrlParams(sURL)
{
var aHashes = sURL.slice(sURL.indexOf('?') + 1).split('&');
return aHashes
.reduce(
function(oParameters, sHash)
{
var [sKey, sValue] = sHash.split('=');
return Object.assign(oParameters, {[sKey]: decodeURIComponent(sValue)})
},
{}
);
}
function fnSetUrlParams(sURL, oParameters, bUpdate)
{
var sBaseURL = sURL.split('?')[0];
var oNewParameters = {};
if (bUpdate) {
var oBaseParameters = fnGetUrlParams(sURL);
oNewParameters = Object.assign(oBaseParameters, oParameters);
} else {
oNewParameters = oParameters;
}
var aParameters = [];
for (var sKey in oNewParameters) {
aParameters.push(sKey+'='+oNewParameters[sKey]);
}
return sBaseURL+'?'+aParameters.join('&');
}
// файл app/addons/addon_name/schemas/menu/menu.post.php
$schema['central']['addon_name.menu_id']['items']['addon_name.submenu_id'] = array(
'attrs' => array(
'class' => 'is-addon'
),
'href' => 'addon_controller_name.manage',
'position' => 700
);
$schema['central']['addon_name.menu_id']['position'] = 900;
return $schema;
// файл app/addons/addon_name/controllers/backend/products.post.php
Registry::set(
'navigation.tabs.addon_tab_id',
[
'title' => __('addon_name.tab_name'),
'js' => true,
]
);
function fn_addon_name_get_products($params, $fields, $sortings, &$condition, &$join, $sorting, $group_by, $lang_code, $having)
{
if ($params['items_per_page']>0) {
$sJoin = str_replace("products.", "p.", $join);
$sCondition = str_replace("products.", "p.", $condition);
$sJoin = preg_replace("/INNER JOIN \?:products_categories.*?(?=INNER)/", "", $sJoin);
$sJoin = preg_replace("/INNER JOIN \?:categories.*?(?=LEFT)/", "", $sJoin);
$sJoin = preg_replace("/INNER JOIN \?:categories.*?$/", "", $sJoin);
preg_match("/AND \?:categories.*?(?=AND)/", $sCondition, $aMatches);
$sCategoriesCondition = $aMatches[0];
$sCondition = preg_replace("/AND \?:categories.*?(?=AND)/", "", $sCondition);
$sCondition = preg_replace("/AND p\.product_type.*\)/", "", $sCondition);
$sOrCondition = "SELECT COUNT(*) FROM ?:products AS p $sJoin WHERE p.parent_product_id=products.product_id $sCondition";
$condition = preg_replace(
"/^\s*AND\s*(.*)/",
"AND (\\1) OR (($sOrCondition)>0 AND products.status IN ('A') $sCategoriesCondition)",
$condition
);
}
}
function array_every(callable $oCallback, array $aArr) {
foreach ($aArr as $mElement) {
if (!$oCallback($mElement)) {
return false;
}
}
return true;
}
$name = 'ярослав';
echo mb_convert_case($name, MB_CASE_TITLE, "UTF-8"); // Ярослав
$smarty.request.variable
Tygh::$app['view']->assign('sVar', '');
Tygh::$app['view']->tpl_vars['meta_keywords']->value;
Registry::get('addons.addon_name.parameter_name');
Registry::get('runtime.company_id');
list($iR, $iG, $iB) = sscanf($sColor, "%02x%02x%02x");
return ($iR*0.299 + $iG*0.587 + $iB*0.114) > 186 ? "black" : "white";
$controller = Registry::get('runtime.controller');
$mode = Registry::get('runtime.mode');
в шаблоне
{$runtime.controller}
{$runtime.mode}
$languages = Languages::getAll();
CART_LANGUAGE
Включить переадресацию(для модуля seo) на /seo-link с адреса типа index.php?dispatch=controller.mode
$_SERVER['X-SEO-REWRITE'] = true;
// if ($_SERVER['REQUEST_METHOD'] == 'GET' && empty($_SERVER['X-SEO-REWRITE']) && !empty($req['dispatch'])) {
// строка из файла /app/addons/seo/func.php
function fn_unparse_url($parsed_url)
{
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
$user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
$pass = ($user || $pass) ? "$pass@" : '';
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
return "$scheme$user$pass$host$port$path$query$fragment";
}
$aURL = parse_url($sURL);
$sURL = fn_unparse_url($aURL);
вставить в app/addons/addon_name/addon.xml
...
<item>
INSERT INTO `?:exim_layouts` (name, cols, pattern_id, active) VALUES ('general', 'Product code,Name,Sort,Status', 'table_name', 'Y');
</item>
<item for="uninstall">
DELETE FROM `?:exim_layouts` WHERE pattern_id = 'table_name'
</item>
...
файл меню app/addons/addon_name/schemas/menu.post.php
$schema['top']['administration']['items']['export_data']['subitems']['addon_name.table_name'] = array(
'href' => 'exim.export?section=table_name',
'position' => 2
);
$schema['top']['administration']['items']['import_data']['subitems']['addon_name.table_name'] = array(
'href' => 'exim.import?section=table_name',
'position' => 2
);
return $schema;
файл app/addons/addon_name/schemas/exim/exim_name.php
<?php
use Tygh\Registry;
$schema = array(
'section' => 'table_name',
'name' => __('table_name'),
'pattern_id' => 'table_name',
'key' => array('table_name_id'),
'order' => 30,
'table' => 'table_name',
'permissions' => array(
'import' => 'manage_catalog',
'export' => 'view_catalog',
),
'export_notice' => __('addon_name.exim_notice'),
'condition' => array(
'use_company_condition' => false,
),
'order_by' => 'table_name_id, sort',
'references' => array(
'products' => array(
'reference_fields' => array('product_id' => '#table_name.product_id'),
'join_type' => 'INNER'
),
'product_descriptions' => array(
'reference_fields' => array('product_id' => '#table_name.product_id', 'lang_code' => DESCR_SL),
'join_type' => 'LEFT'
),
),
'export_fields' => array(
/*
'ID' => array(
'required' => false,
'alt_key' => true,
'db_field' => 'ms_palette_color_groups_id',
),
*/
'Product code' => array(
'required' => true,
'table' => 'products',
'db_field' => 'product_code',
),
'Name' => array(
'required' => true,
'db_field' => 'name',
),
'Sort' => array(
'required' => false,
'db_field' => 'sort',
),
'Status' => array(
'required' => false,
'db_field' => 'status',
),
),
'import_get_primary_object_id' => array(
'skip_alt_keys' => array(
'function' => 'fn_addon_name_skip_alt_keys',
'args' => array('$pattern', '$alt_keys', '$object', '$skip_get_primary_object_id'),
'import_only' => true,
),
),
'import_process_data' => array(
'import_colors' => array(
'function' => 'fn_addon_name_import_colors_groups',
'args' => array('$primary_object_id', '$object', '$pattern', '$options', '$processed_data', '$processing_groups', '$skip_record'),
'import_only' => true,
)
),
);
return $schema;
файл app/addons/addon_name/func.php
function fn_addon_name_skip_alt_keys($pattern, $alt_keys, $object, &$skip_get_primary_object_id)
{
$skip_get_primary_object_id = true;
}
function fn_addon_name_import_colors_groups($primary_object_id, $object, $pattern, $options, &$processed_data, $processing_groups, &$skip_record)
{
$skip_record = true;
$sTableName = 'table_name';
static $aProductIDs = [];
$iProductID = 0;
if (!isset($aProductIDs[$object['product_code']])) {
$iProductID = db_get_field(
"
SELECT
product_id
FROM
?:products
WHERE
product_code = ?s
",
$object['product_code']
);
} else {
$iProductID = $aProductIDs[$object['product_code']];
}
if (!$iProductID)
return;
$aProductIDs[$object['product_code']] = $iProductID;
db_query(
"
INSERT INTO
?:$sTableName
SET
name = '{$object['name']}',
sort = '{$object['sort']}',
status = '{$object['status']}',
product_id = '{$iProductID}'
"
);
$processed_data['N']++;
}
//$aSelectedOptions = ["option id" => "variant id"];
$oProductManager = Tygh::$app['addons.product_variations.product.manager'];
$sVariationCode = $oProductManager->getVariationCode($iProductID, $aSelectedOptions);
/**
* Saves product variation by product combination.
*
* @param array $parent_product_data Parent product data
* @param array $combination Product combination data
* @param array $languages List of languages
*
* @return int
*/
function fn_addon_name_save_variation($parent_product_data, array $combination, $languages)
{
$data = array_merge($parent_product_data, array(
'product_id' => null,
'tracking' => ProductTracking::TRACK_WITHOUT_OPTIONS,
'product_type' => ProductManager::PRODUCT_TYPE_VARIATION,
'parent_product_id' => $parent_product_data['product_id'],
'variation_code' => $combination['variation'],
'variation_options' => json_encode($combination['selected_options']),
'timestamp' => time(),
'updated_timestamp' => time(),
'list_price' => $combination['list_price'],
'weight' => $combination['weight'],
'amount' => isset($combination['amount']) ? $combination['amount'] : 1,
'product_code' => $combination['code'],
'is_default_variation' => empty($combination['is_default_variation']) ? 'N' : $combination['is_default_variation']
));
$iCount = db_get_field("SELECT COUNT(*) FROM ?:products WHERE variation_code = ?s", $combination['variation']);
if ($iCount)
return;
$product_variation_id = db_query('INSERT INTO ?:products ?e', $data);
fn_update_product_prices($product_variation_id, array(
'price' => $combination['price'],
'prices' => array(),
));
foreach ($languages as $lang_code => $lang) {
$description_data = array(
'product_id' => $product_variation_id,
'company_id' => $data['company_id'],
'lang_code' => $lang_code,
'product' => $combination['name'],
);
db_query('INSERT INTO ?:product_descriptions ?e', $description_data);
}
return $product_variation_id;
}
function fn_addon_name_generate_variations($iProductID, $oAuth, $iOptionID)
{
$aProduct = fn_get_product_data($iProductID, $oAuth, CART_LANGUAGE, '', false, false, false, false, false, false, false, false);
$aOption = fn_get_product_option_data($iOptionID, $iProductID);
$aOptions = [];
$aOptions[$aOption['option_id']] = $aOption;
$aCombinations = fn_product_variations_get_options_combinations($aProduct, $aOptions);
$aVariations = [];
$iIndex = fn_product_variations_get_last_product_code_index($iProductID);
foreach ($aCombinations as $sVariationCode => $aCombination) {
$aVariations[$sVariationCode] = fn_product_variations_get_variation_by_selected_options(
$aProduct,
$aOptions,
$aCombination['selected_options'],
$iIndex
);
}
if (!empty($aVariations)) {
$options_ids = array_keys($aOptions);
/** @var ProductManager $product_manager */
$product_manager = Tygh::$app['addons.product_variations.product.manager'];
$languages = Languages::getAll();
$product_row = db_get_row('SELECT * FROM ?:products WHERE product_id = ?i', $iProductID);
$default_product_variation = $product_manager->getDefaultVariationOptions($iProductID);
foreach ($aVariations as $variation_code => $combination) {
$combination['is_default_variation'] = ($default_product_variation) ? 'N' : 'Y';
fn_addon_name_save_variation($product_row, $combination, $languages);
$default_product_variation = true;
}
$product_manager->changeProductTypeToConfigurable($iProductID, array_values($options_ids));
}
}
if (!defined('BOOTSTRAP')) { die('Access denied'); }
$sTableName = "";
$sControllerName = $sTableName;
$aDefaultData = array(
);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$suffix = '.manage';
if ($mode == 'import') {
$oHandler = fopen($_FILES['file']['tmp_name'], 'r');
fgetcsv($oHandler);
while(!feof($oHandler)) {
$aItem = fgetcsv($oHandler);
//TODO
}
fclose($oHandler);
}
if ($mode == 'export') {
$sFilePath = '/export.csv';
$oHandler = fopen($_SERVER['DOCUMENT_ROOT'].$sFilePath, 'w');
$aItems = db_get_array("SELECT * FROM ?:$sTableName");
fputcsv(
$oHandler,
[
//TODO
]
);
foreach ($aItems as $aItem) {
fputcsv(
$oHandler,
[
//TODO
]
);
}
fclose($oHandler);
header("Location: $sFilePath");
die();
}
if ($mode == 'm_delete') {
foreach ($_REQUEST["${sTableName}_ids"] as $iItemId) {
db_query("DELETE FROM ?:$sTableName WHERE ${sTableName}_id=?i", $iItemId);
}
}
if ($mode == 'm_update') {
foreach ($_REQUEST["${sTableName}_data"] as $iItemId => $iItemData) {
$iItemData = array_merge($aDefaultData, $iItemData);
db_query("UPDATE ?:$sTableName SET ?u WHERE ${sTableName}_id = ?i", $iItemData, $iItemId);
}
}
if ($mode == 'update') {
$_REQUEST["${sTableName}_data"] = array_merge($aDefaultData, $_REQUEST["${sTableName}_data"]);
if ($iID) {
db_query("UPDATE ?:$sTableName SET ?u WHERE ${sTableName}_id = ?i", $_REQUEST["${sTableName}_data"], $_REQUEST["${sTableName}_id"]);
} else {
db_query("REPLACE INTO ?:$sTableName ?e", $_REQUEST["${sTableName}_data"]);
}
}
if ($mode == 'delete') {
db_query("DELETE FROM ?:$sTableName WHERE ${sTableName}_id=?i", $_REQUEST["${sTableName}_id"]);
}
if (!empty($_REQUEST["redirect"])) {
return array(CONTROLLER_STATUS_OK, $_REQUEST["redirect"]);
}
return array(CONTROLLER_STATUS_OK, $sControllerName . $suffix);
}
if ($mode == 'update') {
$aItem = db_get_row("SELECT * FROM ?:$sTableName WHERE ${sTableName}_id=?i", $_REQUEST["${sTableName}_id"]);
Tygh::$app['view']->assign(array(
'sRedirectURL' => $_REQUEST["redirect"],
'aItem' => $aItem,
));
}
if ($mode == 'add') {
$aItem = array(
);
Tygh::$app['view']->assign(array(
'sRedirectURL' => $_REQUEST["redirect"],
'aItem' => $aItem,
));
}
if ($mode == 'manage') {
$aDefaultParameters = array(
'page' => 1,
'items_per_page' => 10
);
$aParameters = array_merge($aDefaultParameters, $_REQUEST);
$aSortings = array(
"${sTableName}_id" => "?:$sTableName.${sTableName}_id",
'sort' => "?:$sTableName.sort",
'status' => "?:$sTableName.status",
);
$aSorting = db_sort($aParameters, $aSortings, "sort", 'asc');
$sCondition = '';
if (!empty($aParameters['q'])) {
//$sCondition .= db_quote(" OR text LIKE ?l", "%" . trim($aParameters['q']) . "%");
}
$aParameters['total_items'] = db_get_field("SELECT COUNT(*) FROM ?:$sTableName WHERE 1 ?p", $sCondition);
$sLimit = db_paginate($aParameters['page'], $aParameters['items_per_page'], $aParameters['total_items']);
$aItems = db_get_hash_array(
"SELECT * FROM ?:$sTableName WHERE 1 ?p ?p ?p",
"${sTableName}_id",
$sCondition,
$aSorting,
$sLimit
);
Tygh::$app['view']->assign(array(
'aItems' => $aItems,
'aSearch' => $aParameters,
));
}