WordPress For SAE 移植全攻略

66

你跟朽木一样把博客搭建在SAE上吗?
你还在用应用商店陈旧的WordPress版本吗?

wordpress

那么这篇文章你要好好读一下了。

你不需要懂什么技术,只要按照我写的一步步操作就可以了。

第一步 配置文件

SAE是没有写权限的,所以wp-config.php是我们要提前准备好的。

1
2
3
4
5
6
7
8
9
10
11
/** WordPress数据库的名称 */
define('DB_NAME', SAE_MYSQL_DB);
 
/** MySQL数据库用户名 */
define('DB_USER', SAE_MYSQL_USER);
 
/** MySQL数据库密码 */
define('DB_PASSWORD', SAE_MYSQL_PASS);
 
/** MySQL主机名 */
define('DB_HOST', SAE_MYSQL_HOST_M.':'.SAE_MYSQL_PORT);

在根目录新建一个config.yaml,内容如下

handle:
  - rewrite:if (!is_file() && !is_dir() && path ~ "^/(.*)") goto "index.php/$1"

第二步 附件/图片无法上传修正

SAE没有写权限,但是它为我们提供了一个Storage来上传附件,先到SAE的后台新建一个Domain,我的是blog

打开wp-include/funciton.php文件,找到$baseurl = $url;这句代码,在它后面添加$basedir = $dir = 'saestor://blog/blog-uploads';

这里的blog-uploads是朽木博客的附件文件夹,WordPress默认的是wp-content/uploads,这里可以根据自己喜好来填写,但是必须要和WordPress后台的默认上传路径保持一致。还需要到后台修改文件的完整 URL 地址为你的Storage最终地址,例如我的 http://xiumu-blog.stor.sinaapp.com/blog-uploads

第三步 禁用WordPress自动更新

既然SAE没有提供修改代码的权限,那么更新对新手用户来说显得太“奢侈”了,而且这个功能会无端的消耗掉你的豆豆,特别是3.7以后新增的自动更新功能

编辑wp-include/update.php,移到底部,你会发现一大串的add_action(....);,把它们全部删除然后再尾部添加

 add_action( 'load-update-core.php', 'wp_version_check' );
 add_action( 'load-update-core.php', 'wp_update_themes' );
 add_action( 'load-update-core.php', 'wp_update_plugins' );

这样只有你手动去点击 仪表盘->更新的时候,才会检测更新。

第四步 屏蔽WordPress权限检查

这好像是3.5才新加入的代码,用来判断上传文件的执行权限来提高安全性,SAE根本无需考虑代码安全性,它们的存在却会让系统报错。

1
2
3
4
		// Set correct file permissions
		$stat = stat( dirname( $new_file ));
		$perms = $stat['mode'] & 0000666;
		@ chmod( $new_file, $perms );

找到上面这段代码,消灭它们,分别在wp-admin/include/file.phpwp-include/class-wp-image-editor-gd.phpwp-includes\class-wp-image-editor-imagick.php这几个文件中 ,其他肯定还有,但是目前没有发现他们对系统有什么影响,只要找到这3处,删除代码即可。

第五步 修正WordPress自带缩略图裁剪

在WordPress后台设置了图片尺寸后,如果上传的图片大于这个尺寸,就会自动裁剪,而在SAE上却不会,翻来覆去的找了下原因,终于让我找到了。

罪魁祸首在imagepng imagejpeg不能用Wrappers

所以我们要修改缩略图的输出方式,打开wp-include/class-wp-image-editor.php找到如下一句代码

$result = call_user_func_array( $function, $arguments );

修改为

1
2
3
4
5
6
7
		//$result = call_user_func_array( $function, $arguments );
		$arguments_temp = $arguments;
		$arguments_temp[1] = SAE_TMP_PATH.'image_temp.dat';
		$result = call_user_func_array( $function, $arguments_temp );
		if ($result) {
			file_put_contents($arguments[1],file_get_contents(SAE_TMP_PATH.'image_temp.dat'));
		}

到这里,WordPress For SAE 的移植已经基本结束了。

进阶

开启SAE的MemoCache缓存 新建wp-content/object-cache.php文件,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
<?php
/*
Plugin Name: Memcached
Description: Memcached backend for the WP Object Cache.
Version: 2.0.1
Plugin URI: http://wordpress.org/extend/plugins/memcached/
Author: Ryan Boren, Denis de Bernardy, Matt Martz
 
Install this file to wp-content/object-cache.php
*/
 
