magento 免邮费价格根据打折后的价格设置

在magento 后台中有设置 免邮费的一项。 但是经过测试实际上价格是小计价格

即购物车里产品价格初步总计,还没有做优惠券等折扣计算。

例如有些网站开发了 积分抵现的功能,亦或是你设置了购物车促销规则,亦或是通过促销规则设置了

优惠券等等情况都会造成最终价格低于达到包邮的价格。

那么我们的修改方法如下:

找到文件 MageShippingModelCarrierFreeshipping.php (在 local 下重写)

修改其中代码:

if (!$this->getConfigFlag('active')) {
                return false;
            }

            $result = Mage::getModel('shipping/rate_result');
            $this->_updateFreeMethodQuote($request);
            if (($request->getFreeShipping())
                || ($request->getBaseSubtotalInclTax() >= $this->getConfigData('free_shipping_subtotal'))
            ) {
                $result->append($this->addFreeShipping());
            }

改为:

if (!$this->getConfigFlag('active')) {
                return false;
            }

            $result = Mage::getModel('shipping/rate_result');
            $this->_updateFreeMethodQuote($request);
            if (($request->getFreeShipping())
                || ($request->getPackageValueWithDiscount() >= $this->getConfigData('free_shipping_subtotal'))
            ) {
                $result->append($this->addFreeShipping());
            }

其实就改动了一个函数 即 getPackageValueWithDiscount() 。

函数 getBaseSubtotalInclTax()是获得购物车的小计价格

getPackageValueWithDiscount() 是获得打折后的包裹价格

当然你可以打印出 $request 变量 看一下里面还有那些值。

此文章通过 python 爬虫创建,原文是自己的csdn 地址: magento 免邮费价格根据打折后的价格设置

使用customer.update 方法 ,magento 1.7.0.2 soap api bug

使用 magento(1.7.0.2) 的soap api 更新用户信息的时候发现不能够更新用户的密码。

