Додайте функцію спеціального перенаправлення на сторінку подяки woocommerce

Posted Posted in Поради / рекомендації
add_action('after_setup_theme', 'woocommerce_support');
        function woocommerce_support()
        {
          add_theme_support('woocommerce');
        }


        add_filter('woocommerce_cart_item_name', 'add_excerpt_in_cart_item_name', 10, 3);
        function add_excerpt_in_cart_item_name($item_name,  $cart_item,  $cart_item_key)
        {
          $excerpt = wp_strip_all_tags(get_the_excerpt($cart_item['product_id']), true);
          $style = ' style="font-size:14px; line-height:normal;"';
          $excerpt_html = '
        <p name="short-description" class="product-description"' . $style . '>' . $excerpt . '</p>';

          return $item_name . $excerpt_html;
        }
        add_action( 'woocommerce_get_return_url', 'trueroman_redirect_to_thank_you_2', 90, 2 );
 
        function truemisha_redirect_to_thank_you_2( $thank_you_url, $order ) {
         
          // it would be nice to check the status of the order, do not redirect fake orders
          if( $order->has_status( 'failed' ) ) {
            return $thank_you_url;
          }
         
          return site_url( '/thanks?id='.$order->get_id() );
       
        }

Оновлювати кошик автоматично при зміні кількості

Posted Posted in Поради / рекомендації
add_action('wp_head', function () {

?><style>
    .woocommerce button[name="update_cart"],
    .woocommerce input[name="update_cart"] {
      display: none;
    }
  </style><?php

        });

        add_action('wp_footer', function () { ?>
  <script>
    jQuery(function($) {
      let timeout;
      $('.woocommerce').on('change', 'input.qty', function() {
        if (timeout !== undefined) {
          clearTimeout(timeout);
        }
        timeout = setTimeout(function() {
          $("button[name='update_cart']").removeAttr("disabled");
          $("[name='update_cart']").trigger("click"); // trigger cart update
        }, 1000); // 1 second delay, half a second (500) seems comfortable too
      });
    });
  </script>
<?php

        });

Мінімальне замовлення товару woocommerce

Posted Posted in Поради / рекомендації
/**
 * For cart
 */
add_filter('woocommerce_cart_item_quantity', 'trueroman_min_kolvo_cart', 20, 3);

function truemisha_min_kolvo_cart($product_quantity, $cart_item_key, $cart_item)
{

  $product = $cart_item['data'];
  $min = 0;

  if (567 === $product->get_id()) { // товар с ID 500
    $min = 1;
  }

  return woocommerce_quantity_input(
    array(
      'input_name'   => "cart[{$cart_item_key}][qty]",
      'input_value'  => $cart_item['quantity'],
      'max_value'    => $product->get_max_purchase_quantity(),
      'min_value'    => $min,
      'product_name' => $product->get_name(),
    ),
    $product,
    false
  );
}

Автоматично додавати продукт у кошик під час відвідування woocommerce

Posted Posted in Поради / рекомендації
/**
 * Automatically add product to cart on visit
 */
add_action('template_redirect', 'add_product_to_cart');
function add_product_to_cart()
{
  $simple_product_id = 567;


  if (!is_admin()) {
    $product_id = 567; //replace with your own product id
    $found = false;


    //check if product already in cart
    if (sizeof(WC()->cart->get_cart()) > 0) {
      foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
        $_product = $values['data'];
        if ($_product->get_id() == $product_id)
          $found = true;
      }
  
        // товар с ID 27 в корзине
        // if product not found, add it
   
        if (!$found) 
          WC()->cart->add_to_cart($product_id);
        } else {
          // if no products in cart, add it
          WC()->cart->add_to_cart($product_id);
        
    
    }
  }
}

How to enable the Gutenberg editor в WooCommerce products

Posted Posted in Поради / рекомендації
add_filter( 'use_block_editor_for_post_type', 'art_enable_rest_for_product', 10, 2 );
add_filter( 'woocommerce_taxonomy_args_product_cat', 'art_show_in_rest_for_product', 10, 1 );
add_filter( 'woocommerce_taxonomy_args_product_tag', 'art_show_in_rest_for_product', 10, 1 );
add_filter( 'woocommerce_register_post_type_product', 'art_show_in_rest_for_product', 10, 1 );

/**
 * Включение редактора Gutenberg для товаров
 *
 * @sourcecode https://onmywaystudio.net/
 *
 * @param  bool   $can_edit
 * @param  string $post_type
 *
 * @return bool
 *
 * @author        Roman Petrovich
 * @testedwith    WC 3.9
 */
function art_enable_rest_for_product( $can_edit, $post_type ) {

	if ( 'product' === $post_type ) {
		$can_edit = true;
	}

	return $can_edit;
}

/**
 * Включение поддержки REST для товаров
 *
 * @sourcecode https://onmywaystudio.net/
 * @param  array $args
 *
 * @return mixed
 *
 * @author        Roman Petrovich
 * @testedwith    WC 3.9
 */
function art_show_in_rest_for_product( $args ) {

	$args['show_in_rest'] = true;

	return $args;
}

Перевірка дозволів на решта Woocommerce

Posted Posted in Поради / рекомендації
REST-API WOOCOMERCE

add_filter( 'woocommerce_rest_check_permissions', 'my_woocommerce_rest_check_permissions', 90, 4 ); function my_woocommerce_rest_check_permissions( $permission, $context, $object_id, $post_type ){ return true; }

редирект со страницы на страницу

RewriteCond %{QUERY_STRING} ^_route_=login/$
RewriteRule ^(.*)$ https://onmywaystudio.net/? [R=301,L]

Відображення сторінок лише авторизованим користувачам wordpress

Posted Posted in Поради / рекомендації
function prefix_redirect_function() {
if ( is_page(552 , 554) && !is_user_logged_in() ) { // 42 это ID
// редирект на главную:        wp_redirect( home_url() );
// или так на url:
// wp_redirect( ‘http://www.example.com’, 301 );exit;
    }
}
.page-id-296 .zip-check {display:none}

Встановіть файл cookie та закрийте спливаюче вікно після надсилання Contact Form 7 form

Posted Posted in Поради / рекомендації
<?php
// As is this will check if the form is in a popup, if so set a cookie and close after 5 seconds.

// Copy everything below this line.
function custom_cf7_scripts() { ?>
	<script type="text/javascript">
		var wpcf7Elm = document.querySelector('.wpcf7');

		wpcf7Elm.addEventListener('wpcf7submit', function (event) {
			var $form = $(event.target),
				$popup = $form.parents('.pum');

			if (!$popup.length) {
				return;
			}
			
			$popup.trigger('pumSetCookie');

			setTimeout(function () {
				$popup.popmake('close');
			}, 5000);
		}, false);
	</script><?php
}

add_action( 'wp_footer', 'custom_cf7_scripts' );

Платіжний віджет Liqpay

Posted Posted in Поради / рекомендації
$liqpay = new LiqPay($public_key, $private_key);
$html = $liqpay->cnb_form(array(
'action'         => 'pay',
'amount'         => '1',
'currency'       => 'USD',
'description'    => 'description text',
'order_id'       => 'order_id_1',
'version'        => '3'
));
Параметри платіжного віджета
dataRequiredStringjson рядок з параметрами APIs закодований функцією base64_encode( json_string ), де base64_encode – повертає рядок, закодований методом base64
signatureRequiredStringУнікальний підпис кожного запиту base64_encode( sha1( private_key + data + private_key) ), де sha1 – повертається хеш у вигляді бінарного рядку з 20 символів.
embedToOptionalStringЕлемент на HTML-сторінці в якому буде відображений віджет
modeOptionalStringРежим відображення віджета на сайті. Можливі значення: embed – вбудоване вікно, popup – спливаюче вікно на Вашому сайті.
languageOptionalStringМова відображення віджету ruuken.
  <div id="liqpay_checkout"></div>
  <script>
	window.LiqPayCheckoutCallback = function() {
		LiqPayCheckout.init({
			data: "eyAidmVyc2lvbiIgOiAzLCAicHVibGljX2tleSIgOiAieW91cl9wdWJsaWNfa2V5IiwgImFjdGlv" +
			"biIgOiAicGF5IiwgImFtb3VudCIgOiAxLCAiY3VycmVuY3kiIDogIlVTRCIsICJkZXNjcmlwdGlv" +
			"biIgOiAiZGVzY3JpcHRpb24gdGV4dCIsICJvcmRlcl9pZCIgOiAib3JkZXJfaWRfMSIgfQ==",
			signature: "QvJD5u9Fg55PCx/Hdz6lzWtYwcI=",
			embedTo: "#liqpay_checkout",
			language: "ru",
			mode: "embed" // embed || popup
		}).on("liqpay.callback", function(data){
			console.log(data.status);
			console.log(data);
		}).on("liqpay.ready", function(data){
			// ready
		}).on("liqpay.close", function(data){
			// close
		});
	};
  </script>
  <script src="//static.liqpay.ua/libjs/checkout.js" async></script>
