Parece ser que existe un problema muy común, que surge cuando habilitas varios tipos de gastos de envío y habilitas la opción de gasto de envío gratuito cuando cumpla X condiciones.
Pues resulta que cuando se cumple los criterios para que el envío sea gratuito, woocommerce te da muestra una lista con todos los tipos de envíos disponibles, ¡incluido el envío gratuito!
Lo cual parece curioso, si ya es gratis el envio, para que mostrar la lista de los de pago, obviamente ningún cliente quiere pagar gastos de envío.
Y para mas inri, resulta que woocommerce, ofrece una solución un poco rara, ya que viene ocurriendo desde los inicios de woocommerce y es incluir una función dentro del tema hijo en funtions.php
/**
* Hide shipping rates when free shipping is available.
* Updated to support WooCommerce 2.6 Shipping Zones.
*
* @param array $rates Array of rates found for the package.
* @return array
*/
function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );
Versión WC 2.5
/**
* woocommerce_package_rates is a 2.1+ hook
*/
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
/**
* Hide shipping rates when free shipping is available
*
* @param array $rates Array of rates found for the package
* @param array $package The package array/object being shipped
* @return array of modified rates
*/
function hide_shipping_when_free_is_available( $rates, $package ) {
// Only modify rates if free_shipping is present
if ( isset( $rates['free_shipping'] ) ) {
// To unset a single rate/method, do the following. This example unsets flat_rate shipping
unset( $rates['flat_rate'] );
// To unset all methods except for free_shipping, do the following
$free_shipping = $rates['free_shipping'];
$rates = array();
$rates['free_shipping'] = $free_shipping;
}
return $rates;
}
Versión < WC 2.5
/**
* Hide ALL shipping options when free shipping is available and customer is NOT in certain states
* Hide Free Shipping if customer IS in those states
*
* UPDATED FOR WOOCOMMERCE 2.1
*
* Change $excluded_states = array( 'AK','HI','GU','PR' ); to include all the states that DO NOT have free shipping
*/
add_filter( 'woocommerce_package_rates', 'hide_all_shipping_when_free_is_available' , 10, 2 );
/**
* Hide ALL Shipping option when free shipping is available
*
* @param array $available_methods
*/
function hide_all_shipping_when_free_is_available( $rates, $package ) {
$excluded_states = array( 'AK','HI','GU','PR' );
if( isset( $rates['free_shipping'] ) AND !in_array( WC()->customer->shipping_state, $excluded_states ) ) :
// Get Free Shipping array into a new array
$freeshipping = array();
$freeshipping = $rates['free_shipping'];
// Empty the $available_methods array
unset( $rates );
// Add Free Shipping back into $avaialble_methods
$rates = array();
$rates[] = $freeshipping;
endif;
if( isset( $rates['free_shipping'] ) AND in_array( WC()->customer->shipping_state, $excluded_states ) ) {
// remove free shipping option
unset( $rates['free_shipping'] );
}
return $rates;
}
El motor de almacenamiento se encarga de almacenar, manejar y recuperar información de una tabla. Los motores más conocidos son MyISAM e InnoDB. La elección de uno u otro dependerá mucho del escenario donde se aplique.
En la elección se pretende conseguir la mejor relación de calidad acorde con nuestra aplicación. Si necesitamos transacciones, claves foráneas y bloqueos, tendremos que escoger InnoDB.
Por el contrario, escogeremos MyISAM en aquellos casos en los que predominen las consultas SELECT a la base de datos.
InnoDB dota a MySQL de un motor de almacenamiento transaccional (conforme a ACID) con capacidades de commit (confirmación), rollback (cancelación) y recuperación de fallos.
InnoDB realiza bloqueos a nivel de fila y también proporciona funciones de lectura consistente sin bloqueo al estilo Oracle en sentencias SELECT.
Estas características incrementan el rendimiento y la capacidad de gestionar múltiples usuarios simultáneos.
No se necesita un bloqueo escalado en InnoDB porque los bloqueos a nivel de fila ocupan muy poco espacio.
InnoDB también soporta restricciones FOREIGN KEY. En consultas SQL, aún dentro de la misma consulta, pueden incluirse libremente tablas del tipo InnoDB con tablas de otros tipos
InnoDB
InnoDB es una tecnología de almacenamiento de datos de fuente abierta para MySQL, incluido como formato de tabla estándar en todas las distribuciones de MySQL AB a partir de las versiones 4.0.
Su característica principal es que soporta transacciones de tipo ACID y bloqueo de registros e integridad referencial. InnoDB ofrece una fiabilidad y consistencia muy superior a MyISAM, la anterior tecnología de tablas de MySQL, si bien el mejor rendimiento de uno u otro formato dependerá de la aplicación específica.
Soporte de transacciones
Bloqueo de registros
Nos permite tener las características ACID (Atomicity, Consistency, Isolation and Durability: Atomicidad, Consistencia, Aislamiento y Durabilidad en español), garantizando la integridad de nuestras tablas.
Es probable que si nuestra aplicación hace un uso elevado de INSERT y UPDATE notemos un aumento de rendimiento con respecto a MyISAM.
MyISAM
MyISAM es la tecnología de almacenamiento de datos usada por defecto por el sistema administrador de bases de datos relacionales MySQL.
Este tipo de tablas están basadas en el formato ISAM pero con nuevas extensiones. En las últimas versiones de Mysql, el motor InnoDB está empezando a reemplazar a este tipo de tablas por su capacidad de ejecutar transacciones de tipo ACID y bloqueo de registros e integridad referencial.
Mayor velocidad en general a la hora de recuperar datos.
Recomendable para aplicaciones en las que dominan las sentencias SELECT ante los INSERT / UPDATE.
Ausencia de características de atomicidad ya que no tiene que hacer comprobaciones de la integridad referencial, ni bloquear las tablas para realizar las operaciones, esto nos lleva como los anteriores puntos a una mayor velocidad
Hasta el momento se ha empleado una conexión abierta hacia la base de datos para realizar las peticiones de consulta o actualización de información persistente, sin embargo un compañero comentó que sería bueno hacer hincapié en que, según la necesidad del cliente, se podría hacer uno de un “modo desconectado” de acceso a base de datos. Lo cual recuerda que sería bueno definir los conceptos de modo conectado y desconectado.
Pero… ¿A qué se refieren los desarrolladores con los términos conectado o desconectado?
La forma común y más fácil de implementar en el modo “conectado” o modo de trabajo en el cual el sistema abre una conexión, realiza una acción (o transacción) sobre la base de datos y al final cierra dicha conexión por lo cual los datos quedan persistentes inmediatamente. El modo desconectado sería lo equivalente a hacer una copia local de los objetos de la base de datos sobre las que se desea trabajar (realizando una única apertura inicial de la conexión a base de datos al inicio), para manipularlos con el número de transacciones que se desee y finalmente hacer un volcado del resultado sobre la base de datos, momento en el cual los cambios son recién persistentes.
La pregunta que os surgirá en estos momentos, es ¿Cual es más eficiente? La respuesta es “Depende”.
Si se ha optado por un sistema en el que se va a manipular datos muy delicados y un cambio no registrado puede significar una gestión errónea en una transacción que se ejecute inmediatamente después de la primera, por lo que sería recomendable que dicha aplicación tenga un sistema conectado, ya que de esta manera en todo momento la comunicación con la base de datos y la información estará actualizada. Sin embargo esto va a producir un alto consumo de recursos (entre ellos, las aperturas y cierres de conexiones además de las operaciones de gestión interna del sistema gestor de base de datos) pero va evitar errores que podrían suponer graves consecuencia para el cliente. Por poner un ejemplo sencillo piénsese en un banco o tienda online donde un cambio en la cuenta puede afectar a las siguientes acciones disponibles, generando un error si no se actualizan los cambios inmediatamente.
Por otro lado, si el sistema en cuestión no requiere de una actualización continua de información sería recomendable utilizar una conexión en modo desconectado, donde la información se carga al iniciar la aplicación y en la que se vaya refrescando cada determinado tiempo según el criterio que se crea conveniente. Este tipo de sistemas agota los recursos de una manera completamente distinta, ya que en un sistema conectado, solo tenemos que recuperar la información que no sea necesaria en ese momento, mientras que en este caso recuperaremos mucha información inicialmente, para poder cerrar la base de datos. Para citar un ejemplo se puede pensar en un volcado masivo entra bases de datos.
Se dice que el objeto DataReader realiza un modo conectado ya que necesita tener un curso abierto a la base de datos para poder operar sin embargo el DataSet se dice que es desconectado ya que este ejecuta carga los valores en memoria, desconecta y cuando se requiera se volverá a conectar para realizar un volcado de los datos contenidos en memoria en el soporte persistente de datos.
Por otro lado, si el desarrollador lo desea también podría servirse de ambas tecnologías para la consecución de sus fines, ya que puede usar en DataReader para leer y volcar los valores a objetos de clases personalizadas y luego desconectar, de la misma manera que lo hace DataAdapter, pero manualmente.
Ahora se mostrará cómo se haría un acceso a base de datos y manipulación por medio de un modo Desconectado.
Para empezar se definirá el controlador de la página es el siguiente:
A destacar que se utilizará el mismo código de vista que se ha utilizado en el post anterior, simplemente se cambiará el código del método utilizado en modelo, el cual será llamado getAllDataDesconectado
Como se puede ver, el programador ha creado un DataSet en el que ha añadido una tabla llamada “Asistentes”. El DataAdapter llenará de datos al DataSet en su tabla Asistentes. Y posteriormente se leerán los datos del DataTable y se realizará la acción que más convenga, en este caso, guardarlos datos en una lista para devolvérsela al controlador.
Como paso final solo quedaría mostrar el resultado en la vista.
Ahora que ya se sabe hacer una consulta sobre la base de datos utilizando el modo desconectado, no es complicado hacer modificaciones o eliminaciones sobre los elementos del DataSet y así, al volcar los datos a la base de datos al final de la operación, modificar los elementos persistentes en la base de datos.
Para solucionar este problema “An error occurred while updating an object. product ()”
Usted debe ejecutar las siguientes SQL en su servidor de base de datos, cambiado ps_ por el prefijo de su base de datos.
ALTER TABLE `ps_product` ADD` pack_stock_type` int (11) DEFAULT UNSIGNED '3';
ALTER TABLE `ps_product_shop` ADD` pack_stock_type` int (11) DEFAULT UNSIGNED '3';
ALTER TABLE `ps_pack` ADD` id_product_attribute_item` int (10) NOT NULL UNSIGNED DESPUÉS `id_product_item`;
ALTER TABLE `ps_pack` DROP PRIMARY KEY
Este verificará si ya tiene las DNS nuevas, en caso contrario, las cambiará.
On Error Resume Next
strComputer = "."
strDNSNuevas = "Servidor_DNS_1,Servidor_DNS_2″
Set objWMIService = GetObject("winmgmts://" _ & "{impersonationlevel=impersonate}|\" & strComputer & "rootcimv2″)
Set colNetCards = objWMIService.ExecQuery _ ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IpEnabled = True")
For Each objNetCard In colNetCards
strDNSs = Join(objNetCard..DNSServerSearchOrder,",")
If strDNSs <> strDNSNuevas Then
objNetCard.Set.DNSServerSearchOrder(Join(strDNSNuevas,","))
End If
Next