function wp_cache_add($key, $data, $flag = '', $expire = 0) {
	global $wp_object_cache;
 
	return $wp_object_cache->add($key, $data, $flag, $expire);
}
 
function wp_cache_incr($key, $n = 1, $flag = '') {
	global $wp_object_cache;
 
	return $wp_object_cache->incr($key, $n, $flag);
}
 
function wp_cache_decr($key, $n = 1, $flag = '') {
	global $wp_object_cache;
 
	return $wp_object_cache->decr($key, $n, $flag);
}
 
function wp_cache_close() {
	global $wp_object_cache;
 
	return $wp_object_cache->close();
}
 
function wp_cache_delete($id, $flag = '') {
	global $wp_object_cache;
 
	return $wp_object_cache->delete($id, $flag);
}
 
function wp_cache_flush() {
	global $wp_object_cache;
 
	return $wp_object_cache->flush();
}
 
function wp_cache_get($id, $flag = '') {
	global $wp_object_cache;
 
	return $wp_object_cache->get($id, $flag);
}
 
function wp_cache_init() {
	global $wp_object_cache;
 
	$wp_object_cache = new WP_Object_Cache();
}
 
function wp_cache_replace($key, $data, $flag = '', $expire = 0) {
	global $wp_object_cache;
 
	return $wp_object_cache->replace($key, $data, $flag, $expire);
}
 
function wp_cache_set($key, $data, $flag = '', $expire = 0) {
	global $wp_object_cache;
 
	if ( defined('WP_INSTALLING') == false )
		return $wp_object_cache->set($key, $data, $flag, $expire);
	else
		return $wp_object_cache->delete($key, $flag);
}
 
function wp_cache_add_global_groups( $groups ) {
	global $wp_object_cache;
 
	$wp_object_cache->add_global_groups($groups);
}
 
function wp_cache_add_non_persistent_groups( $groups ) {
	global $wp_object_cache;
 
	$wp_object_cache->add_non_persistent_groups($groups);
}
 
