Woocommerce Почта РФ плагин фиксированная стоимость.

307

Есть плагин https://wordpress.org/support/plugin/russian-post-and-ems-for-woocommerce/.
У автора нет функционала фиксированной цены. По крайней мере на данный момент. Хотя в аналогичном сдек плагине это реализовано.

Как указано в топике самим автором https://wordpress.org/support/topic/фиксированная-стоимость-доставки/ можно сделать через фильтр.

add_filter( 'woocommerce_package_rates', 'override_ups_rates' );
function override_ups_rates( $rates ) {
    foreach( $rates as $rate_key => $rate ){
        // Check if the shipping method ID is UPS
        if( ($rate->method_id == 'rpaefw_post_calc') ) {
            // Set cost to zero
            $rates[$rate_key]->cost = 350;

        }
    }
    return $rates;
}

0
 

Woocommerce EKOM ошибка.

288

Почта России. Ошибка запроса для»price». CODE: 400 {«version_api»:2,»version»:»2.11.4.664″,»caption»:»Расчет тарифов»,»id»:53030,»name»:»ЕКОМ обыкновенный»,»mailtype»:53,»mailctg»:3,»directctg»:1,»from»:197022,»to»:919561,»weight»:100,»date»:20220701,»time»:230000,»postoffice»:[{«index»:197022,»tp»:1,»type»:3,»typei»:1,»name»:»САНКТ-ПЕТЕРБУРГ 22″,»regionid»:78,»regiono»:40000000,»region-main»:1,»area-main»:1,»placeid»:11102,»placeo»:40000000,»parent»:197000,»root»:190700,»courier»:190880,»pvz»:1,»item-check-view»:1,»move»:1,»weight-max»:20000,»pack-max»:99,»box»:190900},{«index»:919561,»tp»:2,»type»:16,»typei»:4,»name»:»РЯЗАНЬ-ПОЧТОМАТ (АПС)»,»regionid»:62,»regiono»:61701000001,»region-main»:1,»area-main»:1,»placeid»:17796,»placeo»:61701000001,»parent»:390700,»root»:390700,»partner»:1,»move»:1,»weight-max»:30000,»pay-card»:1,»rent»:1}],»errors»:[{«msg»:»ЕКОМ обыкновенный. Плата за доставку ЕКОМ (2635). ЕКОМ нельзя принять в 197022 \»САНКТ-ПЕТЕРБУРГ 22\». (1.11).»,»type»:1,»code»:2004}],»place»:»C5-r00-1″}

Сам задал сам отвечу)

Так понял, что указал ОПС который не поддерживает EKOM.
Соотв нужно указать тот, в котором есть.

0
 

Woocommerce шпараглка по корзине. Get cart data

280

Еще одна шпаргалочка, только уже по корзине