Параметри для формування data:
Основні
ParameterRequiredTypeDescription
versionRequiredNumberВерсія API. Поточне значення – 3
public_keyRequiredStringПублічний ключ – ідентифікатор магазину. Отримати ключ можна в налаштуваннях магазину
actionRequiredStringТип операції. Можливі значення: pay – платіж, hold – блокування коштів на рахунку відправника, subscribe – регулярний платіж, paydonate – пожертва, auth – предавторізація картки
amountRequiredNumberСума платежу. Наприклад: 57.34
currencyRequiredStringВалюта платежу. Можливі значення: USDEURUAH
descriptionRequiredStringПризначення платежу.
order_idRequiredStringУнікальний ID покупки у Вашому магазині. Максимальна довжина 255 символів.
expired_dateOptionalStringЧас до якого клієнт може оплатити рахунок за UTC. Передається в форматі 2016-04-24 00:00:00
languageOptionalStringМова клієнта ruuken
paytypesOptionalStringПараметр в якому передаються способи оплати, які будуть відображені на чекауті. Можливі значення apay – оплата за допомогою Apple Pay, gpay – оплата за допомогою Google Pay, card – оплата карткою, liqpay – через кабінет liqpay, privat24 – через кабінет приват24, masterpass – через кабінет masterpass, moment_part – розстрочка, cash – готівкою, invoice – рахунок на e-mail, qr – сканування qr-коду. Якщо параметр не переданий, то застосовуються настройки магазину, вкладка Checkout.
result_urlOptionalStringURL у Вашому магазині на який покупець буде переадресовано після завершення покупки. Максимальна довжина510 символів.
server_urlOptionalStringURL API в Вашому магазині для повідомлень про зміну статусу платежу (сервер->сервер). Максимальна довжина 510 символів. Детальніше
verifycodeOptionalStringМожливе значення Y. Динамічний код верифікації, генерується і повертається в Callback. Так само згенерований код буде переданий в транзакції верифікації для відображення у виписці по картці клієнта. Працює для actionauth.

Платіж з розщепленням суми на декількох одержувачів. У цьому параметрі вказується JSON масив з правилами розщеплення платежу. При використанні параметра split_rules відбувається одне списання з клієнта і кілька зарахувань одержувачам. Еквайрингова комісія стягується з кожного магазину в масиві split_rules. Приклад JSON рядка:

[
  {
    "public_key": "i000000001",
    "amount": 1,
    "commission_payer": "sender",
    "server_url": "https://server1/callback"
  },
  {
    "public_key": "i000000002",
    "amount": 2,
    "commission_payer": "receiver",
    "server_url": "https://server2/callback"
  }
]
Параметри відправника
sender_address NEWOptionalStringАдреса відправника
sender_cityOptionalStringМісто відправника
sender_country_codeOptionalStringКод країни відправника. Цифровий ISO 3166-1 код
sender_first_nameOptionalStringІм’я відправника
sender_last_nameOptionalStringПрізвище відправника
sender_postal_codeOptionalStringПоштовий індекс відправника
Параметри захищеного платежу
letter_of_creditOptionalStringЩоб включити прийом платежів за акредитивом передайте параметр із значенням1
letter_of_credit_dateOptionalStringДата закінчення терміну акредитива в наступному форматі 2015-03-31 00:00:00 по UTC.
Параметри регулярного платежу
subscribeOptionalStringРегулярний платіж. Можливі значення: 1
subscribe_date_startOptionalStringДата першого платежу. Час необхідно вказувати в такому форматі 2015-03-31 00:00:00 по UTC. Якщо вказана минула дата, то підписка буде активована з поточної дати отримання запиту
subscribe_periodicityOptionalStringПеріодичність списання коштів. Можливі значення:
month – раз на місяць
year – раз на рік
Параметри для оплати в 1 клік
customerOptionalStringУнікальний ідентифікатор клієнта на сайті мерчанта. При передачі параметра LiqPay запам’ятовує платіжні реквізити клієнта і його ідентифікатор – подальша оплата може бути проведена в 1 клік. Максимальна довжина 100 символів.
(При використанні параметра для <b>Masterpass 1 клік</b>, в даному полі передається валідный номер телефону платника)
recurringbytokenOptionalStringДозволяє генерувати card_token платника, який ви отримаєте в callback запиті на server_urlcard_token дозволяє проводити платежі без введення реквізитів картки платника, використовуючи API оплати за токеном – тобто в 1 клік. Для отримання card_token необхідно передати в запиті значення: 1
customer_user_idOptionalStringІдентифікатор користувача в системі мерчанта, передається при кожній оплаті користувача (не повинен збігатися з customer, використовується для оплати за допомогою гаманця <b>Masterpass 1 клік</b>)
Інші параметри
daeOptionalStringДовгий запис Detail Addenda.
Параметр dae являє собою JSON рядок, до якого застосували функцію base64JSON може містити наступні параметри:
{
  "airLine": "Avia", // абревіатура авіакомпанії, max 4 символів.
  "ticketNumber": "ACSFD12354SA", // номер квитка, max 15 символів. 
  "passengerName": "John Doe", // ім'я пасажира, max 29 символів.
  "flightNumber": "742", // номер рейсу, max 5 цифр.
  "originCity": "DP", // код міста/аеропорту вильоту, max 5 символів.
  "destinationCity": "NY", // код міста/аеропорту призначення, max 5 символів.
  "departureDate": "100514" // дата вильоту в форматі YYMMDD, max 6 цифр.
}

Виправлення поширеної помилки jQuery в WordPress

Posted Posted in Поради / рекомендації
wp_enqueue_script( 'tt-mobile-menu', get_template_directory_uri() .

'/js/mobile-menu.js', array('jquery'), '1.0', true );

