Это очень интересный вопрос. Я думаю, что вы получаете много отрицательных голосов и критику, потому что это трудный вопрос, но не потому, что это плохой вопрос. По сути, вы хотите создать позицию в корзине и позицию в заказе непосредственно из данных, введенных в форму. Я знаю, что это можно сделать, потому что я сделал нечто очень похожее. Сложность состоит в том, что API для WC_Cart требуется объект WC_Product для создания позиций. Я обошел это, предоставив объект прокси-продукта для работы с WC_Cart. Обычно свойства объекта продукта заполняются из данных в базе данных, но я использовал действия и фильтры для заполнения свойств прокси-объекта. Поскольку счет формируется из заказа, делать нечего, поскольку позиция теперь существует в заказе. Для меня это решение потребовало значительного количества продвинутого кода, т. Е. Потребовало много времени и усилий и глубоких знаний WooCommerce.
Теперь для моей напыщенной речи. Это очень уродливое решение, и оно не будет необходимым, если WooCommerce будет реализован по-другому. WooCoomerce (и WordPress) в основном используют действия и фильтры для изменения поведения кода по умолчанию. Но в объектно-ориентированном программировании классы расширены для изменения поведения класса по умолчанию. Например, класс WC_Cart имеет метод:
public function add_to_cart( $product_id = 0, $quantity = 1, $variation_id = 0, $variation = array(), $cart_item_data = array() )
, где должны быть действительными либо $ product_id, либо $ var_id. В идеале вы должны расширить класс WC_Cart с помощью новой функции add_to_cart (), которая может создавать позиции только из $ cart_item_data. Однако вы не можете расширить класс WC_Cart, поскольку корзина создается в классе WooCommerce следующим образом:
public function initialize_cart() {
...
$this->cart = new WC_Cart();
...
}
И наоборот, использование класса WC_Order реализовано так, что его можно расширять, поскольку объекты заказов создаются factory:
class WC_Order_Factory {
public static function get_order( $order_id = false ) {
...
// Filter classname so that the class can be overridden if extended.
$classname = apply_filters( 'woocommerce_order_class', $classname, $order_type, $order_id );
return new $classname( $order_id );
}
}
Таким образом, вы можете использовать фильтр 'woocommerce_order_class' для расширения класса WC_Order.