class WP_Object_Cache {
	var $global_groups = array ('users', 'userlogins', 'usermeta', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss');
 
	var $no_mc_groups = array( 'comment', 'counts' );
 
	var $autoload_groups = array ('options');
 
	var $cache = array();
	var $mc = array();
	var $stats = array();
	var $group_ops = array();
 
	var $cache_enabled = true;
	var $default_expiration = 0;
 
	function add($id, $data, $group = 'default', $expire = 0) {
		$key = $this->key($id, $group);
 
		if ( in_array($group, $this->no_mc_groups) ) {
			$this->cache[$key] = $data;
			return true;
		} elseif ( isset($this->cache[$key]) && $this->cache[$key] !== false ) {
			return false;
		}
 
		$mc =& $this->get_mc($group);
		$expire = ($expire == 0) ? $this->default_expiration : $expire;
		$result = $mc->add($key, $data, false, $expire);
 
		if ( false !== $result ) {
			@ ++$this->stats['add'];
			$this->group_ops[$group][] = "add $id";
			$this->cache[$key] = $data;
		}
 
		return $result;
	}
 
	function add_global_groups($groups) {
		if ( ! is_array($groups) )
			$groups = (array) $groups;
 
		$this->global_groups = array_merge($this->global_groups, $groups);
		$this->global_groups = array_unique($this->global_groups);
	}
 
	function add_non_persistent_groups($groups) {
		if ( ! is_array($groups) )
			$groups = (array) $groups;
 
		$this->no_mc_groups = array_merge($this->no_mc_groups, $groups);
		$this->no_mc_groups = array_unique($this->no_mc_groups);
	}
 
	function incr($id, $n, $group) {
		$key = $this->key($id, $group);
		$mc =& $this->get_mc($group);
 
		return $mc->increment($key, $n);
	}
 
	function decr($id, $n, $group) {
		$key = $this->key($id, $group);
		$mc =& $this->get_mc($group);
 
		return $mc->decrement($key, $n);
	}
 
	function close() {
 
		foreach ( $this->mc as $bucket => $mc )
			$mc->close();
	}
 
	function delete($id, $group = 'default') {
		$key = $this->key($id, $group);
 
		if ( in_array($group, $this->no_mc_groups) ) {
			unset($this->cache[$key]);
			return true;
		}
 
		$mc =& $this->get_mc($group);
 
		$result = $mc->delete($key);
 
		@ ++$this->stats['delete'];
		$this->group_ops[$group][] = "delete $id";
 
		if ( false !== $result )
			unset($this->cache[$key]);
 
		return $result; 
	}
 
	function flush() {
		// Don't flush if multi-blog.
		if ( function_exists('is_site_admin') || defined('CUSTOM_USER_TABLE') && defined('CUSTOM_USER_META_TABLE') )
			return true;
 
		$ret = true;
		foreach ( array_keys($this->mc) as $group )
			$ret &= $this->mc[$group]->flush();
		return $ret;
	}
 
	function get($id, $group = 'default') {
		$key = $this->key($id, $group);
		$mc =& $this->get_mc($group);
 
		if ( isset($this->cache[$key]) )
			$value = $this->cache[$key];
		else if ( in_array($group, $this->no_mc_groups) )
			$value = false;
		else
			$value = $mc->get($key);
 
		@ ++$this->stats['get'];
		$this->group_ops[$group][] = "get $id";
 
		if ( NULL === $value )
			$value = false;
 
		$this->cache[$key] = $value;
 
		if ( 'checkthedatabaseplease' == $value )
			$value = false;
 
		return $value;
	}
 
	function get_multi( $groups ) {
		/*
		format: $get['group-name'] = array( 'key1', 'key2' );
		*/
		$return = array();
		foreach ( $groups as $group => $ids ) {
			$mc =& $this->get_mc($group);
			foreach ( $ids as $id ) {
				$key = $this->key($id, $group);
				if ( isset($this->cache[$key]) ) {
					$return[$key] = $this->cache[$key];
					continue;
				} else if ( in_array($group, $this->no_mc_groups) ) {
					$return[$key] = false;
					continue;
				} else {
					$return[$key] = $mc->get($key);
				}
			}
			if ( $to_get ) {
				$vals = $mc->get_multi( $to_get );
				$return = array_merge( $return, $vals );
			}
		}
		@ ++$this->stats['get_multi'];
		$this->group_ops[$group][] = "get_multi $id";
		$this->cache = array_merge( $this->cache, $return );
		return $return;
	}
 
	function key($key, $group) {	
		if ( empty($group) )
			$group = 'default';
 
		if ( false !== array_search($group, $this->global_groups) )
			$prefix = $this->global_prefix;
		else
			$prefix = $this->blog_prefix;
 
		return preg_replace('/\s+/', '', "$prefix$group:$key");
	}
 
	function replace($id, $data, $group = 'default', $expire = 0) {
		$key = $this->key($id, $group);
		$expire = ($expire == 0) ? $this->default_expiration : $expire;
		$mc =& $this->get_mc($group);
		$result = $mc->replace($key, $data, false, $expire);
		if ( false !== $result )
			$this->cache[$key] = $data;
		return $result;
	}
 
	function set($id, $data, $group = 'default', $expire = 0) {
		$key = $this->key($id, $group);
		if ( isset($this->cache[$key]) && ('checkthedatabaseplease' == $this->cache[$key]) )
			return false;
		$this->cache[$key] = $data;
 
		if ( in_array($group, $this->no_mc_groups) )
			return true;
 
		$expire = ($expire == 0) ? $this->default_expiration : $expire;
		$mc =& $this->get_mc($group);
		$result = $mc->set($key, $data, false, $expire);
 
		return $result;
	}
 
	function colorize_debug_line($line) {
		$colors = array(
			'get' => 'green',
			'set' => 'purple',
			'add' => 'blue',
			'delete' => 'red');
 
		$cmd = substr($line, 0, strpos($line, ' '));
 
		$cmd2 = "<span style='color:{$colors[$cmd]}'>$cmd</span>";
 
		return $cmd2 . substr($line, strlen($cmd)) . "\n";
	}
 
	function stats() {
		echo "<p>\n";
		foreach ( $this->stats as $stat => $n ) {
			echo "<strong>$stat</strong> $n";
			echo "<br/>\n";
		}
		echo "</p>\n";
		echo "<h3>Memcached:</h3>";
		foreach ( $this->group_ops as $group => $ops ) {
			if ( !isset($_GET['debug_queries']) && 500 < count($ops) ) { 
				$ops = array_slice( $ops, 0, 500 ); 
				echo "<big>Too many to show! <a href='" . add_query_arg( 'debug_queries', 'true' ) . "'>Show them anyway</a>.</big>\n";
			} 
			echo "<h4>$group commands</h4>";
			echo "<code>\n";
			$lines = array();
			foreach ( $ops as $op ) {
				$lines[] = $this->colorize_debug_line($op); 
			}
			print_r($lines);
			echo "</code>\n";
		}
 
		if ( $this->debug )
			var_dump($this->memcache_debug);
	}
 
	function &get_mc($group) {
		if ( isset($this->mc[$group]) )
			return $this->mc[$group];
		return $this->mc['default'];
	}
 
	function failure_callback($host, $port) {
		//error_log("Connection failure for $host:$port\n", 3, '/tmp/memcached.txt');
	}
 
	function __construct() {
		self::WP_Object_Cache();
	}
 
	function WP_Object_Cache() {
		global $memcached_servers;
 
		if ( isset($memcached_servers) )
			$buckets = $memcached_servers;
		else
			$buckets = array('127.0.0.1');
 
		reset($buckets);
		if ( is_int(key($buckets)) )
			$buckets = array('default' => $buckets);
 
		foreach ( $buckets as $bucket => $servers) {
			$this->mc[$bucket] = memcache_init();
		}
 
		global $blog_id, $table_prefix;
		$this->global_prefix = ( is_multisite() || defined('CUSTOM_USER_TABLE') && defined('CUSTOM_USER_META_TABLE') ) ? '' : $table_prefix;
		$this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':';
 
		$this->cache_hits =& $this->stats['get'];
		$this->cache_misses =& $this->stats['add'];
	}
}
?>

移植hyper-cache缓存插件 SAE的MC缓存是比较吃豆豆的,而相比较新浪自主研发的KVDB的价格却少得可怜,所以我们可以把hyper-cache的缓存写入到KVDB中去,KVDB中只有两个属性,有点类似于Array,既键名与键值,我们可以通过改写SAE提供的SaeKVClient类来给数据加入一个时间戳,用来判断缓存到期时间。

这个类是从官方论坛收集的,根据需要修改了一下,源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php
class MyKVClient extends SaeKVClient
{
    private $_inited = false;
    /*
 
    */
    public function init()
    {
        $_inited = true;
        return parent::init();
    }
    public function set($k, $v=null, $timeout = 0)
    {
        if(!@$_inited)
        {
            $this->init();
        }
        if(!empty($timeout))
        {
            $timeout = time()+$timeout;
        }
        $v = array('d'=>$v,'t'=>$timeout);
        return parent::set($k,$v);
    }
    public function get($k)
    {
        if(!@$_inited)
        {
            $this->init();
        }
        $v = parent::get($k);
        if($v['t']<time() && !empty($v['t']))
        {
            $this->delete($k);
            return false;
        }
        return $v['d'];
    }
    public function gett($k)
    {
        $v = parent::get($k);
        return $v['t'];
    }
    public function delete($k)
    {
        if(!@$_inited)
        {
            $this->init();
        }
        return parent::delete($k);
    }
    public function mget($ks)
    {
        if(!@$_inited)
        {
            $this->init();
        }
        $v = parent::mget($ks);
        if(!empty($v))
        {
            foreach($v as $key=>$val)
            {
                if($val['t']<time() && !empty($val['t']))
                {
                        unset($v[$key]);
                        $this->delete($key);
                }
                else
                {
                        $v[$key] = $val['d'];
                }
            }
        }
        return $v;
    }
    public function pkrget($k,$c=1,$start_key=NULL)
    {
        if(!@$_inited)
        {
            $this->init();
        }
        $v = parent::pkrget($k,$c,$start_key);
        if(!empty($v))
        {
            foreach($v as $key=>$val)
            {
                if($val['t']<time() && !empty($val['t']))
                {
                    unset($v[$key]);
                    $this->delete($key);
                }
                else
                {
                    $v[$key] = $val['d'];
                }
            }
        }
        return $v;
    }
    public function pkrdelete($k,$c=1)
    {
        if(!@$_inited)
        {
            $this->init();
        }
        $v = parent::pkrget($k,$c);
        if(!empty($v))
        {
            foreach($v as $key=>$val)
            {
                $this->delete($key);
            }
        }
        return;
    }
}

如果在非SAE环境中安装hyper-cache,它会在wp-content目录生成一个advanced-cache.php来保存配置,最好还是能在其他环境中配置好,然后再把这个文件上传到SAE来,设置$hyper_cache_path为一个前缀,而不是路径,例如$hyper_cache_path = 'hypercache_';,这样我们可以通过pkrgetpkrdelete来操作hyper-cache的缓存。

options.php有个777的提示需要屏蔽,其他修改都在cache.php和plugin.php中,具体修改太过繁琐就不一一贴出来了。

数据库缓存插件 db-cache-reloaded-fix MYSQL也是资源大户,能省则省,同 hyper-cache 一样 db-cache-reloaded-fix 在非SAE环境中也会向wp-content中写入配置文件,一个db-config.ini,一个db.php。

db.php中define( 'DBCR_CACHE_DIR', DBCR_PATH.'/cache' );也最好修改成前缀,用来识别,我的是define( 'DBCR_CACHE_DIR', 'db-cache-reloaded-fix' );

其他的修改都在db-functions.php里了。

好累,先到这里吧。

共 66 条评论

