Özel yükleme dizinindeki her özel resim boyutu?


11

Özel resim boyutlarımı özel klasörlere yüklemek istiyorum. Klasör, seçilen genişlik adına sahip olmalıdır. Örneğin:

Bu özel boyutları eklersem ...

add_image_size('custom-1', 300, 9999);
add_image_size('custom-2', 400, 9999);

Yüklenen görüntülerin şu şekilde yüklenmesi iyi olurdu:

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

Mümkün mü? Sadece upload_dir filtresi ile global upload klasörünü değiştirebileceğimi buldum .

Yanıtlar:


21

Philipp, fikrini ona koyarsan her şey mümkün. WordPress resim düzenleyici sınıfını genişleterek sorununuzu çözebilirsiniz.

Not WordPress 3.7 kullanıyorum - Önceki kodlarda ve en son 3.8 sürümünde aşağıdaki kodlardan herhangi birini kontrol etmedim.


Image Editor ile ilgili temel bilgiler

WordPress, görüntü manipülasyonunu işleyen iki yerleşik sınıfa sahiptir:

  • WP_Image_Editor_GD( /wp-includes/class-wp-image-editor-gd.php)
  • WP_Image_Editor_Imagick( /wp-includes/class-wp-image-editor-imagick.php)

Bu iki sınıf WP_Image_Editor, her ikisi de görüntüleri yüklemek, yeniden boyutlandırmak, sıkıştırmak ve kaydetmek için farklı bir görüntü motoru (sırasıyla GD ve ImageMagick) kullandığından uzar.

WordPress varsayılan olarak, PHP eklentisine ihtiyaç duyan ImageMagick motorunu ilk önce kullanmaya çalışır, çünkü genellikle PHP'nin varsayılan GD motoruna tercih edilir. Çoğu paylaşılan sunucuda ImageMagick uzantısı etkin değildir.


Resim Düzenleyici Ekle

Hangi motorun kullanılacağına karar vermek için WordPress dahili bir işlevi çağırır __wp_image_editor_choose()(içinde bulunur /wp-includes/media.php). Bu işlev, hangi motorun isteği işleyebileceğini görmek için tüm motorlarda dolaşır.

İşlev ayrıca şöyle bir wp_image_editorsgörüntü düzenleyicisi eklemenize izin veren bir filtreye sahiptir :

add_filter("wp_image_editors", "my_wp_image_editors");
function my_wp_image_editors($editors) {
    array_unshift($editors, "WP_Image_Editor_Custom");

    return $editors;
}

Biz ediyoruz Not prepending bizim özel resim editörü sınıfı WP_Image_Editor_Custombizim motor diğer motorlar test etmeden önce yeniden boyutlandırma işleyebilir eğer WordPress kontrol edecek, böylece.


Resim Düzenleyicimizi oluşturma

Şimdi kendi görüntü düzenleyicimizi yazacağız, böylece dosya adlarına kendimiz karar verebiliriz. Dosya adlandırma yöntemi tarafından kullanılır WP_Image_Editor::generate_filename()(her iki motor da bu yöntemi devralır), bu nedenle özel sınıfımızda bunun üzerine yazmalıyız .

Yalnızca dosya adlarını değiştirmeyi planladığımız için, mevcut motorlardan birini genişletmeliyiz, böylece tekerleği yeniden icat etmek zorunda değiliz. Ben uzatacaktır WP_Image_Editor_GDmuhtemelen ImageMagick uzantısı etkin olmayan, benim örnekte. Kod bir ImageMagick kurulumu için değiştirilebilir. Temayı farklı kurulumlarda kullanmayı planlıyorsanız her ikisini de ekleyebilirsiniz.

// 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}";
    }
}

Yukarıdaki kodun çoğu doğrudan WP_Image_Editorsınıftan kopyalanmış ve size kolaylık olması için yorumlanmıştır. Tek gerçek değişiklik, son ekin artık bir önek olmasıdır.

Alternatif olarak, sadece soneki bir önek haline getirmek parent::generate_filename()için bir çağırabilir ve kullanabilirsiniz mb_str_replace(), ancak yanlış gitmeye daha meyilli olacağını düşündüm.


Meta verilere yeni yollar kaydetme

Yüklemeden sonra image.jpg, uploads klasörü şöyle görünür:

  • 2013/12/150x150/image.jpg
  • 2013/12/300x300/image.jpg
  • 2013/12/image.jpg

Çok uzak çok iyi. Ancak, gibi temel işlevleri çağırırken wp_get_attachment_image_src(), tüm görüntü boyutlarının image.jpgyeni dizin yolu olmadan kaydedildiğini fark edeceğiz .

Yeni klasör yapısını görüntü meta verilerine (dosya adlarının depolandığı yer) kaydederek bu sorunu çözebiliriz. (Çeşitli filtrelerden veri çalışır wp_generate_attachment_metadataönce diğerlerinin yanı sıra) veritabanına sokulmadan, ama biz zaten özel bir görüntü düzenleyici uyguluyorsanız bu yana, görüntü boyutu meta kaynağına geri seyahat edebilirsiniz: WP_Image_Editor::multi_resize(). Bunun gibi diziler üretir:

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()Özel sınıfımızdaki yöntemin üzerine yazacağız :

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;
}

Gördüğünüz gibi, herhangi bir kodu değiştirmek için uğraşmadı. Sadece üst yöntemi çağırıyorum ve meta veri oluşturmasına izin verdim. Sonra ortaya çıkan dizi döngü ve fileher boyut için değeri ayarlamak .

Şimdi wp_get_attachment_image_src($att_id, array(300, 300))geri dönüyor 2013/12/300x300/image.jpg. Yaşasın!


Son düşünceler