// $cart conditionals (if)
 WC()->cart->is_empty()
 WC()->cart->needs_payment()
 WC()->cart->show_shipping()
 WC()->cart->needs_shipping()
 WC()->cart->needs_shipping_address()
 WC()->cart->display_prices_including_tax()
 // Get $cart totals
 WC()->cart->get_cart_contents_count();
 WC()->cart->get_cart_subtotal();
 WC()->cart->subtotal_ex_tax;
 WC()->cart->subtotal;
 WC()->cart->get_displayed_subtotal();
 WC()->cart->get_taxes_total();
 WC()->cart->get_shipping_total();
 WC()->cart->get_coupons();
 WC()->cart->get_coupon_discount_amount( 'coupon_code' );
 WC()->cart->get_fees();
 WC()->cart->get_discount_total();
 WC()->cart->get_total();
 WC()->cart->total;
 WC()->cart->get_tax_totals();
 WC()->cart->get_cart_contents_tax();
 WC()->cart->get_fee_tax();
 WC()->cart->get_discount_tax();
 WC()->cart->get_shipping_total();
 WC()->cart->get_shipping_taxes();
 // Loop over $cart items
 foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
    $product = $cart_item['data'];
    $product_id = $cart_item['product_id'];
    $quantity = $cart_item['quantity'];
    $price = WC()->cart->get_product_price( $product );
    $subtotal = WC()->cart->get_product_subtotal( $product, $cart_item['quantity'] );
    $link = $product->get_permalink( $cart_item );
    // Anything related to $product, check $product tutorial
    $attributes = $product->get_attributes();
    $whatever_attribute = $product->get_attribute( 'whatever' );
    $whatever_attribute_tax = $product->get_attribute( 'pa_whatever' );
    $any_attribute = $cart_item['variation']['attribute_whatever'];
    $meta = wc_get_formatted_cart_item_data( $cart_item );
 }
 // Get $cart customer billing / shipping
 WC()->cart->get_customer()->get_billing_first_name();
 WC()->cart->get_customer()->get_billing_last_name();
 WC()->cart->get_customer()->get_billing_company();
 WC()->cart->get_customer()->get_billing_email();
 WC()->cart->get_customer()->get_billing_phone();
 WC()->cart->get_customer()->get_billing_country();
 WC()->cart->get_customer()->get_billing_state();
 WC()->cart->get_customer()->get_billing_postcode();
 WC()->cart->get_customer()->get_billing_city();
 WC()->cart->get_customer()->get_billing_address();
 WC()->cart->get_customer()->get_billing_address_2();
 WC()->cart->get_customer()->get_shipping_first_name();
 WC()->cart->get_customer()->get_shipping_last_name();
 WC()->cart->get_customer()->get_shipping_company();
 WC()->cart->get_customer()->get_shipping_country();
 WC()->cart->get_customer()->get_shipping_state();
 WC()->cart->get_customer()->get_shipping_postcode();
 WC()->cart->get_customer()->get_shipping_city();
 WC()->cart->get_customer()->get_shipping_address();
 WC()->cart->get_customer()->get_shipping_address_2();
 // Other stuff
 WC()->cart->get_cross_sells();
 WC()->cart->get_cart_item_tax_classes_for_shipping();
 WC()->cart->get_cart_hash();
 WC()->cart->get_customer();
0
 

Woocommerce шпаргалка по Orders. Get orders data.

273

В некоторых задачах требуется получить объект заказа.
Вот некоторая шпаргалка.