  1. 回复

    朽木大哥,HyperCache我已经试过可以在WP4.1+SAE上运行了,DB CACHE RELOADED FIX是不支持WP 4.X了对吗?

  2. 回复

    还需要到后台修改文件的完整 URL 地址为你的Storage最终地址,例如我的 http://xiumu-blog.stor.sinaapp.com/blog-uploads,博主好,原谅小白前来问这个简单的问题,这一句实在是没看懂,还请博主多多指教下。

    • 回复

      没什么印象了,你到后台设置->多媒体->文件的完整URL地址 应该是指的这个吧

  3. 回复

    第二步 “修正了 附件/图片无法上传”
    按教程修改了这里后,我通过程序接口也能够直接保存图片到storage里了哈?

  4. 回复

    Օn peut vous dire գue ce n’est pas faux !!

  5. 回复

    唉,为什么我的照你文章里的改完后,上传是可以了,就是图片无法在文章中显示,好像是被剪切了!

    • 回复

      你仔细对比下 看看问题是不是出在文中 “自带缩略图裁剪” 的部分,哦对了,当时写这篇文章的时候用的是3.5.1

      • 回复

        朽木大大那你出过一个最新的版本的WordPress移植方法呀!好期待!望朽木早出!

  6. 回复

    我完全按照上面的都改好了代码,上传图片也成功了,但就是不能显示图片!查看原图倒是可以,好像就是不显示被自动剪切过的图片,这是怎么回事儿呀?