jQuery(document).ready(function()

{

jQuery(#selector) ...

});

(function($) {

// Use $() inside of this function

$(#selector) ...

})(jQuery);
<script src="http://code.jquery.com/jquery-1.11.2.min.js" type="text/javascript"></script>

Як скрити повідомлення або сторінки від администратора WordPress

Posted Posted in Поради / рекомендації
function true_hide_pages_from_admin( $query ) {
	global $pagenow;
	if( is_admin() && 'edit.php' == $pagenow && 'page' == get_query_var('post_type') ){
		// в качестве 'page' в условии можно указать любой произвольный тип постов
		$query->set( 'post__not_in', array(300,271) ); 
		// через запятую прописываем ID страниц, которые хотим скрыть
	}
	return $query;
}
 
add_action( 'pre_get_posts' ,'true_hide_pages_from_admin' );
function true_hide_posts_from_admin( $query ) {
	global $pagenow;
	if( is_admin() && 'edit.php' == $pagenow ){
		$query->set( 'post__not_in', array(9,54) ); 
		// через запятую указываем ID постов или страниц, которые хотим скрыть
	}
	return $query;
}
 
add_action( 'pre_get_posts' ,'true_hide_posts_from_admin' );
function true_hide_all( $query ) {
	$query->set( 'post__not_in', array(300,271) ); 
	return $query;
}
 
add_action( 'pre_get_posts' ,'true_hide_all' ); 

Змінити фото в URL-адресі

Posted 2 коментаріPosted in Поради / рекомендації
<meta name="viewport" content="width=device-width, initial-scale=1">
   <meta property="og:image" content="https://onmywaystudio.net/wp-content/uploads/2018/05/cropped-download-1-1.png;" />
<meta property="og:image:secure_url" content="https://onmywaystudio.net/wp-content/uploads/2018/05/cropped-download-1-1.png"; />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:width" content="400" />
<meta property="og:image:height" content="300" />
<meta property="og:image:alt" content="" />

Додавання згоди на політику конфіденційності WooCommerce

Posted Posted in Поради / рекомендації
// Добавление чекбокса
add_action( 'woocommerce_review_order_before_submit', 'truemisha_privacy_checkbox', 25 );
 
function truemisha_privacy_checkbox() {
 
	woocommerce_form_field( 'privacy_policy_checkbox', array(
		'type'          => 'checkbox',
		'class'         => array( 'form-row' ),
		'label_class'   => array( 'woocommerce-form__label-for-checkbox' ),
		'input_class'   => array( 'woocommerce-form__input-checkbox' ),
		'required'      => true,
		'label'         => 'Принимаю <a href="' . get_privacy_policy_url() . '">Политику конфиденциальности</a>',
	));
 
}
 
// Валидация
add_action( 'woocommerce_checkout_process', 'truemisha_privacy_checkbox_error', 25 );
 
function truemisha_privacy_checkbox_error() {
 
	if ( empty( $_POST[ 'privacy_policy_checkbox' ] ) ) {
		wc_add_notice( 'Ваш нужно принять политику конфиденциальности.', 'error' );
	}
 
}
// Добавление чекбокса
add_action( 'woocommerce_register_form', 'truemisha_registration_privacy_checkbox', 25 );
 
function truemisha_registration_privacy_checkbox() {
 
	woocommerce_form_field(
		'privacy_policy_reg',
		array(
			'type'          => 'checkbox',
			'class'         => array( 'form-row' ),
			'label_class'   => array( 'woocommerce-form__label-for-checkbox' ),
			'input_class'   => array( 'woocommerce-form__input-checkbox' ),
			'required'      => true,
			'label'         => 'Принимаю <a href="' . get_privacy_policy_url() . '">Политику конфиденциальности</a>',
		)
	);
 
}
 
// Валидация
add_filter( 'woocommerce_registration_errors', 'truemisha_registration_privacy_checkbox_error', 25 );
 
function truemisha_registration_privacy_checkbox_error( $errors ) {
 
	if( is_checkout() ) {
		return $errors;
	}
 
	if ( empty( $_POST[ 'privacy_policy_reg' ] ) ) {
		$errors->add( 'privacy_policy_reg_error', 'Ваш нужно принять политику конфиденциальности.' );
	}
 
	return $errors;
 
}

Доступність товару в Woocommerce

Posted Posted in Поради / рекомендації
add_action( 'woocommerce_before_shop_loop_item_title', 'my_sold_out_loop' );
 
function my_sold_out_loop() {
    global $product;
 
    if ( !$product->is_in_stock() ) {
        echo '<span class="soldout">Нет в наличии</span>';
    }
}

add_action( 'woocommerce_before_single_product_summary', 'my_sold_out_loop' );

span.soldout {
padding: 3px 7px;
background: #7b1616;
color: white;
font-size: 13px;
}
add_filter( 'woocommerce_get_availability', 'wcs_custom_get_availability', 1, 2);
function wcs_custom_get_availability( $availability, $_product ) {  
    if ( $_product->is_in_stock() ) {
        $availability['availability'] = __('Available!', 'woocommerce');
    }
    if ( ! $_product->is_in_stock() ) {
        $availability['availability'] = __('Sold Out', 'woocommerce');
    }
    return $availability;
}
    if ( $product->is_in_stock() ) {
        echo '<div class="stock" >' . $product->get_stock_quantity() . ' в наличии</div>';
    } else {
        echo '<div class="out-of-stock" >Нет в наличии</div>';
    }
function my_stock_loop() {
    global $product;
    if ( $product->is_in_stock() ) {
        echo '<div class="stock" >' . $product->get_stock_quantity() . ' в наличии</div>';
    } else {
        echo '<div class="out-of-stock" >Нет в наличии</div>';
    }
}
add_action( 'woocommerce_after_shop_loop_item_title', 'my_stock_loop' );
add_filter( 'woocommerce_get_price_html', 'my_price_html', 100, 2 );
function my_price_html( $price, $product ){
  global $product;
  $return_string = $price;
  if ( $product->stock_status == 'outofstock' ) {
  	  $return_string = $price .' &nbsp;(Нет в наличии)';
     }
  return $return_string; 	
}
add_filter( 'woocommerce_product_subcategories_hide_empty', 'hide_empty_categories', 10, 1 );
function hide_empty_categories ( $hide_empty ) {
    $hide_empty  =  FALSE;
    // You can add other logic here too
    return $hide_empty;
}
add_filter( 'woocommerce_product_subcategories_hide_empty', 'show_empty_categories', 10, 1 );
function show_empty_categories ( $show_empty ) {
    $show_empty  =  TRUE;
    // You can add other logic here too
    return $show_empty;
}

Додати поле до профілю користувача wordpress і woocommerce

Posted Posted in Поради / рекомендації
function my_user_contactmethods($user_contactmethods){
    $user_contactmethods['phone'] = 'Телефон';
    return $user_contactmethods;
}
add_filter('user_contactmethods', 'my_user_contactmethods');

<p class="form-row form-row-wide">
        <label for="phone">Phone</label>
        <input type="text" class="input-text" name="phone" id="phone" value="<?php echo esc_attr( $user->phone ); ?>" />
    </p>
    
    $phone  = ! empty( $_POST[ 'phone' ] ) ? $_POST[ 'phone' ] : '';
  $user->phone = $phone;

Опис категорії продуктів Woocommerce під продуктами

Posted Posted in Поради / рекомендації

Для того, щоб відобразити опис категорій товарів Woocommerce внизу сторінки – під товари, необхідно додати у файл functions.php теми наступного коду:

remove_action( 'woocommerce_archive_description', 'woocommerce_taxonomy_archive_description', 10 );

add_action( 'woocommerce_after_shop_loop', 'woocommerce_taxonomy_archive_description', 100 );
function woocommerce_taxonomy_archive_description() {
    if ( is_tax( array( 'product_cat', 'product_tag' ) ) && get_query_var( 'paged' ) == 0 ) {
        $description = wpautop( do_shortcode( term_description() ) );
        if ( $description ) {
            echo '<div class="term-description">' . $description . '</div>';
        }
    }
}

Сортування записів WordPress за часом створення та користувацьким полем AFC

Posted Posted in Поради / рекомендації
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

function my_pre_get_posts($query) {

    if ($query->is_main_query() && !is_admin()) { 
        $query->set('meta_key', 'sorting'); // сортировка по произвольному полю
        $query->set('orderby', 'meta_value_num');
        $query->set('order', 'ASC'); // порядок сортировки
    }
    $query->set('meta_query', $meta_query);
}
function postSorting() {
    $todays_date = current_time('Ymd');
    $args = array(
        'post_type' => 'post',
        'posts_per_page' => '4',
        'paged' => $paged,
        'meta_query' => array(
            'relation' => 'AND',
            'sorting_clause' => array(
                'key' => 'sorting',
                'type' => 'numeric',
                'value' => array(0, 100),
                'compare' => 'BETWEEN',
                
            ),
            'date' => array(
                'date_clause' => array(
                    'key' => 'date',
                    'compare' => '<=',
                    'value' => $todays_date,
                ),
                'time_clause' => array(
                    'key' => 'time',
                    'compare' => 'EXISTS',
                ),
            )
        ),
        'orderby' => array(
            'sorting_clause' => 'ASC',
            'date_clause' => 'ASC',
            'time_clause' => 'ASC',
        ),
    );
 
    $query = new WP_Query( $args );

    //вывод цикла...

    // сброс
    wp_reset_postdata();
}

Відсоткова знижка на весь кошик без купона у WooCommerce

Posted Posted in Поради / рекомендації

Фіксована процентна знижка на весь кошик у WooCommerce
Отже, почнемо з найпростішої знижки – фіксованої. У ньому знижка буде використана до всього кошика в результаті, без зайвих дій з боку користувача.

Скрипт знижки:

function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	$discount = $cart->subtotal * 0.05; // 0.05 - это 5%
	
	$cart->add_fee('Фиксированная скидка в 5% ', -$discount);

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Ви вставляєте його в кінці файлу functions.php, який знаходиться в папці вашої теми.

Фіксована (застосовується, коли в кошику є певні товари) відсоткова знижка на весь кошик у WooCommerce
Другий варіант фіксованої знижки – це знижка, яка застосовується залежно від того, які товари (або набори товарів) знаходяться у кошику.

Скрипт для застосування знижки за наявності певного товару в кошику:

function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	$array_product_id = [];

	foreach($cart->get_cart() as $cart_item) {

		$array_product_id[] = $cart_item['product_id'];
	
	}

	if(in_array(6, $array_product_id)) { // Если в корзине есть товар с ID = 6

		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

		$cart->add_fee('Фиксированная скидка в 5% за выбор акционного товара ', -$discount);

	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Скрипт для застосування знижки за наявності одного з товарів в кошику:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	$array_product_id = [];

	foreach($cart->get_cart() as $cart_item) {

		$array_product_id[] = $cart_item['product_id'];
	
	}

	if(in_array(6, $array_product_id) || in_array(7, $array_product_id)) { // Если в корзине есть товар с ID = 6 или ID = 7

		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

		$cart->add_fee('Фиксированная скидка в 5% за выбор акционного товара ', -$discount);

	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Скрипт для застосування знижок на певні товари у кошику:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	$array_product_id = [];

	foreach($cart->get_cart() as $cart_item) {

		$array_product_id[] = $cart_item['product_id'];
	
	}

	if(in_array(6, $array_product_id) && in_array(7, $array_product_id)) { // Если в корзине есть товары с ID = 6 и ID = 7

		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

		$cart->add_fee('Фиксированная скидка в 5% за выбор акционных товаров ', -$discount);

	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Той, який вам потрібний, ви вставляєте внизу файлу functions.php, який знаходиться у папці вашої теми. Якщо ви використовуєте варіативні товари, то код «product_id» потрібно замінити на «variation_id».

Фіксована (застосовується за наявності товарів з певних категорій у кошику) відсоткова знижка на весь кошик у WooCommerce
Тут, як ви вже зрозуміли, на відміну від попереднього варіанту для застосування знижки перевіряється не сам товар, а категорія, в якій він знаходиться.

Скрипт для застосування знижки за наявності в кошику товару з певної категорії


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	foreach($cart->get_cart() as $cart_item) {

		if(has_term(16, 'product_cat', $cart_item['product_id'])) { // Если в корзине есть товар из категории с ID = 16

			$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

			$cart->add_fee('Фиксированная скидка в 5% за выбор товара из акционной категории ', -$discount);

			break;

		}
	
	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Скрипт для застосування знижки за наявності товару в кошику з однієї категорії:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	foreach($cart->get_cart() as $cart_item) {

		if(has_term([16, 23], 'product_cat', $cart_item['product_id'])) { // Если в корзине есть товар из категории с ID = 16 или ID = 23

			$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

			$cart->add_fee('Фиксированная скидка в 5% за выбор товара из акционной категории ', -$discount);

			break;

		}
	
	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Скрипт для застосування знижки за наявності товару в кошику з певних категорій:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	foreach($cart->get_cart() as $cart_item) {

		if(has_term(16, 'product_cat', $cart_item['product_id']) && has_term(23, 'product_cat', $cart_item['product_id'])) { // Если в корзине есть товар из категории с ID = 16 и ID = 23

			$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

			$cart->add_fee('Фиксированная скидка в 5% за выбор товара из акционных категорий ', -$discount);

			break;

		}
	
	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Скрипт для застосування знижки за наявності в кошику товарів з певних категорій:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	$one_category = false; // Товар из первой категории
	$two_category = false; // Товар из второй категории

	foreach($cart->get_cart() as $cart_item) {

		if(has_term(16, 'product_cat', $cart_item['product_id'])) { // Если в корзине есть товар из категории с ID = 16

			$one_category = true;

		}

		if(has_term(23, 'product_cat', $cart_item['product_id'])) { // Если в корзине есть товар из категории с ID = 23

			$two_category = true;

		}
	
	}

	if($one_category && $two_category) { // Если в корзине есть товары из категорий с ID = 16 и ID = 23

		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

		$cart->add_fee('Фиксированная скидка в 5% за выбор товаров из акционных категорий ', -$discount);

	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Той, який вам потрібен, ви все одно вставляєте внизу файлу functions.php, який знаходиться у папці вашої теми.

Фіксована (залежно від обраного способу доставки) відсоткова знижка на весь кошик у WooCommerce
Крім того, що ми можемо прив’язати знижку до конкретного товару або, наприклад, його категорії, можна просто організувати знижку на обраний спосіб доставки.

Скрипт для застосування знижки при виборі конкретного способу доставки:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	global $woocommerce;

	$delivery_name = '';
	$delivery_selected = [];
	$available_methods = $woocommerce->shipping->get_packages();

	if(isset($woocommerce->session)) {

		$delivery_selected = $woocommerce->session->get('chosen_shipping_methods');

	}

	foreach($available_methods as $method) {
		
		foreach($delivery_selected as $delivery) {
			
			if(isset($method['rates'][$delivery])) {

				$delivery_name = $method['rates'][$delivery]->label;

				break;

			}
		
		}

	}

	if($delivery_name == 'Самовывоз') {

		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

		$cart->add_fee('Фиксированная скидка в 5% за самовывоз ', -$discount);

	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Скрипт для застосування знижки при виборі одного із зазначених способів доставки:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	global $woocommerce;

	$delivery_name = '';
	$delivery_selected = [];
	$available_methods = $woocommerce->shipping->get_packages();

	if(isset($woocommerce->session)) {

		$delivery_selected = $woocommerce->session->get('chosen_shipping_methods');

	}

	foreach($available_methods as $method) {
		
		foreach($delivery_selected as $delivery) {
			
			if(isset($method['rates'][$delivery])) {

				$delivery_name = $method['rates'][$delivery]->label;

				break;

			}
		
		}

	}

	if($delivery_name == 'Самовывоз' || $delivery_name == 'СДЭК') {

		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%

		$cart->add_fee('Фиксированная скидка в 5% за выбранный способ доставки ', -$discount);

	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Тот, который вам нужен, вы вставляете внизу файла functions.php, который находится в папке вашей темы.

Динамическая (переменная в зависимости от суммы) процентная скидка на всю корзину в WooCommerce
В отличие от вышеупомянутых вариантов с фиксированной скидкой, здесь задача немного усложняется. Мы привяжем нашу скидку к ценовому диапазону. И, например, когда человек заказал товаров на сумму от 1000 до 10 000, мы дадим ему одну скидку, а выше – другую.

Реализация будет выглядеть так:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	$woo_current_price = $cart->subtotal; // Текущая итоговая сумма
	
	if($woo_current_price >= 1000 && $woo_current_price <= 10000) {
	
		$discount = $cart->subtotal * 0.03; // 0.03 - это 3%
		$cart->add_fee('Скидка в 3% за заказ на сумму от 1 000 до 10 000 рублей ', -$discount);
		
	} elseif($woo_current_price > 10000) {
	
		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%
		$cart->add_fee('Скидка в 5% за заказ на сумму более 10 000 рублей ', -$discount);
	
	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Ви також вставляєте його в низ файлу functions.php, який знаходиться в папці вашої теми.

Динамічна (змінна залежно від загальної кількості товарів) відсоткова знижка на весь кошик у WooCommerce
Тут, як ви зрозуміли із заголовка, ми розраховуватимемо знижку не на суму, як ми це зробили в другому варіанті, а на кількість товарів у кошику.

Виконання:


function woo_discount_total(WC_Cart $cart) {

	if(is_admin() && !defined('DOING_AJAX')) {
	
		return;
		
	}

	$woo_count_item = $cart->get_cart_contents_count(); // Количество товаров в корзине
	
	if($woo_count_item >= 10 && $woo_count_item <= 50) {
	
		$discount = $cart->subtotal * 0.03; // 0.03 - это 3%
		$cart->add_fee('Скидка в 3% за заказ включающий в себя от 10 до 50 товаров ', -$discount);
		
	} elseif($woo_count_item > 50) {
	
		$discount = $cart->subtotal * 0.05; // 0.05 - это 5%
		$cart->add_fee('Скидка в 5% за заказ включающий в себя более 50 товаров ', -$discount);
	
	}

}

add_action('woocommerce_cart_calculate_fees' , 'woo_discount_total');

Увімкнуть перевірку поля телефону у woocommerce

Posted Posted in Поради / рекомендації
// Custom validation for Billing Phone checkout field 
add_action('woocommerce_checkout_process', 'custom_validate_billing_phone'); 
function custom_validate_billing_phone() { 
    $is_correct = preg_match('^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$', $_POST['billing_phone']); 
    if ($_POST['billing_phone'] && !$is_correct) { 
     wc_add_notice(__('The Phone field should be <strong>between 6 and 20 digits</strong>.'), 'error'); 
    } 
}

jQuery не визначено в WordPress

Posted Posted in Поради / рекомендації

Крок 1: Увімкнення бібліотеки jQuery

Коли ви переглядаєте код, переконайтеся, що jQuery увімкнено і завантажиться перед сценарієм. Навіть jQuery слід завантажувати лише один раз. Якщо він завантажується кілька разів, це спричинить проблему.

Якщо він не увімкнений, передайте його як третій аргумент у вашій функції wp_enqueue_script() таким чином:

wp_enqueue_script( 'tt-mobile-menu', get_template_directory_uri() .

'/js/mobile-menu.js', array('jquery'), '1.0', true );

Шаг 2: Структура файлу JavaScript

По-друге, ви переконаєтеся, що ваш JavaScript почнеться так:

jQuery(document).ready(function()

{

jQuery(#selector) ...

});

(function($) {

// Use $() inside of this function

$(#selector) ...

})(jQuery);

Крок 3. Переконайтеся, що jQuery завантажено

Іноді виникають проблеми, тому що jQuery не завантажується, хоч увімкнено. Отже, щоб переконатися, що jQuery завантажено, скопіюйте URL-адресу зі сценарію src і вставте його у нову вкладку браузера. Наприклад: якщо сценарій src такий:

<script src="http://code.jquery.com/jquery-1.11.2.min.js" type="text/javascript"></script>

Приховування полів замовлення в залежності від обраного способу доставки WooCommerce

Posted Posted in Поради / рекомендації

Крок один. Додавання форми полів до фрагмента

WooCommerce має таку функціональність фрагментів, ви можете додати до них потрібний html і відобразити в потрібному місці. Отже, додайте фрагмент

Код змінено. Попередній фрагмент буде працювати, але якщо магазин використовує особистий кабінет, то виникнуть проблеми. Оскільки ця форма підключена до файлу checkout / form-billing.php, правильніше використовувати такий код

/**
 * Добавляем часть формы к фрагменту
 *
 * @sourcecode    https://wpruse.ru/woocommerce/hiding-fields-on-chosen-delivery/
 *
 * @param $fragments
 *
 * @return mixed
 *
 * @sourcecode    https://wpruse.ru/woocommerce/hiding-fields-on-chosen-delivery/
 * @author        Artem Abramovich
 * @testedwith    WC 5.5
 */
function awoohc_add_update_form_billing( $fragments ) {

	$checkout = WC()->checkout();

	parse_str( $_POST['post_data'], $fields_values );

	ob_start();

	echo '<div class="woocommerce-billing-fields__field-wrapper">';

	$fields = $checkout->get_checkout_fields( 'billing' );

	foreach ( $fields as $key => $field ) {
		$value = $checkout->get_value( $key );

		if ( isset( $field['country_field'], $fields[ $field['country_field'] ] ) ) {
			$field['country'] = $checkout->get_value( $field['country_field'] );
		}

		if ( ! $value && ! empty( $fields_values[ $key ] ) ) {
			$value = $fields_values[ $key ];
		}

		woocommerce_form_field( $key, $field, $value );
	}

	echo '</div>';

	$fragments['.woocommerce-billing-fields__field-wrapper'] = ob_get_clean();

	return $fragments;
}

add_filter( 'woocommerce_update_order_review_fragments', 'awoohc_add_update_form_billing', 99 );

Крок другий. Видалення непотрібних полів

Передбачається, що способи доставки налаштовані. Наприклад, було створено два методи. Тепер вам потрібно вказати бажаний ідентифікатор способу доставки. Найпростіший спосіб – заглянути у вихідний код

Вибрані рядки є ідентифікаторами. Тепер достатньо зробити чек, і якщо ми отримаємо бажаний спосіб доставки, видаліть зайві поля

/**
 * Скрываем поля для бесплатного способа доставки
 *
 * @param $fields
 *
 * @return mixed
 *
 * @sourcecode    https://wpruse.ru/woocommerce/hiding-fields-on-chosen-delivery/
 * @author        Artem Abramovich
 * @testedwith    WC 5.5
 */
function awoohc_override_checkout_fields( $fields ) {

	// получаем выбранные методы доставки.
	$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );

	// проверяем текущий метод и убираем не ненужные поля.
	if ( false !== strpos( $chosen_methods[0], 'free_shipping' ) ) {
		unset(
			$fields['billing']['billing_company'],
			$fields['billing']['billing_address_1'],
			$fields['billing']['billing_address_2'],
			$fields['billing']['billing_city'],
			$fields['billing']['billing_postcode'],
			$fields['billing']['billing_state'],
			$fields['billing']['billing_phone'],
			$fields['billing']['billing_email']
		);
	}

	return $fields;
}

add_filter( 'woocommerce_checkout_fields', 'awoohc_override_checkout_fields' );

Крок третій. Оновлення сторінки

Все працює, окрім оновлення сторінки. Додамо деяку магію ajax, оскільки вся обробка полів на сторінці Checkout здійснюється за допомогою ajax.

/**
 * Прелоад при переключении доставки
 *
 * @sourcecode    https://wpruse.ru/woocommerce/hiding-fields-on-chosen-delivery/
 * @author        Artem Abramovich
 * @testedwith    WC 5.5
 */
function awoohc_add_script_update_shipping_method() {

	if ( is_checkout() ) {
		?>
		<!--Скроем поле Страна. Если успользуется поле Страна, то следцет убрать скрытие-->
		<style>
			#billing_country_field {
				display: none !important;
			}
		</style>

		<!--Выполняем обновление полей при переключении доставки-->
		<script>
			  jQuery( document ).ready( function( $ ) {
				  $( document.body ).on( 'updated_checkout updated_shipping_method', function( event, xhr, data ) {
					  $( 'input[name^="shipping_method"]' ).on( 'change', function() {
						  $( '.woocommerce-billing-fields__field-wrapper' ).block( {
							  message: null,
							  overlayCSS: {
								  background: '#fff',
								  'z-index': 1000000,
								  opacity: 0.3
							  }
						  } );
					  } );
				  } );
			  } );
		</script>
		<?php
	}
}

add_action( 'wp_footer', 'awoohc_add_script_update_shipping_method' );

Код підключається до гачка wp_footer, при бажанні його можна помістити в окремий файл. Код був перевірений на стандартну тему StoreFront. Все повинно працювати коректно.

І оновлення полів також робиться не після оновлення способів доставки, а паралельно з цим оновленням

Заміна знака валюти на літери Woocommerce

Posted Posted in Поради / рекомендації

Відкриваємо файл WordPress теми functions.php і додаємо в нього фільтр для woocommerce (УВАГА !!! Код наведений нижче додаємо в кінець файлу functions.php):

 

add_filter( 'woocommerce_currencies', 'add_my_currency' );

function add_my_currency( $currencies ) {

$currencies['UAH'] = __( 'Українська гривня', 'woocommerce' );

return $currencies;

}

add_filter('woocommerce_currency_symbol', 'add_my_currency_symbol', 10, 2);

function add_my_currency_symbol( $currency_symbol, $currency ) {

switch( $currency ) {

case 'UAH': $currency_symbol = 'грн'; break;

}

return $currency_symbol;

}

Встановлення платформи Orchid – адміністративна панель Laravel

Posted Posted in Поради / рекомендації

Перш ніж використовувати платформу, її потрібно встановити. Цей посібник повинен допомогти вам виконати просту установку для початку проекту.

Створіть проект

Примітка. Якщо ви вже встановили Laravel, ви можете пропустити цей крок.

Будучи пакетом для фреймворку, спочатку потрібно встановити Laravel. Це можна зробити за допомогою інструмента керування залежностями Composer, запустивши composer create-projectкоманду у своєму терміналі:

$ composer create-project laravel/laravel orchid-project "8.*" --prefer-dist

Щоб отримати додаткову інформацію про те, як встановити Laravel, дотримуйтесь Офіційного посібника з встановлення Laravel .

У вас немає композитора? Його легко встановити, дотримуючись інструкцій на сторінці завантаження .

Він створить новий orchid-projectкаталог, завантажить залежності та сформує провідні каталоги та файли, необхідні для початку роботи. Іншими словами, встановіть свій новий фреймворк-проект.

Не забудь

  • Встановіть права “chmod -R o + w” на каталоги storageіbootstrap/cache
  • Відредагуйте .envфайл

Примітка. Якщо ви щойно встановили Laravel, можливо, вам доведеться створити ключ за допомогою командиphp artisan key:generate

Додайте залежність

Перейдіть до створеного каталогу проекту та запустіть команду:

$ composer require orchid/platform

Примітка. Вам також потрібно створити нову базу даних, оновити .envфайл за допомогою облікових даних та додати URL-адресу програми до змінної APP_URL.

Встановлення платформи

Примітка. Установка замінить app/Models/Userмодель.

Запустіть процес встановлення, виконавши команду:

php artisan orchid:install

Створити користувача

Щоб створити користувача з максимальними дозволами, ви можете виконати таку команду з іменем користувача, електронною поштою та паролем:

php artisan orchid:admin admin admin@admin.com password

Запустіть локальний сервер

Якщо ви не встановили сервер (Nginx, Apache тощо) для запуску проекту, ви можете використовувати вбудований сервер:

php artisan serve

Відкрийте браузер і перейдіть до http://localhost:8000/admin. Якщо все працює, ви побачите сторінку входу на панель керування. Пізніше ви можете зупинити сервер, натиснувши Ctrl + Cна терміналі.

Примітка. Припустимо, у вашому середовищі виконання використовується інший домен (наприклад, orchid.loc). У цьому випадку панель адміністратора може бути недоступною. Вам потрібно вказати свій домен у файлі конфігурації config/platform.phpабо .envфайлі. Це дозволяє зробити адміністративну панель доступною для іншого домену або субдомену, наприклад platform.example.com.

Видавничі ресурси

За замовчуванням статичні файли (css / js) доставляються за маршрутами додатків. Це найкращий баланс між конфігурацією та відстеженням змін, але ви можете вказати веб-сервери для розповсюдження. Для цього вам потрібно запустити команду, яка створює символічне посилання у загальнодоступному каталозі. Будь ласка, використовуйте його, лише якщо на вашому веб-сервері є проблеми :

php artisan orchid:link

Проблеми, які виникли під час встановлення? Можливо, хтось уже мав цю проблему https://github.com/orchidsoftware/platform/issues. Якщо ні, ви можете надіслати повідомлення або звернутися за допомогою .

Оновлення

Перебуваючи в каталозі проекту, використовуйте Composerдля оновлення пакета:

composer update orchid/platform --with-dependencies

Примітка. Ви також можете оновити всі свої залежності, перелічені у composer.jsonфайлі, запустивши composer update.

Установка ext-dom PHP7

Posted Posted in Поради / рекомендації

Перш за все, прочитайте попередження! Він каже, що не запускайте composer від імені root! По-друге, ви, ймовірно, використовуєте Xammp на своєму локальному комп’ютері, який за замовчуванням має необхідні бібліотеки php.

Але на вашому сервері вам не вистачає ext-dom. php-xml має всі необхідні пов’язані пакети. Таким чином, ви можете просто встановити його, запустивши


sudo apt
-get update
sudo apt install php
-xml

Скорее всего, вам тоже не хватает mbstring . Если вы получите сообщение об ошибке, установите этот пакет также с:

sudo apt-get install php-mbstring

Доп запуск

composer update
composer
require cviebrock/eloquent-sluggable

Для тих, хто хоче встановити ext-dom на php 7.1 і вище, виконайте цю команду:

sudo apt install php-xml

Як вставити шорткод в PHP

Posted Posted in Поради / рекомендації

Спеціально для тих, хто і так все знає, а просто шукає швидку відповідь, як вставити шорткод в шаблон wordpress або на інший движок, то ось, будь ласка, використовуйте цей код:

<?php echo do_shortcode( ‘[your_shortcode]’ ); ?>

Однако не забывайте про пунктуацию! Кавычки в вашем шорткоде и в php коде должны быть разными.

Тобто, якщо у вашому шаблоні сайту на wordpress, ви використовуєте такий же шорткод, але з двома лапками всередині ([«…»]), і в вашому php-коді ви також використовуєте подвійні лапки («[…]») , то потрібно одні з них поміняти на одинарні. Саме через таких дрібних причин часто не працюють шорткоди в wordpress.

Показати пароль за допомогою піктограми

Posted Posted in Поради / рекомендації

<div class=”password”>
<input type=”password” id=”password-input” placeholder=”Введите пароль” name=”password” value=”123456″>
<a href=”#” class=”password-control”></a>
</div>
<style type=”text/css”>
.password {
width: 300px;
margin: 15px auto;
position: relative;
}
#password-input {
width: 100%;
padding: 5px 0;
height: 30px;
line-height: 40px;
text-indent: 10px;
margin: 0 0 15px 0;
border-radius: 5px;
border: 1px solid #999;
font-size: 18px;
}
.password-control {
position: absolute;
top: 11px;
right: 6px;
display: inline-block;
width: 20px;
height: 20px;
background: url(https://snipp.ru/demo/495/view.svg) 0 0 no-repeat;
}
.password-control.view {
background: url(https://snipp.ru/demo/495/no-view.svg) 0 0 no-repeat;
}
</style>

<script src=”https://snipp.ru/cdn/jquery/2.1.1/jquery.min.js”></script>
<script>
$(‘body’).on(‘click’, ‘.password-control’, function(){
if ($(‘#password-input’).attr(‘type’) == ‘password’){
$(this).addClass(‘view’);
$(‘#password-input’).attr(‘type’, ‘text’);
} else {
$(this).removeClass(‘view’);
$(‘#password-input’).attr(‘type’, ‘password’);
}
return false;
});
</script>

Створити таб вкладки для картки товару WooCommerce

Posted Posted in Поради / рекомендації

Цей плагін розширює WooCommerce, щоб дозволити власникам магазинів додавати власні вкладки до продуктів. Вкладки відображаються на окремих сторінках товару праворуч від вкладки “Опис” за замовчуванням.

Окремими вкладками товару керується на екрані редагування продукту WooCommerce і їх можна додавати для кожного продукту. Ви також можете створити збережені вкладки та додавати їх до кількох продуктів за потреби. Вкладки можна легко додавати, видаляти та переставляти.

Області вмісту вкладок використовують стандартний текстовий редактор WordPress і можуть містити текст, зображення, HTML або шорткоди.

Custom Product Tabs for WooCommerce

Приховати віджети WordPress на мобільному пристрої

Posted Posted in Поради / рекомендації

Найпростіший спосіб – використовувати Widget Options Plugin який можна приховати віджети на мобільних та інших пристроях. Він безкоштовний в репозиторії: https://wordpress.org/plugins/widget-options/.

Нижче можна побичити опції

Запити SQL для перенесення сайту WordPress в інший домен

Posted Posted in Поради / рекомендації

Опис запитів SQL

Взагалі основних запитів три (на скріншоті є і четвертий запит, але про нього трохи пізніше). Отже, https://test.onmywaystudio.net/ – старий домен, https://onmywaystudio.net/ – новий.

Назви таблиць бази даних WordPress мають префікси. За замовчуванням це wp_, але на вашому сайті префікс може бути абсолютно яким завгодно, наприклад таблиця wp_posts у вас може називатися omw_posts або qwertyposts, врахуйте це.

 

UPDATE wp_options SET option_value = REPLACE (option_value, ‘https://test.onmywaystudio.net/’, ‘https://onmywaystudio.net/’) WHERE option_name = ‘home’ OR option_name = ‘siteurl’;
UPDATE wp_posts SET post_content = REPLACE (post_content, ‘https://test.onmywaystudio.net/’, ‘https://onmywaystudio.net/’);
UPDATE wp_postmeta SET meta_value = REPLACE (meta_value, ‘https://test.onmywaystudio.net/’,’https://onmywaystudio.net/’);

Перенаправлення після вдалого замовлення в магазині

Posted Posted in Поради / рекомендації

Редирект можна зробити, додавши цей код у function.php вашій темі.

add_action( 'template_redirect', 'woo_custom_redirect_after_purchase' );
function woo_custom_redirect_after_purchase() {
    global $wp;
    if ( is_checkout() && !empty( $wp->query_vars['order-received'] ) ) {
        wp_redirect( 'URL куда будем делать редирект' );
        exit;
    }
}

Тепер можна просто створити сторінку “спасибі за замовлення” та оформити як угодно.

Install Symfony Framework

Posted Posted in Поради / рекомендації

Создание проекта

 

Чтобы создать новый Symfony проект, основанный на одном из официальных шаблонов, нужно запустить команду:

 

$ symfony new [--full | --demo] <path-to-project>

 

По умолчанию используется минимальный шаблон skeleton. Чтобы установить website-skeleton нужно запустить команду с опцией --full. Соответственно, для установки demo проекта необходимо запускать команду с опцией --demo.

 

Под капотом symfony new выполняет команду composer create-project, затем инициализирует новый Git репозиторий и сразу создаёт Initial commit.

 

symfony new

 

Локальный сервер

 

Для запуска сервера достаточно в корне приложения запустить команду

 

$ symfony serve

 

symfony serve

 

она проанализирует доступные SAPI на используемой машине и выберет лучший вариант из существующих, пользуясь следующими приоритетами: на первом месте PHP FPM, дальше PHP CGI и в конце PHP CLI. Список доступных SAPI можно посмотреть командой:

 

$ symfony local:php:list

 

symfony local:php:list

 

После этого команда запустит сервер, который будет доступен по адресу 127.0.0.1 и подберёт свободный порт начиная с 8000.

 

По умолчанию сервер запускается в интерактивном режиме. Мы сразу видим логи сервера и приложения, но наш терминал заблокирован. Сервер можно запустить в режиме демона. Для этого нужно добавить опцию -d при запуске команды symfony serve.

 

Логи можно будет посмотреть, запустив команду:

 

$ symfony server:log

 

также можно посмотреть статус запущеного сервера используя команду:

 

$ symfony server:status

 

чтобы остановить запущенный сервер используется команда:

 

$ symfony server:stop

 

UPD: Раньше для запуска сервера мы использовали пакет symfony/web-server-bundle. С появлением Symfony CLI этот пакет становится не очень актуальным, так как он умеет только запускать сервер, используя PHP CLI SAPI и не поддерживает HTTPS, доменные имена, PHP FPM SAPI и прочее.

 

Поддержка TLS

 

Некоторые сторонние сервисы или библиотеки требуют отправлять запросы, используя HTTPS протокол. Symfony CLI предоставляет возможность очень легко настроить поддержку TLS, установив дополнительные компоненты, с помощью следующей команды:

 

$ symfony server:ca:install

 

symfony server:ca:install

 

после чего достаточно перезапустить ваш браузер и вуаля — поддержка TLS настроена! Запускаете сервер командой symfony serve и можно перейти на сайт по HTTPS протоколу.

 

Мне не совсем нравится открывать все проекты по адресу https://127.0.0.1:8000 или https://localhost:8000, а вам? Это приносит свои неудобства: если запущено несколько проектов одновременно — нужно запоминать на каком порту какой проект работает; при перезапуске сервера порты могут меняться и т.п.

 

Symfony CLI решает и этот вопрос! Он предоставляет для нас proxy-сервер, с помощью которого можно создавать красивые доменные имена. Для этого нужно привязать к нашему проекту желаемое домменое имя с помощью команды:

 

$ symfony proxy:domain:attach <domain-name>

 

symfony proxy:domain:attach

 

таким образом домен demo-project.com привязался к директории с проектом. Далее нам нужно запустить proxy-сервер командой:

 

$ symfony proxy:start

 

symfony proxy:start

 

Мы запустили proxy-сервер в режиме демона и он доступен у нас по адресу http://127.0.0.1:7080, можем открыть его в браузере:

 

symfony proxy server

 

где увидим список доменов, пути к проектам в файловой системе и статус сервера для каждого проекта. На данном скриншоте видно то, что все сервера находятся в статусе Stopped, то есть они пока не запущены. Следующим шагом нам нужно добавить этот proxy-сервер в настройки ОС

 

macOS Proxy Config

 

На этом настройка proxy-сервера заканчивается, далее нужно запустить сервер уже известной нам командой symfony serve. Помимо IP-адреса с портом мы увидим наше доменное имя, по которому можем перейти в браузере! Ко всем доменным именам добавляется постфикс .wip.

 

symfony serve

 

То есть в случае использования proxy-сервера flow запуска проекта немного меняется:

 

  1. Запускаем proxy-сервер
    $ symfony proxy:start
  2. Запускаем сервер для приложения
    $ symfony serve

 

Для завершения работы с проектом “зеркалируем” действия, описанные выше:

 

  1. Останавливаем сервер
    $ symfony server:stop
  2. Останавливаем proxy-сервер
    $ symfony proxy:stop

 

Для упрощения данных операций рекоммендую использовать утилиту GNU Make.

 

Переключение версий PHP

 

Если вы используете разные версии PHP на разных проектах, вы наверняка сталкивались с проблемой переключения между версиями. Было бы здорово иметь какой-то автоматический инструмент для этого, не так ли? Symfony CLI умеет решать и эту проблему! Вам достаточно создать файл .php-version в корне проекта и в качестве содержимого указать желаемую версию.

 

$ echo "7.2" > .php-version

 

php-version

 

Как видно на скриншоте выше, Symfony CLI прочитал файл .php-version и запустил сервер, используя версию, указанную в этом файле.

 

Так же Symfony CLI предоставляет нам обёртку над PHP CLI, которая тоже учитывает версию PHP, указанную в файле .php-version. То есть если вам нужно вызывать консольные скрипты, например bin/console — используйте её.

 

$ symfony php

 

symfony php

 

Для удобства можно создать алиас для этой команды, чтобы сэкономить время и избежать ошибок в написании команды. К примеру, я создал для себя алиас sphp:

 

$ echo "alias sphp='symfony php'" >> ~/.bash_profile && source ~/.bash_profile

 

Symfony CLI предоставляет аналогичную обёртку для Composer, поэтому с ним у вас также не возникнет никаких проблем. Для удобства можно создать алиас и для этой обёртки. У меня это scomposer:

 

$ echo "alias scomposer='symfony composer'" >> ~/.bash_profile && source ~/.bash_profile

 

Проверка на уязвимые пакеты

 

В качестве бонуса Symfony CLI предоставляет команду для проверки на наличие уязвимых composer-пакетов в вашем проекте. Больше не прийдётся устанавливать в проект зависимость Symfony Security Checker. Так же официальная документация говорит о том, что версия встроенная в Symfony CLI работает оптимальнее за счёт того, что она не делает HTTP запросы на официальный API. Запустить проверку можно командой:

 

$ symfony security:check

 

symfony security:check

Встановити Laravel на Ubuntu

Posted Posted in Поради / рекомендації

Системні вимоги

Ваша система повинна відповідати таким вимогам, щоб мати можливість запускати останню версію Laravel:

PHP> = 7.1.3 з OpenSSL, PDO, Mbstring, Tokenizer, XML, Ctype і JSON PHP Extensions.
Composer – менеджер пакетів на рівні додатків для PHP.
Установка попередніх умов

По-перше, переконайтеся, що ви оновили вихідні вашої системи і існуючі пакети програмного забезпечення, використовуючи наступні команди.

$ Sudo apt-get update
$ Sudo apt-get upgrade

Установка LAMP Stack на Ubuntu

Потім потрібно вказати запущену середу LAMP (Linux, Apache, MySQL та PHP), якщо у вас вже є, ви можете пропустити цей крок або встановити LAMP stack, використовуючи наступні команди в системі Ubuntu.

$ Sudo apt-get install python-software-properties
$ Sudo add-apt-repository ppa: ondrej / php
$ Sudo apt-get update
$ Sudo apt-get install apache2 libapache2-mod-php7.2 mysql-server php7.2 php7.2-xml php7.2-gd php7.2-opcache php7.2-mbstring php7.2-mysql

Хоча репозиторій Ubuntu за замовчуванням має PHP, але завжди рекомендується мати сторонній репозиторій для більш частих оновлень.

Якщо ви хочете, ви можете пропустити цей крок і дотримуватися стандартної версії PHP зі сховищ Ubuntu.

Установка Composer на Ubuntu

Тепер нам потрібно встановити Composer (менеджер залежностей для PHP) для установки необхідних залежностей Laravel, використовуючи наступні команди.

# Curl -sS https://getcomposer.org/installer | php
# Mv composer.phar / usr / local / bin / composer
# Chmod + x / usr / local / bin / composer
Установка Laravel на Ubuntu

Після установки Composer тепер ви можете завантажити і встановити останню версію Laravel з офіційного репозиторію git в каталозі Apache / var / www.

$ Cd / var / www
$ Git clone https://github.com/laravel/laravel.git
$ Cd / var / www / laravel
$ Sudo composer install

Після завершення установки Laravel встановіть відповідні дозволи для всіх файлів, використовуючи наступні команди.

$ Chown -R www-data.www-data / var / www / laravel
$ Chmod -R 755 / var / www / laravel
$ Chmod -R 777 / var / www / laravel / storage
Налаштування ключа шифрування

Тепер створіть файл оточення для вашого застосування, використовуючи наданий приклад файлу.

$ Cp .env.example .env

Laravel використовує ключ додатки для захисту користувальницьких сеансів та інших зашифрованих даних.

Тому вам потрібно згенерувати і встановити ключ додатки в випадкову рядок, використовуючи наступну команду.

$ Php artisan key: generate

Після того, як ключ був згенерований, відкрийте файл конфігурації .env і обновіть необхідні значення.

Крім того, переконайтеся, що APP_KEY правильно встановлений в файлі конфігурації, згенерований у наведеній вище команді.

APP_NAME = Laravel
APP_ENV = local
APP_KEY = base64: AFcS6c5rhDl + FeLu5kf2LJKuxGbb6RQ / 5gfGTYpoAk =
APP_DEBUG = true
APP_URL = http: // localhost
Створити базу даних для Laravel

Можливо, вам також знадобилося створити базу даних MySQL для вашого проекту додатки Laravel, використовуючи наступні команди.

$ Mysql -u root -p
mysql> CREATE DATABASE laravel;
mysql> GRANT ALL ON laravel. * to ‘laravel’ @ ‘localhost’ IDENTIFIED BY ‘secret_password’;
mysql> FLUSH PRIVILEGES;
mysql> quit

Тепер відкрийте файл конфігурації .env і обновіть настройки бази даних, як показано нижче:

DB_CONNECTION = mysql
DB_HOST = 127.0.0.1
DB_PORT = 3306
DB_DATABASE = laravel
DB_USERNAME = laravel
DB_PASSWORD = secret_password
Налаштування Apache для Laravel

Тепер перейдіть в конфігураційний файл віртуального хоста за замовчуванням в Apache /etc/apache2/sites-enabled/000-default.conf і обновіть загальнодоступний каталог DocumentRoot в Laravel, як показано нижче:

$ Nano /etc/apache2/sites-enabled/000-default.conf

Тепер змініть конфігурацію віртуального хоста за замовчуванням з наступним змістом, а також обов’язково замініть yourdomain.tld на доменне ім’я вашого веб-сайту, як показано нижче:

<VirtualHost *: 80>
ServerName yourdomain.tld
ServerAdmin webmaster @ localhost
DocumentRoot / var / www / laravel / public
<Directory />
Options FollowSymLinks
AllowOverride None
</ Directory>
<Directory / var / www / laravel>
AllowOverride All
</ Directory>
ErrorLog $ {APACHE_LOG_DIR} /error.log
CustomLog $ {APACHE_LOG_DIR} /access.log combined
</ VirtualHost>

Після внесення вищевказаних змін не забудьте перезавантажити зміни конфігурації Apache, перезапустивши службу, використовуючи наступну команду:

$ Sudo service apache2 restart

Доступ до програми Laravel

Нарешті, отримаєте доступ до вашого додатком Laravel з браузера, використовуючи наступний URL-адресу.

http: //yourdomain.tld
або
http: // your-ip-address

Adobe Flash reaches end of life

Posted Posted in Поради / рекомендації

Adobe’s once-ubiquitous Flash Player, a browser-based runtime for displaying rich media content on the Internet, has reached the end of the road, with the company having made the final scheduled release of the technology for all regions outside mainland China.

The final release was made on December 8. Adobe will no longer support Flash Player after this month; Flash content will be blocked from running in Flash Player beginning on January 12, 2021.

Adobe advises all users to immediately uninstall Flash Player to protect their systems. In release notes, Adobe thanked customers and developers who have used the technology and created content leveraging it during the last two decades. An end-of-life general information page has been posted.

Adobe announced in July 2017 that it would discontinue Flash Player at the end of this year. Flash technology succumbed to perceptions of it as proprietary technology in an era when standards-based technologies such as HTML5 began to gather momentum. Adobe cited WebGL and WebAssembly as now-viable alternatives.

Flash sustained a critical blow when Apple declined not to support it on the iPhone and iPad mobile devices. Additionally, security issues plagued Flash, and major browser vendors began moving away from the technology. Video content site YouTube backed away from Flash in 2015, opting for HTML5.

By giving three years’ advance notice, Adobe hoped to provide enough time for developers, designers, businesses, and others to migrate their Flash content to new standards. The timing of the Flash end-of-life was coordinated with major browser vendors.

Mozilla Firefox boosts JavaScript performance

Posted Posted in Поради / рекомендації

Firefox users can expect improved JavaScript performance in the Firefox 83 browser, with the Warp update to the SpiderMonkey JavaScript engine enabled by default.

Also called WarpBuilder, Warp improves responsiveness and memory usage and speeds up page loads by making changes to JiT (just-in-time) compilers. Optimizing JiT is changed to rely solely on the CacheIR simple linear bytecode format, specifically, CacheIR data collected by the baseline tiers. The new architecture leveraged in the browser also is described as being more maintainable and unlocking additional SpiderMonkey improvements.

Firefox 83 was published in beta October 20 and is scheduled to be released November 17. Warp has been shown to be faster than Ion, SpiderMonkey’s previous optimizing JiT, including a 20 percent improvement on Google Docs load time. Other JavaScript-intensive websites such as Netflix and Reddit also have shown improvement.

Basing Warp on CacheIR enabled removal of code throughout the engine that was needed to track global type inference data used by IonBuilder, resulting in speedups. Although IonBuilder and WarpBuilder both produce Ion MIR, an intermediate representation used by the optimizing JiT back end, IonBuilder had a lot of complex code not needed in WarpBuilder. Warp also can do more work off-thread and needs fewer recompilations. Plans call for continued optimizations on Warp, which at present is slower than Ion on some synthetic benchmarks.

Warp has replaced the front end — the MIR building phase — of the IonMonkey JiT. Plans call for removing the old code and architecture, which is likely to happen in Firefox 85. Additional performance and memory usage improvements are anticipated as a result. Mozilla also will continue to incrementally optimize the back end of the IonMonkey JiT, as Mozilla believes there is still room for improvement for JavaScript-intensive workloads. Also in development is a tool for web developers and Mozilla to explore CacheIR data for a JavaScript function.

Angular, React, Vue: JavaScript frameworks

Posted Posted in Поради / рекомендації

Figure 1 describes how state manifestation is handled without such frameworks. Figure 2 describes how it is handled with the frameworks.

Figure 1. Without data binding

dev ui data binding smIDG
Figure 1.

Figure 2. With data binding via Angular, React, and Vue

web ui data binding smIDG
Figure 2.

Components

The frameworks also align in being component-based. This is not a new idea: Each area of the user interface is represented by a component. The code in the component determines what is displayed and how the view behaves. Bundling state-driven data binding into components delivers the critical advantage to all three frameworks that makes them superior in complex interfaces to what went before.

Industry adoption profiles

Now we will take a look at the presence of each framework in the industry, to get a look at the level of adoption and viability. What I mean here is, when you choose a framework for a new project, or decide on which framework to learn, you want to be sure you are adopting a framework that is going to be successful over the long term.

Figure 3 looks at the number of watchers each framework has on Stack Overflow. A few things are clear from this chart. All three frameworks have a strong presence on Stack Overflow, although Vue is far behind with just over 50,000 watchers. ReactJS has a commanding lead, which has increased over the past year.

Figure 3. Stack Overflow Watchers

so watchers large

IDG

Figure 3.

Figure 4 looks at GitHub stars. Here Angular takes last place, lagging far behind. Interestingly, Vue is in the lead, and well ahead of React, indicating a great deal of curiosity (if not actual use) in the project. In each case, over the last year, the frameworks have shown increasing interest at about the same rate.

Figure 4. GitHub Stars

github stars large

IDG

Figure 4.

GitHub stars tend to reflect people’s theoretical interest in a project. Figure 5 looks at weekly NPM downloads, which is an indicator of active, practical use of the projects.

Popularity take-away

Each of these frameworks appears to have enough up-take to be long-term viable. React’s popularity means it is easier to find developers who know it, and easier to find employers that are hiring for it.

Figure 5. NPM downloads (weekly)

npm weekly large

IDG

Figure 5.

The fact that leaps out in Figure 5 is that the actual active use of frameworks goes to ReactJS by a landslide. React has almost twice as many weekly downloads as the other two frameworks combined. It’s no surprise that React is the most in-use framework, but it’s notable just how significant its lead is.

Technical comparison

You’ve seen how the frameworks are conceptually similar, and had a look at their relative presence in the industry. Now let’s have a look at their technical aspects.

Angular

Angular 2+ was “designed from above.” That is, a bunch of smart people sat down and decided what would make for the ultimate front-end JavaScript framework.

In many ways, they succeeded: Angular is a very complete framework. On the other hand, Angular can feel overwhelming to learn and use the framework, as you are immediately required to master a large set of interacting elements (services, dependency injection, etc.) to achieve anything.

Angular is intended to incorporate everything you might need to develop large-scale front ends. In comparison, React relies upon community-developed plug-ins (for router support, for instance).

Ultimately, you as a developer are inside a code-thought-machine that wants you to conform to its ideals and conventions.

On the plus side, the wholesale adoption of ReactiveX (RxJS) across the board is innovative and forward-thinking. Not only does it mean all the event handling needs (intra-component, inter-component, back-end service calls, etc.) are managed via the same mechanism, but the same well-built framework (ReactiveX) and its learning will transfer to any other language you can imagine.

Moreover, large-scale projects with many team members may benefit from the more rigid and well-defined architectural style present in Angular.

There are varying opinions about the benefits and drawbacks of TypeScript, but you will code and read TypeScript if you use Angular. Another executive up-front decision.

Angular adopts ECMAScript classes wholesale. These classes use the built-in state as the component state. These are decorated with annotations to define their metadata.

Views in Angular are similar to views in Vue in that they are straight HTML templates with additional data-binding and logic support via inline directives.

Angular uses NgRX/store as its built-in, centralized state management plug-in.

Angular component example

Listing 2 displays a counter component similar to the React example, and is derived from this example.

@Component({
    selector: 'app',
    template: `
    <button (click)="increment()">Increment</button>
    <button (click)="decrement()">Decrement</button>
    <div></div>
    {{counter}}   
`
})
export class App {
    public counter : number = 0;

    increment(){
      this.counter += 1;
    }

    decrement(){
      this.counter -= 1;
    }
}

bootstrap(App, []);

Notice the @Component annotation. This is a “decorator” that informs Angular that the JavaScript class that follows is a component. Other features like services are handled in a similar fashion.

Also observe that the state is handled as a class member: public counter. This is a fairly clean way to build components atop JavaScript’s native syntax.

The interactive part of the component is added to the button elements via the (click) directive that is analagous to the DOM method onClick, but allows for calling methods on the component class. In this case it executes the increment and decrement methods.

Finally, the inline token {{counter}} allows for outputting the data-bound variable. This is slightly different from React’s syntax, but almost the same, and serves the same purpose.

React

React’s strength is that it has organically grown up from in-the-world use and has continued to develop in response to heavy usage. It has undergone extensive growth, but its roots and ongoing advantages reside in its being a framework used by Facebook for its own applications.

You can see Facebook’s committment to driving innovation in the framework with forward-looking features like Concurrent Mode (still in experimental mode at the time of writing).

React has also aggressively developed what is known as “pure” or functional components and hooks to empower them. These components avoid some of the overhead of class-based components. Vue has some support for functional components, and it is possible to create them in Angular, but React is the clear leader in this area.

Component definition and interactions are relatively straightforward in React, honoring the principle of least surprise.

As long as you avoid unnecessary Redux usage, the handling of React with a large-scale application is as good as Vue. Angular handles large code bases in a consistent manner and can offer benefits over React in this area. It is possible to define elegant large-scale apps in React, but the framework itself isn’t going to do as much as Angular to enforce that definition.

React uses an immutable state object accessible only via setState() to represent component state. This is different from Vue and Angular, which employ a more built-in JavaScript approach to state data.

React employs JSX for its view templates. JSX is an interesting approach in that it is like HTML with JavaScript superpowers (or JavaScript with HTML superpowers, if you prefer). JSX can be a bit off-putting when first learning the framework. It works quite well in the long run and is not difficult to learn if you arleady know HTML and JavaScript.

React’s default centralized data management is handled via Redux.

React component example

Listing 1 has a simple component example in React, derived from the React docs. This is a functional component, as that is the primary way to build components going forward.

import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Notice how the state is handled via the useState “hook.” This exposes the setCount() method to the template. The template is returned by the actual component function, and is written in JSX. JSX allows the inline integration of the JavaScript function into the onClick attribute of the button element, which interacts with the component state. The state is also accessed via the {count} token in the template markup.

Vue

Vue adopts a “normal JSON object as state” philosophy. Any time you can just use the language itself, it’s a win for simplicity. So you’ll find Vue simpler in this respect than React’s setState(), for example. However, there are edge cases and caveats that ultimately mean you are dealing with a native-JSON-hybrid beast.

In a sense, Vue is somewhere between Angular and React, a compromise between Angular’s top-down design and React’s organic growth.

Despite being the newest contender, and lacking the backing of a large corporation, Vue has kept pace with developments and delivers a fully viable framework. Also, there are a number of quality plug-ins and kits for Vue (like Quasar and Vuetify).

Vue has a reputation for being the easiest to learn. That probably derives from its JSON data model and HTML-with-decoration view definitions (versus React’s JSX). Vue templates can also incorporate inline JavaScript functions, unlike JSX.

Vue offers Vuex as its built-in, centralized state management solution.

Vue component example

Listing 3 shows a simple component definition in Vue, from the Vue docs.

// Define a new component called button-counter
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

In Listing 3, you can see that the component is exported as a CommonJS module. This is the Vue idiom for defining the component code. The template is identified as the template member.

Within the object that the module exports is the data member. This is a function that returns an object defining the component’s state.

Notice that the template allows for HTML with inline directives like v-on:click, similar to Angular’s (click) or React’s onClick. The syntax in Vue for outputting bound variables is the same as Angular: {{count}}.

Performance comparison

Performance can be tricky to get a handle on. This excellent article offers a data-based comparison of the three frameworks in three areas: DOM manipulation, load time, and memory allocation.

In the categories: Angular wins for DOM manipulation (in most cases); Vue wins for load times; React and Angular win for memory allocation.

In general, it’s not terribly valuable to make a performance-based decision among the frameworks. How you use them will make the biggest impact on performance.

Native support and server-side rendering

Although Vue and Angular also support to-native features and server-side rendering, React seems to be keeping well ahead in terms of the simplicity in using these. JSX has a good feel for me personally, in that it keeps related code and layout close together. Others have had a less happy experience with it. Overall, I count JSX as a positive for React.

Which framework to use?

The question as to which technology is best is impossible to say definitively. There are quantitative differences, but in the end it is a qualitative decision.

As with many technology choices, external factors can play a big role. In particular, your familiarity with the frameworks and that of your team will weigh heavily. Availability of developers who know the tech is also important, and in that arena, React is the clear winner. The React project also seems the most committed to offering forward-looking innovations.

Microsoft та Google вирішують проблеми сумісності браузерів

Posted Posted in Поради / рекомендації

Microsoft and Google are partnering to promote web browser compatibility around a number of CSS (Cascading Style Sheets) features, with an effort called #Compat2021.

Also involving open source software consulting firm Igalia and the broader web community, #Compat2021 aims to improve compatibility in five specific areas:

  • CSS Flexbox, a CSS module that defines a CSS box model optimized for user interface design and the layout of items in a single direction.
  • CSS Grid, for dividing a page into regions or defining the relationship in terms of layer, position, and size, between parts of a control built from HTML primitives.
  • CSS Position: sticky, or sticky positioning, which is akin to a hybrid of relative and fixed positioning.
  • CSS aspect-ratio property, pertaining to a CSS property setting a preferred aspect ratio for the box, to be used in the calculation of auto sizes and other layout functions.
  • CSS transforms, for rotating, scaling, skewing, or translating an element.

The joint working group involved in the project identified these focus areas based on the number of related bugs in each vendor’s tracking system, feature usage data, survey feedback, CanIUse data, and web-platform-tests test results.

While working group members will focus on their respective implementations, the Microsoft Edge team plans to contribute fixes to the Google-sponsored Chromium project to pass all CSS Grid tests in 2021 and to support improving interop across browsers.

#Compat21 was announced on March 22. Progress on the project can be tracked on the Compat 2021 dashboard.