// Get Order ID and Key
 $order->get_id();
 $order->get_order_key();
 // Get Order Totals $0.00
 $order->get_formatted_order_total();
 $order->get_cart_tax();
 $order->get_currency();
 $order->get_discount_tax();
 $order->get_discount_to_display();
 $order->get_discount_total();
 $order->get_fees();
 $order->get_formatted_line_subtotal();
 $order->get_shipping_tax();
 $order->get_shipping_total();
 $order->get_subtotal();
 $order->get_subtotal_to_display();
 $order->get_tax_location();
 $order->get_tax_totals();
 $order->get_taxes();
 $order->get_total();
 $order->get_total_discount();
 $order->get_total_tax();
 $order->get_total_refunded();
 $order->get_total_tax_refunded();
 $order->get_total_shipping_refunded();
 $order->get_item_count_refunded();
 $order->get_total_qty_refunded();
 $order->get_qty_refunded_for_item();
 $order->get_total_refunded_for_item();
 $order->get_tax_refunded_for_item();
 $order->get_total_tax_refunded_by_rate_id();
 $order->get_remaining_refund_amount();
 // Get and Loop Over Order Items
 foreach ( $order->get_items() as $item_id => $item ) {
    $product_id = $item->get_product_id();
    $variation_id = $item->get_variation_id();
    $product = $item->get_product();
    $product_name = $item->get_name();
    $quantity = $item->get_quantity();
    $subtotal = $item->get_subtotal();
    $total = $item->get_total();
    $tax = $item->get_subtotal_tax();
    $taxclass = $item->get_tax_class();
    $taxstat = $item->get_tax_status();
    $allmeta = $item->get_meta_data();
    $somemeta = $item->get_meta( '_whatever', true );
    $product_type = $item->get_type();
 }
 // Other Secondary Items Stuff
 $order->get_items_key();
 $order->get_items_tax_classes();
 $order->get_item_count();
 $order->get_item_total();
 $order->get_downloadable_items();
 $order->get_coupon_codes();
 // Get Order Lines
 $order->get_line_subtotal();
 $order->get_line_tax();
 $order->get_line_total();
 // Get Order Shipping
 $order->get_shipping_method();
 $order->get_shipping_methods();
 $order->get_shipping_to_display();
 // Get Order Dates
 $order->get_date_created();
 $order->get_date_modified();
 $order->get_date_completed();
 $order->get_date_paid();
 // Get Order User, Billing & Shipping Addresses
 $order->get_customer_id();
 $order->get_user_id();
 $order->get_user();
 $order->get_customer_ip_address();
 $order->get_customer_user_agent();
 $order->get_created_via();
 $order->get_customer_note();
 $order->get_address_prop();
 $order->get_billing_first_name();
 $order->get_billing_last_name();
 $order->get_billing_company();
 $order->get_billing_address_1();
 $order->get_billing_address_2();
 $order->get_billing_city();
 $order->get_billing_state();
 $order->get_billing_postcode();
 $order->get_billing_country();
 $order->get_billing_email();
 $order->get_billing_phone();
 $order->get_shipping_first_name();
 $order->get_shipping_last_name();
 $order->get_shipping_company();
 $order->get_shipping_address_1();
 $order->get_shipping_address_2();
 $order->get_shipping_city();
 $order->get_shipping_state();
 $order->get_shipping_postcode();
 $order->get_shipping_country();
 $order->get_address();
 $order->get_shipping_address_map_url();
 $order->get_formatted_billing_full_name();
 $order->get_formatted_shipping_full_name();
 $order->get_formatted_billing_address();
 $order->get_formatted_shipping_address();
 // Get Order Payment Details
 $order->get_payment_method();
 $order->get_payment_method_title();
 $order->get_transaction_id();
 // Get Order URLs
 $order->get_checkout_payment_url();
 $order->get_checkout_order_received_url();
 $order->get_cancel_order_url();
 $order->get_cancel_order_url_raw();
 $order->get_cancel_endpoint();
 $order->get_view_order_url();
 $order->get_edit_order_url();
 // Get Order Status
 $order->get_status();
 // Get Thank You Page URL
 $order->get_checkout_order_received_url();
0
 

October CMS простая сортировка. (simple sortable)

283

Я коснусь только простой сортировки, пока что. Довольно хороший гайд есть на форуме октобера https://octoclub.ru/d/21-sortable-simple-tree-nested-tree. Я опишу чуть детальней.

Например есть тестовый проект. В нем «магазин с товарами».

Я буду описывать кейс, когда уже есть лист продуктов. И только потом решили добавить сортировку. Это отличается тем, что у моих продуктов отсутствует ReorderController. При создании новой сущности, указываете, чтобы он был доступен.

При указании данного параметра создадутся вьюшка и некоторые настройки контроллера. У меня этого нет, поэтому буду делать вручную, заодно детальней.

Сначала указываю настройки reorder в контроллере, подключаю Behaivor и файл yaml.

<?php namespace Alex\Store\Controllers;use Backend\Classes\Controller;
use BackendMenu;class Prod extends Controller
{
    public $implement = [
        'Backend\Behaviors\ListController',
        'Backend\Behaviors\FormController',
        'Backend\Behaviors\ReorderController',   // добавил
    ];
    
    public $listConfig = 'config_list.yaml';
    public $formConfig = 'config_form.yaml';
    public $reorderConfig = 'config_reorder.yaml';  // добавил    public function __construct()
    {
        parent::__construct();
        BackendMenu::setContext('Alex.Store', 'main-menu-item');
    }
}

Далее вставляю config_reorder.yaml в папке /controllers/prod. Соотв указываю заголовок, модель. NameForm скажу чуть позже для чего.

title: 'Сортировка продуктов'                 
modelClass: Alex\Store\Models\Prod
nameFrom: title
toolbar:
    buttons: reorder_toolbar

