据说 Zend 正在跟 Plesk 探讨怎么让他们的产品相互兼容。
我没那么高深,无法让 Zend Server 完全兼容 Plesk,但可以做到——
前台用上 Zend Server 版的 php (Plesk 前后台使用两个安装的 php),尽管 Plesk 后台误认为 php module not installed。我强行修改了 psa 数据库里的数据,改了什么我不记得了。说实话,把 Zend Server 和 Plesk 跑在一起意义也不大。
据说 Zend 正在跟 Plesk 探讨怎么让他们的产品相互兼容。
我没那么高深,无法让 Zend Server 完全兼容 Plesk,但可以做到——
前台用上 Zend Server 版的 php (Plesk 前后台使用两个安装的 php),尽管 Plesk 后台误认为 php module not installed。我强行修改了 psa 数据库里的数据,改了什么我不记得了。说实话,把 Zend Server 和 Plesk 跑在一起意义也不大。
我写这个类更多地是为了补习一下英文。顺便说一下,我会逐渐把更多的 support classes 归于 Msdk module,意思是 Magento SDK.
An ideal way to learn IT and English as a foreign language at a time.
<?php class Qian_Mdsk_Helper_Plural extends Mage_Core_Helper_Abstract { /** * auto is a wrapper. it calls another method by language settings * @param int $nr * @param string $singularWord * @return string */ public static function auto($nr, $singularWord) { //if english return self::english($nr, $singularWord, 's'); } public static function english($nr, $singularWord, $pluralSuffix = 's') { if (abs($nr) == 1) { return "$nr $singularWord"; } $no = Mage::helper('corex')->__("No"); //If a word has more than one form of plural, and if the commonly used form is regular, the word will not be included in this dictionary. //e.g. roof => roofs (irregular) or rooves (regular) $dictionary = array( //sh rule exception 'fish' => 'fish', //o rule exception 'canto' => 'cantos', 'homo' => 'homos', 'piano' => 'pianos', 'portico' => 'porticos', 'pro' => 'pros', 'quarto' => 'quartos', 'kimono' => 'kimonos', 'zoo' => 'zoos', 'igloo' => 'igloos', 'kangaroo' => 'kangaroo', 'kniazhestvo' => 'kniazhestva', //x rule exception 'matrix' => 'matrices', 'vertex' => 'vertices', //s rule exception 'alumnus' => 'alumni', 'corpus' => 'corpora', 'focus' => 'foci', 'genus' => 'genera', 'prospectus' => 'prospecti', 'radius' => 'radii', 'syllabus' => 'syllabi', 'viscus' => 'viscera', 'fungus' => 'fungi', 'terminus' => 'termini', 'uterus' => 'uteri', 'Atlas' => 'Atlantes', 'species' => 'species', 'series' => 'series', 'blues' => 'blues', 'axis' => 'axes', 'testis' => 'testes', //y rule exception 'Germany' => 'Germanys', 'Harry' => 'Harrys', //f rule exception 'staff' => 'staff', 'flagstaff' => 'flagstaffs', 'proof' => 'proofs', //other exception //singular and plural are identical 'people' => 'people', 'deer' => 'deer', 'moose' => 'moose', 'sheep' => 'sheep', 'bison' => 'bison', 'salmon' => 'salmon', 'pike' => 'pike', 'trout' => 'trout', 'swine' => 'swine', 'aircraft' => 'aircraft', 'head' => 'head', 'stone' => 'stone', 'benshi' => 'benshi', 'otaku' => 'otaku', 'samurai' => 'samurai', 'Māori' => 'Māori', 'marae' => 'marae', 'waka' => 'waka', //very irregular exception 'child' => 'children', 'alumna' => 'alumnae', 'mouse' => 'mice', 'louse' => 'lice', 'tooth' => 'teeth', 'foot' => 'feet', 'goose' => 'geese', 'automaton' => 'automata', 'criterion' => 'criteria', 'phenomenon' => 'phenomena', 'polyhedron' => 'polyhedra', 'addendum' => 'addenda', 'agendum' => 'agenda', 'consortium' => 'consortia', 'corrigendum' => 'corrigenda', 'datum' => 'data', 'medium' => 'media', 'memorandum' => 'memoranda', 'millennium' => 'millennia', 'symposium' => 'symposia', 'stigma' => 'stigmata', 'stoma' => 'stomata', 'schema' => 'schemata', 'dogma' => 'dogmata', 'lemma' => 'lemmata', 'beau' => 'beaux', 'château' => 'châteaux', 'tableau' => 'tableaux', 'Inuk' => 'Inuit', 'inukshuk' => 'inukshuit', 'phalanx' => 'phalanges', ); if (isset($dictionary[$singularWord])) { $pluralWord = $dictionary[$singularWord]; } else {//some clever conversion $end = substr($singularWord, -3); if ($end == 'man') { //checking last 3 characters $pluralWord = substr($singularWord, 0, -3) . 'men'; } elseif ($end == 'sis') { $pluralWord = substr($singularWord, 0, -3) . 'ses'; } else { $end = substr($singularWord, -2); if ($end == 'ch' || $end == 'sh') { $pluralWord = $singularWord . 'es'; } elseif ($end == 'fe') { $pluralWord = substr($singularWord, 0, -2) . 'ves'; //e.g. knife => knives, wife => wives } else { $end = substr($singularWord, -1); if (strpos('sxo', $end) === false) { //checking last character $pluralWord = $singularWord . 'es'; } elseif ($end == 'f') { $pluralWord = substr($singularWord, 0, -1) . 'ves'; //e.g. half => halves } elseif ($end == 'y') { $secondLast = substr($singularWord, -2, 1); if (strpos('aeiou', $secondLast) === false) { $pluralWord = substr($singularWord, 0, -1) . 'ies'; //e.g. lady => ladies } else { $pluralWord = $singularWord . $pluralSuffix; //e.g. boy => boys } } else { //last rule $pluralWord = $singularWord . $pluralSuffix; } } } } if ($nr == 0) { return "$no $pluralWord"; } else { return "$nr $pluralWord"; } } }
In Gmail, type “-in:inbox” or “!in:inbox” in search box and click “Search Mail”,what emails will show up? All emails not in inbox? Not exactly.
You know Gmail delivers conversions instead of emails as search result, so let’s use terminology conversion. Does “-in:inbox” come up with all conversions not in inbox? No, again.
The collection of “-in:inbox” is all conversions not in inbox plus those conversions originated by me or to which I responded.
在 CentOS 上,怎么把 linux user ftp 登录后限制在它的 home directory?很久以前我设置过一次,知道是很简单的一个设置,今天需要同样的事情再做一次,竟然怎么也想不起来。要命的是,google 了好几个小时都不得要领。
可以说半天时间是浪费掉的。最后当然是重新找到了办法,赶紧记下来:
Edit /etc/proftpd.conf, add
DefaultRoot ~
当然前提预装有 proftpd。如果还预装 plesk,则更简单,/etc/proftpd.conf 已含有
DefaultRoot ~ psacln
只要把新建的用户归入 secondary group psacln 即可。
Magento 自带的管理产品图片的机制简单有效,但每次只能对单个产品进行管理,每次要 http upload 很费时。如果换个角度看,如果要成批更新产品图片,就不那么方便;如果要调用某个产品图片,必须先找到产品才能找到图片,因为 Magento 对上传后的文件进行了 dispretion 处理了文件路径,没有直观的办法可以直接浏览图片。
所以我的做法是,产品图片按产品属性归类,把整个文件夹 ftp 到 Magento 某个位置(或从 Magento 中独立出来,用一个静态文件服务器来管理图片,这样可以提供更方便的文件操作)。
然后在 magento/media/catalog/product 下建一个软连接(假设这个软连接名 static_image_linkedin)到产品图片目录的根。不要在 magento/media/catalog 这一级把 product 建为软连接,因为 Magento 会在 product 下建 cache 目录,从静态文件服务器角度看,这个 cache 是垃圾(我追求完美)。
然后,如果要指定产品使用某图片,必须把image, small_image, thumbnail, media_gallery 对应的值保存为人工指定位置的图片路径,该值的形式如 “/static_image_linkedin/nwf/recycled/green_bag.jpg”。Magento 原值形式如 “/g/r/green_bag.jpg”,我还没做出一个 GUI 帮助完成此项修改,依赖数据库直接操作。
我本有一个想法是修改 magento/app/code/core/Mage/Catalog/Model/Product/Media/Config.php 来改变产品图片目录的根,这样就不需要建软连接。但这样做的缺点是在移交 Magento 给别的 developers 时,我还得多一点额外交代。
When to use:
Magento has a native “buy x get y” sales rule in promotions. Magento’s x and y refer to a same product. For example, if a product offer is “buy 3 get 2”, you have to buy 5 of this product then only pay for 3 of them.
Quite often the store owners want to give an offer which let customers choose from a wide range of products, (the programme add them up, get a total quantity of subselect), and offer another selection of products for free. It is useful if the store have two ranges of products, among which prices are almost the same. Let’s make it clear to you: in this module, “buy x get y” means “Buy X selection of products, Get another Y selection for free”.
I wrote some quick and dirty codes to do “Buy X selection of products, Get another Y selection for free” quite a while ago, but this release refactors the codes into a standard standalone Magento extension.
How to install:
Copy the whole “app” folder, merge to magento/app. That’s it.
If you are logged in Magento backend when doing installation, that’s fine. But you have to log out and log in again to access Buy X Get Y configuration section in System Configuration.
How to use:
Log in Magento backend, go to Promotions -> Shopping Cart Price Rules, create a new rule whose name must start with “[bxgy]”;
In “Rule Information” tab, apart from the Rule Name, set up everything else as if it is normal Magento sales rule;
In “Conditions” tab, create a product total quantity subselect. The product subselect should match the selection of X product in the offer, and condition is “equals or greater than”, and quantity should match the quantity of X product used as qualifier;
* Do not create more than one subselect. Result is unpredictable otherwise.
* The condition must be “equals or greater than” and the quantity must be the threshold quantity of the offer. Although the calculation of the free quota of Y product is not dependent on the quantity (it is dependent on the settings in “Actions” tab), the offer validation is still Magento original logic. This module changes the discount amount after the offer validation. In other words, you must think about when to trigger Magento native “buy x get y”, and do the same conditions for this module.
In “Actions” tab, set Apply to “Buy X get Y (discount amount is Y)” (although this is not normal buy_x_get_y action, the program still check this simple_action), set Discount amount to offer free quota, set Maximum Qty Discount is Applied to to 0, set Discount Qty Step (Buy X) to offer quantity qualifier. For example, if the offer is “buy any 3 of X products, and get any 2 of Y products free”, then set Discount amount to 3, set Maximum Qty Discount is Applied to to 0, set Discount Qty Step (Buy X) to 2. Then, in “Apply the rule only to cart items matching the following conditions (leave blank for all items)”, create a combination of conditions which match the selection of Y product in the offer. Multi combination is OK;
In “Label” tab, enter the offer labels as normal. It is not required, but if you leave it blank, the “ugly” Rule Name “[bxgy]***” will be used is discount description;
Now save the rule, and go to System -> Configuration -> Buy X Get Y -> Buy X selection of products, Get another Y selection for free, set up the offer reminder message in cart. It is not required. And if it is not set up, the offer is still taking effect as long as the sales rule is enabled.
How is it created:
This module is created by koukou1985’s module creator (http://www.magentocommerce.com/wiki/custom_module_with_custom_database_table). Thanks to koukou1985.
How good is it:
This module does not override any Mage classes. It is safe to use with other extensions as long as namespace and module name do not conflict.
FAQ:
Q: Why this module does not work?
A: I won’t cover all reasons that make my module not working. I only point out caveats of my module, and expect you to have common knowledge of Magento, such as “refresh the cache to see the newly installed features”. All caveats are in above sections. So, if you are stuck, go back to the top and read again.
Download BuyXGetY.tar.gz
Update: a new version of bxgy module is available at http://blog.goods-pro.com/1764/magento-extension-bxgy-0-1-1-is-released/
2011/02/21 Update again: please checkout a newer release. Always leave comments on the newest release post. The comment on this post is closed.
我挺奇怪的,搜了一下竟然没人写过此类话题。怎么把 Magento 应用到外贸企业是我从一开始接触 Magento 就盘旋在我脑袋里的思考点,但却没人讨论过。或许 Magento 天生适合 b2c,或许外贸企业的眼光沉浸于展销会、阿里巴巴?
我不否认拿 Magento 去做外贸业务(我指的是报关出口)是有难度的,需要改造很多地方。今天突然想讲一讲,是因为我理清了一个思路:如何处理询盘 (enquiry)。在外贸实践中,询盘不是一个订单 (order)。这左右了我,老想着 extends Mage_Sales_Model_Quote 或 Mage_Wishlist_Model_Wishlist 去做一个 enquiry model,因为 quote 或 wishlist 都可以说是客户下单前的 enquiry。
但在编程实践中,外贸业务的 enquiry 应该由 extends Mage_Sales_Model_Order 才最适合,因为每个 enquiry 都是一个具体的、有形的客户做的,客户的国别、地址都是报价的考虑要素,Mage_Sales_Model_Quote 或 Mage_Wishlist_Model_Wishlist 都不具备这些要素,只有 Mage_Sales_Model_Order 才具备。所以,最简单的办法是为 order 自定义一些 pending 前状态,如 enquiry, offer, offer-accepted, offer-dead。
今后我会多谈谈我怎么把 Magento 应用到外贸企业的思路。
国内的苹果粉把新出炉的 iPhone4 (水货)爆炒到人民币一万多一台,他们疯了,我本可以无语。但是很多人利用位域优势从英国订 iPhone4 往国内带,有的为了谋利,有的为了摆显,连带我也被折腾进去,我真是无奈。
英国能买到 iPhone4,但是目前每人最多订一台。我老婆的名额被她老板业务需要用掉了,我老婆却还想去摆显。倒不是自己用,一万多的机子,她可以£599平价捎给朋友,而且是最紧俏的时候,她想享受一下拉风的感觉吧。我只能成全她,今天跟着她去苹果店用我的名额订了一台,否则为了苹果我们吵架太不值得。
但是作为一个 anti-appler, 我深为我的行为感到可耻。我对不起富士康跳了楼的员工们,我的订购也间接地延迟了 iPhone 被 Android 取代。虽然我个人已经进入了 Android 时代,但还有广大“劳苦大众”还没有机会认识到这世界上还有比 iPhone 更高级智能、更人性化的产品,我对不起他们。
在这里,我道歉——真诚地,希望你们能感受到。
漫天都是“云服务”,但真让我有云的感觉的服务目前只有 Google 一家。最近买了 1&1 cloud server,如果要评满意程度的话,只能是 5 out of 10 (购前期望过高)。
我原以为基于云的服务器可以一劳永逸、无限扩张,哪知 1&1 cloud server cpu core, memory, hard disk 都有上限,cpu core 最多买 4 个,其实就相当于单个 quad core cpu。
1&1 cloud server 性能也一般,或许还不如 vps,唯一优势就是比同等性能的 dedicated server 便宜一些。
Magento store owners are having a challenge when using rcah 0.1.0, especially for homepage. The nature of homepage is CMS, most content of it static.
Store owners want their visitors (especially first time visitors) to read static content on the homepage, but static content become obstacles filling in the central area of the page when visitors start to click on filters for refined results.
Root category as homepage 0.1.1 is released to address the problem. It conditionally hides the CMS Block on category pages. It only hides CMS Block in Display Settings of a category (category landing_page attribute). Static CMS Blocks used for others purposes (in sidebar, footer, etc) are not affected.
I must say the conditions when hiding the CMS Block are subtle. Please refer to readme file with the release for details.
Download RootCategoryAsHomepage.tar.gz