web-dev-qa-db-ja.com

カスタムアップロードディレクトリの各カスタム画像サイズは?

カスタム画像サイズをカスタムフォルダにアップロードしたいのですが。フォルダは選択された幅の名前を持つべきです。例えば:

これらのカスタムサイズを追加すると...

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 フィルタで変更できることがわかりました。

11
Philipp Kühn

Philipp、考えを決めれば何でも可能です。あなたはWordPress画像エディタクラスを拡張することによってあなたの問題を解決することができます。

メモWordPress 3.7を使用しています - 以前のバージョンおよび最新の3.8リリースでは、以下のコードを確認していません。


画像エディタの基本

WordPressには、画像操作を処理する2つの組み込みクラスがあります。

  • WP_Image_Editor_Gd/wp-includes/class-wp-image-editor-Gd.php
  • WP_Image_Editor_Imagick/wp-includes/class-wp-image-editor-imagick.php

これら2つのクラスは、両方とも異なるイメージエンジン(それぞれGdとImageMagick)を使用してイメージのロード、サイズ変更、圧縮、および保存を行うので、WP_Image_Editorを拡張します。

デフォルトでは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;
}

WordPressは他のエンジンをテストする前に私たちのエンジンがリサイズを処理できるかどうかチェックするので私たちはprepending私たちのカスタム画像エディタクラスWP_Image_Editor_Customです。


画像エディタを作成する

今、私たちは自分自身でファイル名を決めることができるように私たち自身の画像エディタを書くつもりです。ファイル名はWP_Image_Editor::generate_filename()メソッド(両方のエンジンがこのメソッドを継承する)によって処理されるので、カスタムクラスでそれを上書きする必要があります。

ファイル名の変更のみを計画しているので、既存のエンジンの1つを拡張する必要があります。そうすれば、ホイールを再発明する必要はありません。 ImageMagick拡張機能が有効になっていない可能性があるため、この例ではWP_Image_Editor_Gdを拡張します。ただし、このコードは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 x 300)よりも小さい場合、生成されるサフィックス(この場合はプレフィックス)と画像サイズは300 x 300ではなく280 x 300です。たくさんの小さな画像をアップロードすると、たくさんのフォルダができます。

適切な解決策は、サイズスラッグをフォルダ名として使用するか(smallmediumなど)、またはコードを最も近い優先イメージサイズに切り上げることです。

あなたはあなたがディレクトリ名として幅だけを使用したいと思いました。ただし注意してください - プラグインやテーマは、幅は同じで高さが異なる2つの異なるサイズを生成する可能性があります。

また、[設定]> [メディア]で[アップロードを月ベースおよび年ベースのフォルダに整理する]を無効にするか、さらにgenerate_filenameを操作して、年/月フォルダを削除することもできます。

お役に立てれば。がんばろう!

21
Robbert

@ 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+x\d+\.#', '.', $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

3
Arty2

私はWordPressのコードのこれらの部分を見ました、そして私は少しも良いニュースがないのですが。

2つのクラスがあります。

  • WP_Image_Editor_Gd
  • WP_Image_Editor_Imagick

どちらも抽象WP_Image_Editorクラスを拡張しています。

これらのクラスは、アップロードされた画像から複数の画像を生成するために使用されるmulti_resizeメソッドを実装しています。

本当に悪いニュースはそこにフィルタフックがないということです、我々が新しく作成されたファイルのために目的地パスを修正するのに使用できるということです。

1

さて、私はそれを手に入れたと思います!完璧ではありませんが、私はそれを望んでいたこのために大丈夫です。私にとっては、画像の幅だけが重要です。高さは私には無用です。特に Imager.jsを実装する場合 画像のURLの高さが邪魔になります。

add_filter('image_make_intermediate_size', 'custom_rename_images');

function custom_rename_images($image) {
    // Split the $image path
    $info = pathinfo($image);
    $dir = $info['dirname'] . '/';
    $ext = '.' . $info['extension'];
    $name = wp_basename($image, '$ext');

    // New Name
    $name_prefix = substr($name, 0, strrpos($name, '-'));
    $size_extension = substr($name, strrpos($name, '-') + 1);
    $image_sizes = explode('x', $size_extension);
    $image_width = $image_sizes[0];
    $new_name = $dir . $image_width . '-' . $name_prefix . $ext;

    // Rename the intermediate size
    $did_it = rename($image, $new_name);

    // Return if successful
    if ($did_it) return $new_name;

    // Return on fail
    return $image;
}

このコードでは、ファイル名は次のようになります。

http://www.my-site.com/wp-content/uploads/300-my-image.jpg
http://www.my-site.com/wp-content/uploads/400-my-image.jpg

サブフォルダをファイル名に追加することは not 可能です。なぜなら私がpost/pageに画像を追加する場合は常にオリジナルのソースが代わりに使用されるからです。削除時にこれらの画像を削除しても機能しません。その理由はわかりません。

1
Philipp Kühn