Добавляем собственно вьюшку reorder.htm в туже папку с нашим контроллером /controllers/prod, так как сортировка происходит на отдельной странице.

<?php Block::put('breadcrumb') ?>
    <ul>
        <li><a href="<?= Backend::url('alex/store/prod/reorder') ?>">Category</a></li>
        <li><?= e($this->pageTitle) ?></li>
    </ul>
<?php Block::endPut() ?><?= $this->reorderRender() ?>

Далее в list tool bar добавляем кнопку на вьюшку.

<a href="<?= Backend::url('alex/store/prod/reorder') ?>" class="btn btn-default oc-icon-list"><?= e(trans('backend::lang.reorder.default_title')) ?></a>

Так отлично. Появилась кнопка а админке.

Собственно этой всей настройки можно было избежать и октобер бы сам сгенерировал как надо, при указании галочки ReorderBehavior, о чем говорил в самом начале.

Кнопка появилась, но при переходе с нее возникает ошибка, говорящая о том, что мы еще не добавили в модель Трейт сортировки.

Добавляем в нашу модель.

use \October\Rain\Database\Traits\Sortable; // Для Sortable

И далее, чтобы этот трейт корректно отрабатывал нашей моделе и соотв таблице нужно поле sort_order. Добавляем его. Тип число, nullable true.

Отлично. Заходим в сортировку. И лично у меня это выглядит так. Есть итемы, но они пустые. Это собственно поле nameForm, которое указывается в config_reorder.yaml. У меня было написано title, хотя исходя из моей таблицы нужно указать name.

Указал name. Результат

!Есть один нюанс. Он касается поля sort_order. В идеале это все делать на новой сущности. Но если мы редактируем существующую, то у поля sort_order будет стоять 0 или Null в таблице. Как было подмечено в статье https://octoclub.ru/d/21-sortable-simple-tree-nested-tree надо в ручном режиме проставить валидные значения для текущих итемов.

В моем случае все не сложно и выглядит так.

Отлично. Все почти готово. Для примера я хочу выделить классный Сыр и поставить его первым. При стандартном получении из модели, сортировка происходит автоматически.

// это из компонента Prod
public function init()
{
    $this->items =  ProdModel::get();
}

Результат

Если же вы получаете итемы другими способами, то может указать дополнительно orderBy по полю sort_order.

0
 

October CMS перевод сайта. (Translate site). Часть 2

343

В первой части обсудили постановку задачи. Я привел источники, на которые можно опираться, обсудили что нам потребуется и так же сделали простой перевод статических частей сайта.
Теперь перейдем к более нетривиальной задаче.

Перевод кастомных компонентов и данных из моделей

Давайте установим Билдер, чтобы сделать небольшой плагин. https://octobercms.com/plugin/rainlab-builder

В нашей демо версии создадим мини каталог-магазин.

Не будем заморачиваться, добавим простые поля товара. Нам этого хватит.


Отлично. Уж извините 🙂 ничего быстрее не придумал, но буду продавать картошку и помидоры и еще что-нибудь. НО! интернационально на всех языках. Поэтому это круто.
Сделал пару товаров.

Добавлю компонентик с помощью которого выведу информацию на фронтенд.
Код:

<?php
namespace Alex\Store\Components;

use Cms\Classes\ComponentBase;
use Alex\Store\Models\Prod as ProdModel;


class Prod extends ComponentBase
{

    public $items;

    public function init()
    {
        
    }

    public function onRun()
    {

    }

    public function componentDetails()
    {
        return [
            'name' => 'Products',
            'description' => 'Some Products'
        ];
    }

    public function defineProperties()
    {
        return [
        ];
    }

}

Регистрируем компонент и выводим.

Plugin.php

<?php namespace Alex\Store;

use System\Classes\PluginBase;

class Plugin extends PluginBase
{
    public function registerComponents()
    { 
        return [
        'Alex\Store\Components\Prod' => 'prods'
        ];
    }

    public function registerSettings()
    {
    }
}

Шаблон:

title = "Store"
url = "/store"
layout = "default"

[prods]
==
<div class="jumbotron">
    <div class="container">
        {% component 'contenteditor' file="lang/home/store" class='' fixture='div'%}
    </div>
</div>

<div class="container">
    <div class="prods">
        {% for prod in prods.items %}
        <div class="prod">
            <div class="name">{{prod.name}}</div>
            <div class="descr">{{prod.descr}}</div>
            <div class="price">{{prod.price}}</div>
        </div>
        {% endfor %}
    </div>
</div>

И пока что как мы видим появилась страничка. Продукты еще не вывелись. Давайте их перекинем с бэка.

public function onRun()
{
    $this->items =  ProdModel::get();
}

Как то так.

Все хорошо. Только продукты я вывел на русском. Хотя мы договорились, что дефолтный язык будет английским. Это я поправлю. Теперь надо подумать как локализовать данные из компонента.
Точнее как локализовать модель. Изначально я делал не столь гибко, тк не до конца разобрался. Я пошел по пути дополнения полей в модель. Это раздуло таблицу и к тому же вышло не гибко. У меня был случай на 2 языка. А что если их будет 2-5 десять?

Поэтому у RainlabTranslate реализован более гибкий подход. Мы будем использовать трейт для имплементации функционала перевода.


class Prod extends Model
{
    use \October\Rain\Database\Traits\Validation;

    public $implement = ['RainLab.Translate.Behaviors.TranslatableModel'];
    public $translatable = ['name','descr'];

Добавили трейт и указали поля для перевода. В итоге получили дефолтный функционал.

И при этом наша таблица осталась с теми же полями, но добавилась отдельная таблица Rainlab с атрибутами.

Отлично. Теперь под дефолтной локалью, кою я поменял на En выводятся товары на английском, под ru соответственно на русском.

Стоит добавить локализацию для валюты и цены. Тогда будет совсем ок.

Что ж таким образом можно переводить контент из моделей для любых кастомных плагинов.
Узкие места и нюансы, я возможно допишу позже.

0
 

October CMS перевод сайта. (Translate site). Часть 1

429

В данной статье я опишу мой подход к локализации сайта, который я довольно успешно применил.
Я просмотрел практически всю информацию на данную тему и преобразовал ее под свои нужды.
Мой подход далеко не идеальный, поэтому делитесь замечаниями и вариантами доработок, возможно мы улучшим статью.

Данный гайд основывается на версии 1, но думаю и для второй будет актуален.

Вот список на который я опирался:
https://medium.com/@octobercms/building-responsive-multi-language-website-with-blog-and-static-pages-using-october-cms-94151610f1ff
https://habr.com/ru/post/305802/
https://medium.com/@octobercms/building-responsive-multi-language-website-with-blog-and-static-pages-using-october-cms-part-2-63ba31243f6a

В списке выше есть источник тут и тут, который прекрасно описывает как локализовать сайт, если используются стандартные плагины RainlabBlog и RainlabStaticPages.
Я же буду говорить о примере, когда данные плагины практически не используются и сайт делается на своих компонентах, что я наблюдаю гораздо чаще.

Постановка задачи

