Woocommerce Adding Multiple shipping methods - wordpress

I used the code below (as provided by woocommerce API) to add custom Shipping Method and it is working but now I want to add another shipping method I tried copy pasting same code with different class name but it doesn't work actually the second method is replacing the first one
I want to know how can I create another Shipping method?
Thank you
function your_shipping_method_init() {
if ( ! class_exists( 'WC_Your_Shipping_Method' ) ) {
class WC_Your_Shipping_Method extends WC_Shipping_Method {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
public function __construct() {
$this->id = 'vip_rate'; // Id for your shipping method. Should be uunique.
$this->method_title = __( 'VIP Shipping Rate' ); // Title shown in admin
$this->method_description = __( '$35 flate rate' ); // Description shown in admin
$this->enabled = "yes"; // This can be added as an setting but for this example its forced enabled
$this->title = "VIP Shipping rate"; // This can be added as an setting but for this example its forced.
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
$this->init_settings(); // This is part of the settings API. Loads settings you previously init.
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* calculate_shipping function.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping( $package ) {
$cost=35;
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => round($cost,2),
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate( $rate );
}
}
}
}
add_action( 'woocommerce_shipping_init', 'your_shipping_method_init' );
function add_your_shipping_method( $methods ) {
$methods[] = 'WC_Your_Shipping_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'add_your_shipping_method' );

I'm having the same issue , my solution was made a new class who extends from WC_Shipping_Method and keep all the same code there and i made 3 new classes extending the new one , any one with their own ID and mothod type
Its not the best solution but its more legant than duplicate N times the same code of the class

OK I have succeeded in adding another Shipping method by renaming Class name.Previously I may be doing something wrong
However I would like to know if there was some better way of doing it because I have copy pasted whole chunk of code twice , My background is not in OOP however I think it is not the proper way of doing this thing

Related

Add Shipping fees to cart through extending WC_Shipping_Method doesn't work

I want to add shipping fees depends on the customer address after he inserts his address, the value of shipping calculted by API request that I'll replace in the following class but the method itself not added at all.
this code in shipping.php file then I included in the index.php file of the Plugin. I also tried different code snippets all of them not working and the shipping method doesn't even added
function trucking_shipping_init()
{
if (!class_exists('WC_Your_Shipping_Method')) {
class WC_trucking_shipping_Method extends WC_Shipping_Method
{
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
public function __construct()
{
$this->id = 'trucking_shipping_method'; // Id for your shipping method. Should be uunique.
$this->method_title = __('JNE TRUCKING'); // Title shown in admin
$this->method_description = __('Pengiriman dengan truck JNE'); // Description shown in admin
$this->enabled = "yes"; // This can be added as an setting but for this example its forced enabled
$this->title = "JNE TRUCKING"; // This can be added as an setting but for this example its forced.
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init()
{
// Load the settings API
$this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
$this->init_settings(); // This is part of the settings API. Loads settings you previously init.
// Save settings in admin if you have any defined
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
/**
* calculate_shipping function.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping($package = array())
{
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '10.99', // this will be replaced by returned API fees
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate($rate);
}
}
}
add_action('woocommerce_shipping_init', 'trucking_shipping_init');
function add_trucking_shipping_method($methods)
{
$methods['trucking_shipping_method'] = 'WC_trucking_shipping_Method';
return $methods;
}
add_filter('woocommerce_shipping_methods', 'add_trucking_shipping_method');
}

Getting customer adress in custom shipping method

I'm currently working on a custom shipping method for WooCommerce. The goal is to calculate the shipping based on the adress the customer enters in the order process. We currently have an API that receives a storeId and the adress of a customer and returns back the exact amount of shipping we need to apply to the order.
For this, I've started to write a new custom shipping order plugin. I am already receiving the $packages array with the order, however I can't seem to find a way to receive the customers adress in the calculate_shipping method. There also will be a useraction required to select the prefered warehouse on the reviewOrderBeforePayment page and I am not quite sure how to access that data yet.
<?php
/*
* Plugin Name: Warehouses Integration
* Description: WooCommerce integration of the Warehouses API
* Version: 1.1.0
* Author: -
* Author URI: -
* Developer: Laura Heimann
* Developer URI: -
* Text Domain: woocommerce-extension
* WC requires at least: 4.0.1
* WC tested up to: 4.0.1
*/
// Security Measure
if (!defined('ABSPATH')) {
exit;
}
// Check if WooCommerce is installed
if (!in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option( 'active_plugins')))) {
alert("WooCommerce is not installed!");
}
// Main Render Function
// This will be hooked into the WooCommerce Order Page
function wcfw_render() {
// TODO: Show List of possible stores, let user select and save selected store somehow
echo "WCFWRENDER";
}
function wcfw_renderThankYou() {
echo "WCFWTHANKYOU";
}
function wcfw_renderReviewOrder() {
// TODO: Show warning if items from different stores
echo "WCFWREVIEWORDER";
}
function wcfw_shippingMethodInit() {
if ( ! class_exists( 'WC_WCFW_Shipping_Method' ) ) {
class WC_WCFW_Shipping_Method extends WC_Shipping_Method {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
public function __construct() {
$this->id = 'wcfw_shipping_method';
$this->title = __( 'Warehouses Shipping' );
$this->method_description = __( 'Shipping Method through the Warehouse' );
$this->enabled = "yes";
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
$this->init_settings(); // This is part of the settings API. Loads settings you previously init.
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* Settings
*/
function init_form_fields() {
$this->form_fields = array(
'apiBase' => array(
'title' => __('Api Base'),
'type' => 'text',
'description' => __('The base URL for API-Calls.'),
'default' => __('---')
),
);
}
/**
* calculate_shipping function.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping( $package = array() ) {
var_dump( $package );
// TODO: Get Customers Adress and selected store
// TODO: Send data to API and apply provided shipping
$rate = array(
'label' => __('Shipping by Truck'),
'cost' => '10.99',
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate( $rate );
}
}
}
}
function add_wcfw_shipping_method( $methods ) {
$methods[] = 'WC_WCFW_Shipping_Method';
return $methods;
}
// Hooks
add_action('woocommerce_review_order_before_payment', 'wcfw_render', 10);
add_action('woocommerce_thankyou', 'wcfw_renderThankYou', 10);
add_action('woocommerce_after_cart_contents', 'wcfw_renderReviewOrder', 10);
add_action('woocommerce_shipping_init', 'wcfw_shippingMethodInit');
add_filter('woocommerce_shipping_methods', 'add_wcfw_shipping_method');

How to use Widget on Wordpress

Now I'm developing a new WebSite using WordPress.
I don't know how to use widgets.
I tried to search on google so I found some answer.
Here is my code.
class WP_Widget_Home extends WP_Widget {
/**
* Sets up the widgets name etc
*/
public function __construct()
{
parent::__construct('id_widget_home',
__('(TrueLove) [PAGE] Home', 'TrueLove'),
array('description' => __('Intro page.', 'TrueLove')));
}
/**
* Outputs the content of the widget
*
* #param array $args
* #param array $instance
*/
public function widget( $args, $instance ) {
// outputs the content of the widget
echo "<h1>I like U!</h1>";
the_content();
}
...
function registerHomeWidgetFunc()
{
return register_widget("WP_Widget_Home");
}
add_action('widgets_init', 'registerHomeWidgetFunc');
I can insert (TrueLove) [Page] Home widget on WidgetPage('wp-admin/widgets.php').
That's all.
How can I use this?

Wordpress hook that will instantiate a class to be able to use get_post_types before publish_CPT hook

I have an issue where I need to instantiate a class in wordpress so that in the constructor I can use the function get_post_types and have that hook happen before the publish_post hook (which I assume is around the publish_CPT hooks).
Here is the code I have so far
class Transient_Delete {
/**
* #var array of all the different post types on the site
*/
private $postTypes;
/**
* #var array of wordpress hooks we will have to assemble to delete all possible transients
*/
private $wpHooks;
public static function init() {
$class = __CLASS__;
new $class;
}
public function __construct()
{
$this->postTypes = array_values( get_post_types(array(), 'names', 'and') );
$this->wpHooks = $this->setWpHooks($this->postTypes);
add_action('publish_alert', array($this, 'deleteAlertTest'));
}
private function setWpHooks($postTypes)
{
$hooks = array_map(function($postType) {
return 'publish_' . $postType;
}, $postTypes);
return $hooks;
}
private function deleteAlertTest($post)
{
$postId = $post->ID;
echo 'test';
}
}
add_action( 'wp_loaded', array( 'Transient_Delete', 'init' ));
Another note here is that this is in the mu-plugins directory.
note: "alert" of publish_alert is a custom post type.
Ok this was my fault, it looks like the hook publish_alert works fine if I change the deleteAlertTest function to public. Any idea on why having it be a private function has that effect? Its within the same class.

Woocommerce custom product_type seems not to be saved correctly

I am creating my own plugin for woocommerce and realized, that my custom product_type is not saved when the product has been created or updated. I am sure that the problem is coming from my plugin, but I am not sure where to look at.
Function to add the product_type (according to a post)
function extend_woocommerce()
{
Class WC_Product_Connected_To_General_Product extends WC_Product_Simple
{
public function __construct($product)
{
$this->product_type = 'connected_to_general_product';
$this->manage_stock = 'yes';
parent::__construct($product);
}
}
}
Class which is called in the plugin
Class general_stock {
/**
* general_stock constructor.
*/
function __construct()
{
if($this->check_if_woocommerce_is_active()){
add_action('init',[$this, 'add_woocommerce_product_type'])
add_filter('product_type_selector', [$this,'add_woocommerce_product_type_general_connected_product']);
...
}
/**
* add_woocommerce_product_type
*/
function add_woocommerce_product_type(){
extend_woocommerce();
}
/**
* add_woocommerce_product_type_general_connected_product
* #param $types
* #return mixed
*/
function add_woocommerce_product_type_general_connected_product($types){
$types[$this->product_type_name] = __('Connected to general Product','ln-general-stock');
return $types;
}
However "everything" works so far: I am able to select the new product type in backend and saving it aswell. (It is selected when I edit the product).
But when I query the Product in frontend and dump it, the value of product_type equals simple which I think should be connected_to_general_product or is this information stored in another value?
Thank you in advance for your help!
Remember the extends of product class name has to start with WP_Product_ followed with the producto type. Eg.:
class WC_Product_Moto extends WC_Product {
protected $product_type = 'moto';
public function get_type(){
return 'moto';
}
}
I would probably re-arrange the structure of your plugin a bit. I like to load the plugin on the woocommerce_loaded plugin, then you don't even need a conditional check to see if WooCommerce is active. But I think the problem is the array key/value pair that you are adding to the product_type_selector filter.
Class general_stock {
/**
* pseudo constructor.
*/
public static function init()
{
include_once( 'path-to/class-wc-product-connected-to-general-product.php' );
add_filter('product_type_selector', array( __CLASS__, 'add_woocommerce_product_type_general_connected_product' ) );
}
...
/**
* add_woocommerce_product_type_general_connected_product
* #param $types
* #return mixed
*/
public static function add_woocommerce_product_type_general_connected_product($types){
$types['general-product'] = __('Connected to general Product','ln-general-stock');
return $types;
}
}
add_action( 'woocommerce_loaded', 'general_stock::init');
Class WC_Product_Connected_To_General_Product extends WC_Product_Simple
{
public function __construct($product)
{
$this->product_type = 'connected_to_general_product';
$this->manage_stock = 'yes';
parent::__construct($product);
}
}
Also, add this code if doesn't work.
add_filter( 'woocommerce_product_class', array($this,'load_custom_product_type_class'), 10, 2 );
public function load_custom_product_type_class( $classname, $product_type ){
if ( $product_type == 'your_custom_product_type_here' ) {
$classname = 'YOUR_PRODUCT_TYPE_CLASS_NAME';
}
return $classname;
}
I had the same problem and found that I had to define a missing function in my case
if (class_exists('WC_Product_Simple')) {
class WC_Product_Ebook_Store extends WC_Product_Simple {
public function __construct( $product ) {
$this->product_type = 'ebook_store';
parent::__construct( $product );
}
public function get_type() {
return 'ebook_store';
}
}
}

Resources