  7. 回复

    WordPress是个不错的博客系统,但现在似乎博客不太用了。我现在专们使用Drupal,这是很好的一个CMF。

    • 回复

      猪跑应该是归类于织梦那样的内容管理CMS吧,很少见用来做博客

  8. 回复

    用的最新版本的WP,但是按照第五步“修正WordPress自带缩略图裁剪”那样做的话就会导致无法生产缩略图,不知为何。。

  9. 回复

    hyper-cache缓存插件,求啊,跪求啊,真心需要啊,没认证没钱,豆豆伤不起啊啊。求一份改好的啊,拜谢了啊

  10. 回复

    求博主分享下db-cache-reloaded-fix 和 hyper-cache 这两个插件的SAE版把….万谢!

  11. 回复

    有没有更新,急需SAE静态缓存插件~

    • 回复

      还没整理,不好意思 .

      • 回复

        哎,SAE用起来还不错,就是CPU太费豆豆了。

  12. 回复

    写这么多辛苦了!

  13. 回复

    hyper-cache缓存插件 啥时候能放出来呢~

  14. 回复

    也遇到upload问题,按这个攻略解决了 http://tahoroom.sinaapp.com/archives/2671.html

  15. 回复

    继续求db-cache-reloaded-fix 和 hyper-cache 这两个插件的SAE版

  16. 回复

    按你这个修改了,但是还是上传不了图片,提示没有目录权限

  17. 回复

    $basedir = $dir = ‘saestor://blog/blog-uploads’;
    这个目录 没太明白啊?

    • 回复

      blog 是 saestor的domain blog-uploads 是stor中的文件夹