  • локализация статического контента
  • локализация динамического контента в плагинах и компонентах
  • локализация интерфейса (меню, футер, функциональные элементы)
  • локализация ссылок

Что нам понадобиться

В моем случае я использовал смежный функционал двух плагинов: RainlabTranslate и ContentEditor.
Далее я объясню как их использовать и для чего каждый.

Локализация статики

Я буду показывать на demo теме октября. Ее переводом мы и займемся.

Локализации статики — это самое простое. Для этого я использовал ContentEditor. Во первых это удобно для клиента, а во вторых он замечательно расширяется RainlabTranslate.

После установки переходим в настройку Транслейта и устанавливаем языки. Их название и локали.

Я добавил русский и сделал его по умолчанию.

Отлично. Теперь у нас доступен режим подраздела для наших локалей.
Можем перейти и попробовать: http://localhost:8888/ru и http://localhost:8888/en. Пока что никаких изменений.

Теперь задаем контент эдитор. Суть плагина в том, что мы оборачиваем контент в паршил, которые хранятся в директории контента themes/demo/content. Расширение транслейта происходит за счет того, что у нас создаются поддиректории для каждого языка автоматом.

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

{% component 'contenteditor' file="lang/home/numbers" class='' fixture='div'%}

Создаем директорию themes/demo/content/lang. И так же в главном layout обяъявляем компонент контент эдитора — [contenteditor]

И далее для примера переведем кусок контента на главной. Перенесем контент блок wellcome.htm в lang и импортируем в виде паршила контент эдитора.

В таком виде:

title = "Demonstration"
url = "/"
layout = "default"

==
<div class="jumbotron">
    <div class="container">
        {% component 'contenteditor' file="lang/home/welcome" class='' fixture='div'%}
    </div>
</div>

Отлично у нас появилась кнопка редактирования и область контента стала подсвеченной.

Теперь можем отредактировать контент под разными локалями http://localhost:8888/ru и http://localhost:8888/en. Кстати я передумал 🙂 основной язык все таки будет английский а переводить будем на русский. Поэтому на локаль en оставляем без изменений, а на локали ru переводим.
Как то так.

Таким же способом можно перевести и другие блоки достаточно внезависимости от сложности верстки. Тоже самое касается других страниц.
При этом если мы посмотрим на директорию контент, то увидим rulang папку. Так же будет и с остальными языками.

Плюсы:
— удобно для пользователя
— игнорируется сложность верстки
— редактирование любых страниц без использования StaticPages плагина
— сколько угодно языков

Минусы
— шаблон дробится на вставки из контент эдитора, что усложняет поиск элементов.

Дальнейший перевод рассмотрим в следующих частях.

0
 

October CMS добавляем экшн в контроллер лист (Controller list action)

415

Есть список, в моем случае например товаров. Необходимо добавить какое-либо действие для обработки списка. Мне было необхдимо сделать функционал клонирования товара.

Мы идем в директорию с плагином и собственно с контроллером, который модифицируем.
У меня для примера /alex/catalog/controllers/Products.php
Так же нам понадобиться шаблон тулбара.

Тут уже кнопка у меня добавлена. Изначально шаблон был без нее.
Шаблон находим /alex/catalog/controllers/products/_list_toolbar.htm

Сам шаблон

<div data-control="toolbar">
    <a href="<?= Backend::url('webfamily/catalog/products/create') ?>"
       class="btn btn-primary oc-icon-plus"><?= e(trans('backend::lang.form.create')) ?></a>
    <button
            class="btn btn-default oc-icon-trash-o"
            disabled="disabled"
            onclick="$(this).data('request-data', {
            checked: $('.control-list').listWidget('getChecked')
        })"
            data-request="onDelete"
            data-request-confirm="<?= e(trans('backend::lang.list.delete_selected_confirm')) ?>"
            data-trigger-action="enable"
            data-trigger=".control-list input[type=checkbox]"
            data-trigger-condition="checked"
            data-request-success="$(this).prop('disabled', true)"
            data-stripe-load-indicator>
        <?= e(trans('backend::lang.list.delete_selected')) ?>
    </button>


    <button
            class="btn btn-primary oc-icon-copy"
            onclick="$(this).data('request-data', {
            checked: $('.control-list').listWidget('getChecked')
        })"
            data-request="onCopy"

    >Скопировать
    </button>
    <a href="<?= Backend::url('webfamily/catalog/products/import') ?>"
       class="btn btn-primary"><?= e(trans('webfamily.catalog::lang.common.import')) ?></a>
</div>

Как видно в шаблоны указаны все кнопки в том числе и новую мной созданную «Скопировать». На нее ставим data-request=«Ваш обработчик» и фунцкию onclick, я взял с копки удаления. Суть js забирать id-ники чекнутых итемов и передавать их на экшн.

Идем далее. Возвращаемся к контроллеру и прописываем обработчик.

