Всё гораздо проще чем Вы думаете. Никакого контроллера делать не нужно у нас всё для этого предусмотрено.
Вам надо отловить событие когда пользователь меняет пункт выдачи. После чего сделать запрос на фронт контроллер:
/shop/controller/front/checkout.inc.php он же в качестве маршрута shop-front-checkout (смотрите файл handlers.inc.php в модуле shop)
Соответственно url для обращения будет /checkout/useract/
Там есть метод actionUserAct. Он позволяет вызвать пользовательский метод из Вашего класса доставки или оплаты. В Вашем случае доставки.
Он принимает несколько параметров:
1. module - Имя модуля (По умолчанию Shop, у Вам соответственно Ваше название папки модуля)
2. typeObj - (0 или 1) 0 - доставка (DeliveryType), 1 - оплата (PaymentType)
3. typeId - id доставки или оплаты
4. class - Класс для обращения, т.е. класс который будет вызван.
5. userAct - Статический метод который нужно вызвать
6. params - Дополнительные параметры для передачи в метод
Описание типов переменных и, то что они принимают можно посмотреть в самом файле я думаю проблем не возникнет.
Соответственно мы можем сформировать запрос через AJAX, вот пример кода для доставки axiomus:
var $_this = $(this);
$.ajax({
url : $_this.data('url'),
type : 'POST',
dataType : 'json',
data : {
module : 'Axiomus',
typeObj : 0, //Доставка
typeId : $_this.data('delivery-id'),
'class' : 'Axiomus',
userAct : 'getChangedDelivery',
params : {
order : { //Объект заказа
way : $_this.data('way'),
key : $_this.data('key'),
value : office
}
}
},
success : function(response){
if (response.success){
$(data.options.axiomusCostId + $_this.data('delivery-id')).html(response.data);
}
}
});
Мы в шаблоне добавляем там свой js который обслуживает обработку этих событий и следит за выбором пользователя.
{addjs file="%axiomus%/delivery/axiomus_widjet.js"}
Поэтому я дополнительно скину код javascript самого модуля доставки Axiomus. Он не решит Ваших всех проблем, но там можно подсмотреть реализацию.
(function( $ ){
$.AxiomusWidjetCreator = function( method ) {
//Найдём ближайший input c выбором
var closestRadio = $('input[name="delivery"]:eq(0)');
var form = closestRadio.closest('form'); //найдем форму
var defaults = {
axiomusDiv : '.axiomusDeliveryBlock', //Контейнер куда будет вставлятся информация Axiomus
axiomusAdress : '.axiomusAdress', //Куда вставляется адрес
axiomusSchedule : '.axiomusSchedule', //Блок с расписанием работы
axiomusCostId : '#scost_' //Идентификатор блока с ценой за доставку
},
$this = form,
data = $this.data('axiomusInfo');
if (!$this.length) return;
if (!data) { //Инициализация
data = { options: defaults };
$this.data('axiomusInfo', data);
}
//public
var methods = {
/**
* Инициализация плагина
*
* @param initoptions - введённые пераметра для записи или перезаписи
*/
init: function(initoptions)
{
data.options = $.extend(data.options, initoptions);
//Навесим все события
presetAxiomusRadioEvents();
//Если контент обновился (для заказа на одной странице)
$('body').on('new-content',function(){
//Навесим события на переключатели
presetAxiomusRadioEvents();
//Проверим выбор sheepla и если она выбрана, то вызовем соответсвующий метод
var selectedCheckbox = $('input[name="delivery"]:checked');
if (typeof(selectedCheckbox.data('axiomus-div-id'))!='undefined'){
// setOrClearAxiomusInfo(null, selectedCheckbox);
}
});
},
/**
* Открывает доступность Axiomus для выбора
*
* @param checkBoxObj - объект с функциями Axiomus
*/
showAxiomus : function (checkBoxObj)
{
var parent = checkBoxObj.data('axiomus-div-id');
$("select",$(parent)).prop('disabled',false).change();
},
/**
* Убирает доступность Axiomus для выбора из всех вариантов
* и скрывает поля
*
*/
clearAxiomus : function ()
{
$(data.options.axiomusDiv+" select").prop('disabled',true);
}
}
//private
/**
* Срабатывает при нажатии на выбранную доставку.
* Если у этой доставки есть признак что если есть признак, что это Axiomus,
* то ничего не делаем. Если нет признака, что подгружалось,
*
*/
var setOrClearAxiomusInfo = function (Event, item)
{
if (Event === null){ //Если вызвали программно
var $_this = item;
}else{ //Если событие
var $_this = $(this);
}
var dataAxiomusDiv = $_this.data('axiomus-div-id');
if ( typeof(dataAxiomusDiv) != 'undefined' ) { //Если это радиокнопка Axiomus
methods.showAxiomus($_this); //Стартуем
}else{
methods.clearAxiomus(); //Очищаем
}
},
/**
* Устанавливает события для обработки
*/
presetAxiomusRadioEvents = function()
{
//Смена адреса доставки в выпадающем списке
$(data.options.axiomusDiv+" select",$this).off('change.axiomus').on('change.axiomus', changeAxiomusAdress);
$(data.options.axiomusDiv+" input[type='radio']", $this).off('change.axiomusradio').on('change.axiomusradio', changeAxiomusRadio);
//Пройдёмся по контейнерам СДЕК
$(data.options.axiomusDiv,$this).each(function(i){
//Найдём и отметим подходящие радиокнопки, которые относятся к СДЕК
var deliveryId = $(this).data('delivery-id');
var radio = $('input[name="delivery"][value="'+deliveryId+'"]');
//Перенесём данные к выборанной радио кнопке, чтобы можно было манипулировать
radio.data('axiomus-div-id',"#"+$(this).attr('id'));
if (radio.prop('checked')){
$("select", $(radio.data('axiomus-div-id'))).prop('disabled',false).change();
}
});
//Получим все радио кнопки
var radioboxes = $('input[type="radio"][name="delivery"]',$this); //найдем radio
//Навесим переключение радиокнопок
radioboxes.each(function(){
$(this).off('click.axiomus').on('click.axiomus', setOrClearAxiomusInfo);
});
$(data.options.axiomusDiv+" input[type='radio']:checked", $this).trigger('change.axiomusradio');
},
/**
* Смена адреса доставки в выпадающем списке
*
*/
changeAxiomusAdress = function()
{
var parent = $(this).closest(data.options.axiomusDiv);
var info = $("option:selected",$(this)).data('info');
if (typeof(info.address)!='undefined'){
$(data.options.axiomusAdress, $(parent)).html("Адрес: "+info.address);
}
if (typeof(info.schedule)!='undefined'){
$(data.options.axiomusSchedule, $(parent)).html(info.schedule);
}
var office = $(this).val();
var $_this = $(this);
$.ajax({
url : $_this.data('url'),
type : 'POST',
dataType : 'json',
data : {
module : 'Axiomus',
typeObj : 0,
typeId : $_this.data('delivery-id'),
'class' : 'Axiomus',
userAct : 'getChangedDelivery',
params : {
order : { //Объект заказа
way : $_this.data('way'),
key : $_this.data('key'),
value : office
}
}
},
success : function(response){
if (response.success){
$(data.options.axiomusCostId + $_this.data('delivery-id')).html(response.data);
}
}
})
},
/**
* Смена переключателя типа забора для DPD
*
*/
changeAxiomusRadio = function ()
{
var parent = $(this).closest(data.options.axiomusDiv);
var val = $(this).val();
if (val=="1"){
$("select", parent).prop('disabled', false);
}else{
$("select", parent).prop('disabled', true);
}
}
if ( methods[method] ) {
methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
}
}
})( jQuery );
$(document).ready(function(){
$.AxiomusWidjetCreator();
});
Послав запрос система сделает обращение к публичному статическому метод (public static function) Вашей доставки. В который передадутся несколько параметров. Например для случая с Axiomus и методом getChangedDelivery:
\Axiomus\Model\Deliverytype\Axiomus::getChangedDelivery($order - объект заказа, $delivery_id - id доставки, $params - Ваши дополнительные параметры, которые Вы передадите)
Теперь, что касается заказа. Заказ во время его оформления находится в сессии постоянно, поэтому Вы можете в него записывать "на лету" сразу и данные сохранятся, просто присвоив нужные значения не вызывая при этом insert или update. Эти методы системе понадобятся только один раз при создании самого заказа, когда пользователь подтвердил его создание.
Мы для записи данных рекомендуем использовать метод addExtraKeyPair у объекта заказа.
$order->addExtraKeyPair('ключ по которому можно достать данные', 'Значение для записи можно массив');
А потом доставать данные с помощью:
$order->getExtraKeyPair('ключ по которому можно достать данные');
Т.к. в таком случае эти данные можно будет достать и после физической записи заказа.
У заказа также есть метод addExtraInfoLine он позволит не только записать данные в заказ, но и инфомация будет доступна для отображения в админке при редактировании товара.