Umarım bu sizin üzerinde ayrıntılı bir temel oluşturmuştur. Ancak, bir görüntünün belirtilen boyuttan küçük olması durumunda (örn. 280x300), oluşturulan son ekin (bizim durumumuzdaki önek) ve görüntü boyutlarının 300x300 değil 280x300 olduğunu unutmayın. Çok daha küçük resimler yüklerseniz, birçok farklı klasör elde edersiniz.

Klasör adı (apre sülük kullanmak ya için iyi bir çözüm olacaktır small, mediumve saire) veya en yakın tercih edilen görüntü boyutu yuvarlak boyutları için kodu genişletmek.

Bir dizin adı olarak yalnızca genişliği kullanmak istediğinizi belirttiniz. Ancak uyarılmalıdır - eklentiler veya temalar aynı genişlikte ancak farklı yüksekliklerde iki farklı boyut oluşturabilir.

Ayrıca, yıl / ay klasörlerini Ayarlar> Medya altındaki 'Yüklemelerimi ay ve yıl tabanlı klasörlere düzenle' seçeneğini devre dışı bırakarak veya generate_filenamedaha da ileri giderek kaldırabilirsiniz .

Bu yardımcı olur umarım. İyi şanslar!


3
Ne cevap! : D İyi adam!
Philipp Kühn

1
Rica ederim! En azından biraz OOP ve WP filtre deneyimine sahip olduğunuzu varsayıyordum, ancak henüz anlamadığınız bir şey varsa, sormaya çekinmeyin. Ödül için teşekkürler!
Robbert

2
@Robbert Frankly, bu harika. Medya yükleme sistemindeki eylem ve filtre kancalarının eksikliğiyle saçlarımı yırtıyordum. Geriye dönüp bakıldığında açık gibi görünüyor, ancak görüntü editörlerini tamamen geçersiz kılmak hiç aklıma gelmemişti. Bunu yapmak bir kerede birçok sorunu çözer.
Jonathan Fingland

1
@JonathanFingland Ha, bunun için tavşan deliğinden aşağı doğru gitmek zorunda olduğumu itiraf ediyorum. Yardım etmekten memnun oldum!
Robbert

Küçük not - kodun son huzurunda (genel işlev multi_resize ($ boyutları)) anahtar kelime "genel" web sitesini kapatır. Sadece kaldırın ve tekrar hazır. 2k17 ve cevabınız hala harika, teşekkür ederim !!
Paradoxetion

3

@ Robbert'in cevabı, WordPress tarafından oluşturulan alternatif boyutları ayrı dizinlerde saklamak için yaptığım çabalarda ilahi bir kaynaktı. Kodum ayrıca yükleme dizinini ./media olarak değiştirdiğinden, istemiyorsanız bu satırları düzenlediğinizden emin olun. İlk afişin sorusuna kesin bir cevap değil, aynı soruna alternatif bir çözüm sunuyor:

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;
    }
}

Popüler galeri / medya eklentileri ile nasıl çalıştığını kontrol etmedim, ancak testlerime göre sorunsuz çalışıyor.

ilgili bonus: WordPress tarafından oluşturulan tüm küçük resimleri silmek için ham bir yardımcı program delete_deprecated_thumbs.php


1

WordPress kodunun bu kısımlarına baktım ve korkarım iyi bir haberim yok.

2 sınıf vardır:

  • WP_Image_Editor_GD
  • WP_Image_Editor_Imagick,

her ikisi de soyut WP_Image_Editorsınıfı genişletiyor .

Bu sınıflar, multi_resizeyüklenmiş olandan birden fazla görüntü oluşturmak için kullanılan uygulama yöntemidir.

Gerçekten kötü haber, orada yeni filtre dosyaları için hedef yolunu değiştirmek için kullanabileceğimiz hiçbir filtre kancası bulunmamasıdır.


Bu utanç verici. Güzel Imager.js'yi uygulamak istedim ama muhtemelen onsuz çalışmayacak.
Philipp Kühn

Imager.js, görüntüleri botlara (Google, Facebook, vb.) Görünmez yapar gibi görünüyor , bu nedenle (buna bir noscriptetiket de manuel olarak eklemezseniz ) kullanmamanızı tavsiye ederim
fregante

Hmm hayır sanmıyorum. Normalde bir görüntünün src'si ile img-tags kullanırsınız. Ve diğer resimler-boyutlarda sözdizimi ile ayrıca bir veri etiketi ekleyin: <img src="http://placehold.it/260" data-src="http://placehold.it/{width}" />. Ve sonra komut dosyası img'in hangi boyutta olduğunu kontrol eder ve bunun için en iyi görüntü boyutunu yükler.
Philipp Kühn

@ PhilippKühn Ben de hayal kırıklığına uğradım. Fikriniz oldukça düzgün ve ben yükleme dizini
derlemek

@ KrzysiekDróżdż Hey sanırım anladım. Aşağıdaki cevabıma bak. Bu çözüm ile görüntüleri dosya adına göre ftp ile sıralayabilir ve kullanılmayan görüntü boyutlarını kolayca kaldırabilirsiniz.
Philipp Kühn

1

Tamam, sanırım anladım! Mükemmel değil ama bunun için iyi istedim. Benim için sadece bir görüntünün genişliği önemlidir. Boy benim için işe yaramaz. Özellikle Imager.js'yi uygulamak için resim URL'sindeki yükseklik rahatsız edici.

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;
}

Bu kodla dosya adları şöyledir:

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

O var değil hep orijinal kaynak sonrası / sayfa görüntüleri eklerseniz yerine kullanılır, çünkü dosya için bir alt klasör eklemek mümkündür. Ve silme sırasında bu görüntüleri kaldırmak da çalışmaz. Neden olduğundan emin değilim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.