/**
     * @return
     * Копирование товара
     */
    public function onCopy() {
        // Проверка на чекнутые товары
        if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) {
            // Первый чекнутый // Делаем действия либо с одним
            //  $copy_id = post("checked")[0];
            // Либо делаем действие со списком ID
              foreach ($checkedIds as $checkedId) {
                 // Делаем дела ........... 
             }       
            Flash::success('Товар скопирован');
        }
        return $this->listRefresh();
    }

Я обрабатывал только первый чекнутый. То есть у меня он в принципе должен быть выбрать один. Вы можете обработать несколько. На выходе я вывожу Флэш сообщение и перезагружаю список.
Собственно все.

0
 

Octber CMS Builder установка поля загрузки картинки

378

Когда я делал поля как обычно используя Page Builder, я наткнулся на ошибку: Model Alexdzen\Content\Models\Brands’ does not contain a definition for ‘image’.

Спросил в чате, оказалось, что добавления поля картинки не столь очевидно как хотелось бы.

Наше значение не указывается в таблице как поле.

Допустим моя задача сделать галлерею. Таблица состоит из Id и Image. Image — не указываем в таблице. Мы идем в нашу модель, в моем случае это Brands.php и прописываем поле image через attachOne (или attachMany).

<?php namespace Alexdzen\Content\Models;

use Model;

/**
 * Model
 */
class Brands extends Model
{
    use \October\Rain\Database\Traits\Validation;
    
    /*
     * Disable timestamps by default.
     * Remove this line if timestamps are defined in the database table.
     */
    public $timestamps = false;


    /**
     * @var string The database table used by the model.
     */
    public $table = 'alexdzen_content_brands';

    /**
     * @var array Validation rules
     */
    public $rules = [
        'image' => 'required',
    ];

    public $attributeNames = [
        'image' => 'Картинка',
    ];

    public $attachOne = [
        'image' => 'System\Models\File'
    ];
}

Соответсвенно в form.yml указываем наше поле из модели.

Ну и чтобы картинка отображался в на странице Контроллера прописываем image. Значение поля я ставлю partial и путь указываю $/alexdzen/content/partials/_image3.htm.

Код паршила

<?php if($value): ?>
    <img src="<?php echo $value->path; ?>" style="max-width: 300px; max-height: 150px;">
<?php endif; ?>

И соответсвенно получаю результат.

0
 

October CMS как переопределить(заоверрайдить) методы Rain Lab Users. (Override Rain Lab)

422

Допустим у вас появилась задача похожую на мою. Мне было необходимо подделать метод onActivate.
Соответсвенно, если мы сделаем это напрямую в плагине в классе Account, то через последующее обновление наши изменения сотрутся.

Поэтому мы идем следующем путем.

У нас есть компонент login.htm. Изначально он использует компонент Account.php Rainlab.

title = "Вход"
url = "/login"
layout = "default"

[account]
forceSecure = 0
==
<main class="page__main">
     {% partial 'user_account/singin' %}
</main>

Допустим у вас Плагин Myplugin. В нем мы создадим свой Аккаунт компонент и отнаследуем от Rainlab.

<?php namespace Alexti\Myplugin\Components;

class Account2 extends \RainLab\User\Components\Account
{
    public function componentDetails()
    {
        return [
            'name' => 'Account2',
            'description' => 'Account2'
        ];
    }

    /**
     * Activate the user
     * @param string $code Activation code
     */
    public function onActivate($code = null)
    {
       // do something
    }
}

Соответсвенно наш компонент надо зарегистрировать в Plugin.php

public function registerComponents()
{
    return [
        'Alexti\Myplugin\Components\Account2' => 'Account2',
   ]
}


Все готово. Теперь Account будет отрабатывать как обычно, но методы которые мы заоверайдили будут отрабатывать в нашем компоненте. И соответсвенно по всех шаблонах необходимо подключить наш компонент.

title = "Вход"
url = "/login"
layout = "default"

[Account2]
forceSecure = 0
==
<main class="page__main">
     {% partial 'user_account/singin' %}
</main>
0