  18. 回复

    朽木同学 把 db-cache-reloaded-fix 和 hyper-cache 这两个插件的SAE版共享出来吧,哈,看你博客已经用上了。

    • 回复

      过两天有时间了吧,这段太忙了,我在hyper-cache写了很多其他东西,还得整理下.

  19. 回复

    为什么我按照你的第二步操作,升级wordpress后,上传文件提示:
    无法建立目录 uploads/2013/05。有没有上级目录的写权限?saestor://wordpress/uploads/2013/05 啊!
    $uploads[‘path’] 没有解析吗

    • 回复

      是否在SAE的控制面板 建了名为 wordpress的 Storage Domain

      • 回复

        1、Storage Domain 有的“ wordpress public public 否 管理 修改属性 删除”;
        2、提示的路径是:/data*/www/htdocs/***/f***y/*/wp-content/uploads/2013/05;
        3、functions.php 中我加的是:
        // for SAE
        $dir = ‘saestor://wordpress/uploads’;
        $url = ‘http://’ . $_SERVER[‘HTTP_APPNAME’] . ‘-wordpress.stor.sinaapp.com/uploads’;
        4、错误提示:无法建立目录 wp-content/uploads/2013/05。有没有上级目录的写权限?

      • 回复

        路径是不是有问题

      • 回复

        问题基本可以解决了,找到 wp_mkdir_p 方法,让他通过写权限检测,直接return true,就不会提示错误了!

        • 回复

          恩,解决就好,不过很纳闷,我移植的时候并没有处理这个,没发现你说的错误,现在这个博客就是在SAE,文章中记录的已经是我所有的笔记了

        • 回复

          怎么解决好的?

        • 回复

          return true 怎么写的

          • http://ww2.sinaimg.cn/large/5e22416bgw1e9enleh7uuj20f605ijru.png

    • 回复

      嗯,确实是不能成功上传,也是wordpress3.5.1的版本。

      • 回复

        楼上说的 wp_mkdir_p 可以试者屏蔽下

        • 回复

          怎么屏蔽该方法 ?没有找到在那个文件下 请指教

          • 在wp-includes/functions.php文件中,找到wp_mkdir_p在方法体内第一句加,我是这么做的

        • 回复

          不会屏蔽 可以说具体些吧 也遇到“无法建立目录 wp-content/uploads/2013/05。有没有上级目录 ”的问题了

          • .. 问题是,我没有遇到这个问题. 不知道怎么下手啊.

          • 在wp-includes/functions.php文件中,找到wp_mkdir_p在方法体内第一句加,我是这么做的

  20. 回复

    后台没有找到修改图片的地方呢?已经修改代码了,就是不知道怎么把后台也改好

    • 回复

      ?不明白你的意思,媒体库的图片不能修改还是?

  21. 回复

    db-cache-reloaded-fix 这个移植到SAE上具体要修改哪些呢?博主指教到底吧,额~

  22. 回复

    请教朽木,sae的版本切换功能很好,自己的vps可以实现吗?

    • 回复

      你可以到开源中国搜索一下 SVN

      • 回复

        原来svn就有这功能,那就方便了

  23. 回复

    一直用的某免费空间,主机在国外,偶尔会down掉,有空研究一下迁到SAE上。

    • 回复

      如果有备案的话,SAE还是不错的,但是没有备案的话SAE国外中转速度貌似不怎么地

      • 回复

        我一直在纠结用阿里云还是SAE

        • 回复

          他们两个不一样,SAE是云计算,阿里云某种程度上其实就是自带CDN的VPS

          • 3Q,决定采用阿里云

  24. 回复

    朽木大哥你好,有点问题请求赐教!加我QQ386630909详聊!

  25. 回复

    SAE的豆豆早就被我自然浪费光光了,so……

    • 回复

      除了偶尔抽一抽,速度比我的国内外VPS都要好

  26. 回复

    朽木大哥,说实话,没太看懂…. 囧……话说那天我试着移至了一个到BAE上,对了,您页面上方飘过云彩的效果很有意思啊

    • 回复

      那图片是从别的站抓的,话说我觉得写的够白话了啊..

发表评论

您的邮箱不会公开,当您的评论有新的回复时,会通过您填写的邮箱向您发送评论内容。 必填字段 *

为何看不到我发布的评论?

正在提交, 请稍候...