我们首先看一下 如何调用api 更新用户信息(参考自:magentocommerce

<?php

$api_url_v1 = "http://192.168.1.162/trunk/index.php/api/soap/?wsdl";
$username = 'moshi';
$password = 'moshiPass';


//连接 SOAP
$client = new SoapClient($api_url_v1);
//获取登入后的 Session ID
$session_id = $client->login($username, $password);
//调用 API 中的方法

$result = $client->call(
          $session_id, 'customer.update', array(
          'customerId' => '70', 'customerData' => array('firstname' => 'mo', 
          'lastname' => 'shi', 'email' => 'moshi@moshi.com', 
          'group_id' => '10', 'password' => '123456')));

var_dump ($result);

?>

但是仅仅这么做更新不了用户的密码。

网上的做法:

找到文件
appcodecoreMageCustomerModelCustomerApi.php
修改 update 方法 在 代码
$customer->save(); 上面添加代码:

if(isset($customerData['password'])){
    $customer->setPassword($customerData['password']);
}

当然最好重写这个模块。

我采用的方法是:
修改 调用api 的 call 函数

把其中的 password 修改为 password_hash 数据即可(当然是加密后的)
我们 可以在 api 调用magento 的update 方法中 找到代码:

foreach ($this->getAllowedAttributes($customer) as $attributeCode=>$attribute) {
            if (isset($customerData[$attributeCode])) {
                $customer->setData($attributeCode, $customerData[$attributeCode]);
            }
        }

这里其实就是根据 被允许的属性来决定哪些属性的值是可以被修改的。
打印 $attributeCode 发现 并没有password 所以直接传送 password 数据这么做是不可行的。
但是我们可以看到 我们是可以修改 pasword_hash 这个值的

当然修改这个值,你首先需要知道 你的magento 系统 加密方式是怎样的。
假设没有更改过,默认的加密方式是 md5(key+password)

所以 你只要在 调用 $client->call() 之前得出 password_hash 值即可。

此文章通过 python 爬虫创建,原文是自己的csdn 地址: 使用customer.update 方法 ,magento 1.7.0.2 soap api bug

magento soap api 列出所有的方法

<?php
$api_url_v1 = "http://192.168.1.162/index.php/api/soap/?wsdl";
$username = 'moshi';
$password = 'moshikey';

//连接 SOAP
$client = new SoapClient($api_url_v1);
//获取登入后的 Session ID
$session_id = $client->login($username, $password);
//调用 API 中的方法
$result = $client->resources($session_id);
foreach($result as $k1=>$v1)
    {
        echo '<div class="box1"><dl>';
        echo '<dt>Title:</dt><dd>'.$v1['title'].'</dd>';
        echo '<dt>Name:</dt><dd>'.$v1['name'].'</dd>';
        echo '<dt>methods:</dt><dd>';
        if(count($v1['methods'])){
            echo '<ul>';
            foreach($v1['methods'] as $k2=>$v2)
            {
                echo '<li>Title:'.$v2['title'].'</li>';
                echo '<li>Name:'.$v2['name'].'</li>';
                echo '<li class="path">Path:'.$v2['path'].'</li>';
            }
            echo '</ul></dd>';
        }
        echo '</dl></div>';
    }

此文章通过 python 爬虫创建,原文是自己的csdn 地址: magento soap api 列出所有的方法

使用excel打开文件,修正长度过长的数字后几位变为0的问题

之前一直不知道这个方法,知道的就跳过吧,勿喷。

我们将身份证号,订单号,手机号,银行卡号等存到文本中,但是使用excel打开的时候

通常会变成科学技术法的样式

如果我们是将数据主动存到 excel中可以通过设置单元格格式为文本即可

但是有的时候这些数据并不是从excel录入的,例如我们从网站中导出。
例如商城导出订单信息,订单号往往很长,而且许多网站后台导出的数据是存到
了csv文件中,而这个文件又默认是使用excel打开。当然我们希望使用excel打开,毕竟基于
excel的强大功能。

例如打开后:

可以看到订单是科学技术法的形式,即使上面有比较详细的数据,但是最后两位是0的
(然而实际上这里的订单最后两位并不是0)
我们使用 notepad++ 或者 记事本打开看一下

可见这样显示是合适的
解决办法:
新建一个空白的excel
依次点击 数据--自文本 之后选择你的csv文件

直接下一步

选择逗号,下一步
之所以选择逗号是因为我们之前是使用 记事本打开csv文件的时候发现每个列的数据使用逗号分割的

格式选择文本,点击完成。

直接确定即可(=$A$1 表示从A1开始)
最后效果

打完收工 🙂

此文章通过 python 爬虫创建,原文是自己的csdn 地址: 使用excel打开文件,修正长度过长的数字后几位变为0的问题

php中的魔术方法

PHP魔术方法:

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为"魔术方法"(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。

__construct(),类的构造函数
__destruct(),类的析构函数
__call(),在对象中调用一个不可访问方法(私有或者不存在)时调用
__callStatic(),用静态方式中调用一个不可访问方法时调用
__get(),获得一个类的成员变量时调用
__set(),设置一个类的成员变量时调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用。
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法
__set_state(),调用var_export()导出类时,此静态方法会被调用。
__clone(),当对象复制完成时调用

__construct()和__destruct()
构造函数__construct()在对象被创建的时候调用,析构函数__destruct()在对象消亡的时候被调用

<?php  
class ConDes
{
    protected $a = '';

    function __construct(){
        echo '在构造函数中<br>';
    }

    function __destruct(){

        echo '在析构函数中<br>';
    }
}

$val = new ConDes();
unset($val);

?><pre name="code" class="php">


输出:

在构造函数中在析构函数中

__call()和__callStatic()在对象中调用一个不可访问方法时会调用这两个方法,后者为静态方法。

<?php  
class MethodTest  
{
    public function __call ($name, $arguments) {
    var_dump($arguments);
        echo "object method $name and ".implode(',',$arguments)."<br>";
    }

    public static function __callStatic ($name, $arguments) {
        echo "static method $name and ".implode(',',$arguments)."<br>";
    }
}

$obj = new MethodTest;
$obj->runTest('in object context','another arg');
MethodTest::runTest('in static context');  
?>

输出:

array (size=2)
  0 => string 'in object context' (length=17)
  1 => string 'another arg' (length=11)

object method runTest and in object context,another arg
static method runTest and in static context

__get(),__set(),__isset()和__unset()

当获取一个不可访问的类成员变量或设置一个不可访问的类成员变量时调用这两个函数。

<?php
class MethodTest  
{
    private $data = array();
    private $a = '';
    public $bbb = '';

    public function __set($name, $value){
        $this->data[$name] = $value;
		echo '__set';
		var_dump($this->data);
    }

    public function __get($name){
		echo '__get';
		var_dump($this->data);
        if(array_key_exists($name, $this->data))
            return $this->data[$name];
        return NULL;
    }

    public function __isset($name){
		echo '__isset';
        return isset($this->data[$name]);
    }

    public function __unset($name){
		echo '__unset';
        unset($this->data[$name]);
    }
}

$in = new MethodTest();
$in->a = 'aaaa';
$aaa = $in->a;
$res = isset($in->c)? 'set':'not set';
echo '<br>'.$res.'<br>';
unset($in->a);
?>

输出:

__set
array (size=1)
  'a' => string 'aaaa' (length=4)
__get
array (size=1)
  'a' => string 'aaaa' (length=4)
__isset
not set
__unset

__sleep()和__wakeup()

当我们在执行serialize()和unserialize()时,会先调用这两个函数。例如我们在序列化一个对象时,这个对象有一个数据库链接,想要在反序列化中恢复链接状态,则可以通过重构这两个函数来实现链接的恢复。

<?php
class Connection {
    public $link;
    private $server, $username, $password, $db;
    
    public function __construct($server, $username, $password, $db)
    {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }
    
    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }
    
    public function __sleep()
    {
    echo 'sleep<br>';
        return array('server', 'username', 'password', 'db');
    }
    
    public function __wakeup()
    {
    echo 'wakeup<br>';
        $this->connect();
    }
}


$a = new Connection('localhost','mosi','moshi','test');
$sql = 'select id,username from user limit 1';
$res = mysql_query($sql,$a->link);
$res = mysql_fetch_array($res);
var_dump($res);

$sres = serialize($a);
mysql_close($a->link);
//unset($a);

$unsres = unserialize($sres);
var_dump($unsres);
$sql = 'select id,username from user limit 1';
$ress = mysql_query($sql,$unsres->link);
$ress = mysql_fetch_array($ress);
var_dump($ress);


?>

输出:

array (size=4)
  0 => string '1' (length=1)
  'id' => string '1' (length=1)
  1 => string 'm0sh1' (length=5)
  'username' => string 'm0sh1' (length=5)
sleep
wakeup
object(Connection)[2]
  public 'link' => resource(6, mysql link)
  private 'server' => string 'localhost' (length=9)
  private 'username' => string 'moshi' (length=4)
  private 'password' => string 'moshi' (length=5)
  private 'db' => string 'test' (length=4)
array (size=4)
  0 => string '1' (length=1)
  'id' => string '1' (length=1)
  1 => string 'm0sh1' (length=5)
  'username' => string 'm0sh1' (length=5)


__toString()

对象当成字符串时的回应方法。例如使用echo $obj;

<?php  
class TestClass  
{
    public function __toString() {
        return 'this is a object';
    }
}

$class = new TestClass();
echo $class;  
?>

输出:

this is a object

这个方法只能返回字符串,而且不可以在这个方法中抛出异常,否则会出现致命错误。

__invoke()

调用函数的方式调用一个对象时的回应方法。

<?php
class Invoke{
	public function __invoke(){
		echo 'in invoke<br>';
	}
}

class noInvoke{

}

$obj = new Invoke();
$obj();

var_dump(is_callable($obj));

$obj2 = new noInvoke();
//$obj2();
var_dump(is_callable($obj2));

输出:

in invoke
boolean true
boolean false

__set_state()

调用var_export()导出类时,此静态方法会被调用。

<?php  
class A  
{
    public $var1;
    public $var2;
	public static function __set_state ($arr) {
        $obj = new A;
        $obj->var1 = 'var11';
        $obj->var2 = $arr['var2'];
        return $obj;
    }
}

$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
var_dump($a);  
var_export($a);  

eval('$ress = '.var_export($a,true).';');
var_dump($ress);

?>

输出:

object(A)[1]
  public 'var1' => int 5
  public 'var2' => string 'foo' (length=3)
A::__set_state(array( 'var1' => 5, 'var2' => 'foo', ))
object(A)[2]
  public 'var1' => string 'var11' (length=5)
  public 'var2' => string 'foo' (length=3)

__clone()

当对象复制完成时调用。

<?php  
class Singleton {  
    private static $_instance = NULL;

    // 私有构造方法 
    private function __construct() {}

    public static function getInstance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new Singleton();
        }
        return self::$_instance;
    }

    // 防止克隆实例
    public function __clone(){
        die('Clone is not allowed error: ' . E_USER_ERROR);
    }
}


$a = Singleton::getInstance();
$b = Singleton::getInstance();

if( $a === $b ){
	echo 'equal<br>';
}

$c = clone $b;
?>

输出:

equal
Clone is not allowed error: 256

PHP 魔术常量:简介在这里

此文章通过 python 爬虫创建,原文是自己的csdn 地址: php中的魔术方法