問題描述
我想在自定義資料夾中上傳自定義圖片大小。該資料夾應具有所選寬度的名稱。例如:
如果我新增這些自定義尺寸…
add_image_size('custom-1', 300, 9999);
add_image_size('custom-2', 400, 9999);
這將是很好的上傳的影像是這樣上傳的:
http://www.my-site.com/wp-content/uploads/300/my-image.jpg
http://www.my-site.com/wp-content/uploads/400/my-image.jpg
這可能嗎?我只發現我可以用 upload_dir 過濾器更改全域性上傳資料夾。
最佳解決方案
菲利普,任何事情都是可能的,如果你把你的想法。您可以透過擴充套件 WordPress 影像編輯器類來解決您的問題。
注意我正在使用 WordPress 3.7 – 我沒有在早期版本和最新的 3.8 版本中檢查下列程式碼。
影像編輯器基礎知識
WordPress 有兩個內建的類來處理影像處理:
-
WP_Image_Editor_GD(/wp-includes/class-wp-image-editor-gd.php) -
WP_Image_Editor_Imagick(/wp-includes/class-wp-image-editor-imagick.php)
這兩個類擴充套件了 WP_Image_Editor,因為它們都使用不同的影像引擎 (分別為 GD 和 ImageMagick) 來載入,調整大小,壓縮和儲存影像。
預設情況下,WordPress 將首先嚐試使用 ImageMagick 引擎,該引擎需要一個 PHP 擴充套件,因為它通常優於 PHP 的預設 GD 引擎。大多數共享伺服器沒有啟用 ImageMagick 擴充套件。
新增影像編輯器
要決定使用哪種引擎,WordPress 會呼叫內部函式__wp_image_editor_choose()(位於/wp-includes/media.php 中) 。此函式迴圈遍歷所有引擎,以檢視哪個引擎可以處理請求。
該功能還有一個稱為 wp_image_editors 的過濾器,可以讓您新增更多的影像編輯器,如:
add_filter("wp_image_editors", "my_wp_image_editors");
function my_wp_image_editors($editors) {
array_unshift($editors, "WP_Image_Editor_Custom");
return $editors;
}
請注意,我們預設了自定義影像編輯器類 WP_Image_Editor_Custom,因此 WordPress 將在測試其他引擎之前檢查我們的引擎是否可以處理調整大小。
建立我們的影像編輯器
現在我們要寫自己的影像編輯器,所以我們可以自己決定檔名。 Filenaming 由 WP_Image_Editor::generate_filename()(兩個引擎繼承此方法) 的方法處理,因此我們應該在我們的自定義類中覆蓋。
由於我們只計劃更改檔名,所以我們應該擴充套件現有的引擎之一,所以我們不必重新發明。我將在我的例子中擴充套件 WP_Image_Editor_GD,因為您可能沒有啟用 ImageMagick 擴充套件。該程式碼對於 ImageMagick 設定可以互換。如果您計劃使用不同設定的主題,您可以新增兩者。
// Include the existing classes first in order to extend them.
require_once ABSPATH.WPINC."/class-wp-image-editor.php";
require_once ABSPATH.WPINC."/class-wp-image-editor-gd.php";
class WP_Image_Editor_Custom extends WP_Image_Editor_GD {
public function generate_filename($prefix = NULL, $dest_path = NULL, $extension = NULL) {
// If empty, generate a prefix with the parent method get_suffix().
if(!$prefix)
$prefix = $this->get_suffix();
// Determine extension and directory based on file path.
$info = pathinfo($this->file);
$dir = $info['dirname'];
$ext = $info['extension'];
// Determine image name.
$name = wp_basename($this->file, ".$ext");
// Allow extension to be changed via method argument.
$new_ext = strtolower($extension ? $extension : $ext);
// Default to $_dest_path if method argument is not set or invalid.
if(!is_null($dest_path) && $_dest_path = realpath($dest_path))
$dir = $_dest_path;
// Return our new prefixed filename.
return trailingslashit($dir)."{$prefix}/{$name}.{$new_ext}";
}
}
上面的程式碼大部分是從 WP_Image_Editor 類直接複製的,併為了方便起見。唯一的實際變化是字尾現在是字首。
或者,您可以呼叫 parent::generate_filename()並使用 mb_str_replace()將字尾更改為字首,但我認為更傾向於出錯。
儲存後設資料的新路徑
上傳 image.jpg 後,uploads 資料夾如下所示:
-
2013/12/150x150/image.jpg -
2013/12/300x300/image.jpg -
2013/12/image.jpg
到現在為止還挺好。但是,當呼叫 wp_get_attachment_image_src()這樣的基本功能時,我們會注意到所有的影像大小都儲存為 image.jpg,而沒有新的目錄路徑。
我們可以透過將新的資料夾結構儲存到影像後設資料 (儲存檔名的位置) 來解決此問題。在插入資料庫之前,資料透過各種過濾器 (wp_generate_attachment_metadata 等) 執行,但由於我們已經在實現自定義影像編輯器,因此我們可以回到影像大小後設資料源 WP_Image_Editor::multi_resize()。它生成像這樣的陣列:
Array (
[thumbnail] => Array (
[file] => image.jpg
[width] => 150
[height] => 150
[mime-type] => image/jpeg
)
[medium] => Array (
[file] => image.jpg
[width] => 300
[height] => 300
[mime-type] => image/jpeg
)
)
我們將在我們的自定義類中覆蓋 multi_resize()方法:
function multi_resize($sizes) {
$sizes = parent::multi_resize($sizes);
foreach($sizes as $slug => $data)
$sizes[$slug]['file'] = $data['width']."x".$data['height']."/".$data['file'];
return $sizes;
}
你可以看到,我沒有打擾替換任何程式碼。我只是呼叫父方法並讓它生成後設資料。然後我迴圈遍歷結果陣列,並調整每個大小的 file 值。
現在 wp_get_attachment_image_src($att_id, array(300, 300))返回 2013/12/300x300/image.jpg 。萬歲!
最後的想法
我希望這為您提供一個很好的依據。但是,請注意,如果影像小於指定尺寸 (例如,280×300),生成的字尾 (我們的字首) 和影像尺寸是 280×300,而不是 300×300 。如果你上傳了很多較小的影像,你會得到很多不同的資料夾。
一個很好的解決方案是使用大小外掛作為資料夾名稱 (small,medium 等),或將程式碼擴充套件到圓形大小,直到最接近的首選影像大小。
你注意到你只想使用寬度作為目錄名。要警告 – 外掛或主題可以生成兩個不同的大小,寬度相同但不同的高度。
此外,您可以透過在 「設定」 和 「設定」 下停用 「將我上傳到月份和 year-based 資料夾」 媒體還是進一步操縱 generate_filename 。
希望這可以幫助。祝你好運!
次佳解決方案
@ Robbert 的答案是將 WordPress 生成的替代大小儲存在單獨的目錄中的神聖資源。我的程式碼也將上傳目錄更改為./media,所以如果不想要,請確保編輯這些行。這不是第一個海報問題的確切答案,而是為同一個問題提供了一個替代解決方案:
if ( !is_multisite() ) {
update_option( 'upload_path', 'media' ); //to-do: add to options page
define( 'UPLOADS', 'media' ); //define UPLOADS dir - REQUIRED
}
//don't 「Organize my uploads into month- and year-based folders」
update_option( 'uploads_use_yearmonth_folders', '0' ); // to-do: add to options page
//create a custom WP_Image_Editor that handles the naming of files
function tect_image_editors($editors) {
array_unshift( $editors, 'WP_Image_Editor_tect' );
return $editors;
}
add_filter( 'wp_image_editors', 'tect_image_editors' );
require_once ABSPATH . WPINC . '/class-wp-image-editor.php';
require_once ABSPATH . WPINC . '/class-wp-image-editor-gd.php';
class WP_Image_Editor_tect extends WP_Image_Editor_GD {
public function multi_resize($sizes) {
$sizes = parent::multi_resize($sizes);
$media_dir = trailingslashit( ABSPATH . UPLOADS );
foreach($sizes as $slug => $data) {
$default_name = $sizes[ $slug ]['file'];
$new_name = $slug . '/' . preg_replace( '#-d+xd+.#', '.', $data['file'] );
if ( !is_dir( $media_dir . $slug ) ) {
mkdir( $media_dir . $slug );
}
//move the thumbnail - perhaps not the smartest way to do it...
rename ( $media_dir . $default_name, $media_dir . $new_name );
$sizes[$slug]['file'] = $new_name;
}
return $sizes;
}
}
根據我的測試,沒有任何問題的工作,雖然我沒有試圖檢查它如何票價與流行的畫廊/媒體外掛。
相關獎金:一個原始實用程式刪除所有 WordPress 生成的縮圖 delete_deprecated_thumbs.php
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。