Takip et

Drush Komutlarının Yapısı ve Anatomisi

Drush, Drupal geliştiricilerinin ve sistem yöneticilerinin günlük işlerini otomatikleştirmek, yönetmek ve hızlandırmak için kullandığı

Drush, Drupal geliştiricilerinin ve sistem yöneticilerinin günlük işlerini otomatikleştirmek, yönetmek ve hızlandırmak için kullandığı güçlü bir komut satırı aracıdır. Drupal sitenizle etkileşim kurmanın ve karmaşık görevleri tek bir komutla yerine getirmenin vazgeçilmez bir yoludur. Ancak Drush’ın gücü sadece mevcut komutlarla sınırlı değildir; kendi özel ihtiyaçlarınıza yönelik komutlar tanımlayarak bu aracı daha da özelleştirebilirsiniz. Bu rehberde, bir VPS (Virtual Private Server) ortamında kendi Drush komutlarınızı nasıl bildireceğinizi, geliştireceğinizi ve kullanacağınızı adım adım öğreneceksiniz.

Özel Drush komutları, tekrarlayan görevleri otomatikleştirmek, karmaşık iş akışlarını basitleştirmek, özel raporlar oluşturmak veya Drupal API’si ile etkileşim kuran benzersiz yönetim görevleri tanımlamak için mükemmel bir yöntemdir. Kendi sunucunuzda (VPS) bu komutları geliştirmek ve çalıştırmak, size tam kontrol ve esneklik sağlar.

Drush Komutlarının Yapısı ve Anatomisi

Bir Drush komutu, temelde bir Drupal modülünün parçası olarak tanımlanan bir PHP sınıfıdır. Bu sınıf, belirli metodları Drush komutları olarak ortaya çıkarır. Drush, bu komutları bulmak için modüllerin src/Commands dizinini tarar ve drush.services.yml dosyasında tanımlanan servisleri kullanır.

Temel Bileşenler:

  • Modül Dizini: Özel komutlarınız, modules/custom altında kendi modülünüz içinde yer almalıdır.
  • drush.services.yml: Bu dosya, Drush’a komut sınıfınızın nerede olduğunu ve nasıl yükleneceğini bildirir.
  • Komut Sınıfı (.php dosyası): Asıl komut mantığını içeren PHP sınıfıdır. Genellikle src/Commands dizini altında bulunur ve \Drush\Commands\DrushCommands sınıfını extend eder.
  • Anotasyonlar: Komut metodlarının üzerinde kullanılan özel yorum bloklarıdır. Bunlar Drush’a komutun adını, açıklamasını, argümanlarını, seçeneklerini ve diğer metadata’yı bildirir (örn. @command, @usage, @option, @argument).

Bu yapıyı anlamak, kendi komutlarınızı geliştirirken size yol gösterecektir. Şimdi adım adım bir örnek modül oluşturalım.

Özel Drush Komut Modülü Oluşturma

Kendi Drush komutlarınızı bildirmek için, standart bir Drupal modülü oluşturmanız ve içine Drush’ın tanıyacağı belirli dosyaları yerleştirmeniz gerekir. Aşağıdaki adımları VPS’inizin SSH terminalinde takip edebilirsiniz.

Aşama 1: Modül Dizini Yapısı Oluşturma

Drupal kurulumunuzun ana dizininde (genellikle /var/www/html/drupal veya benzeri bir yer), özel modülleriniz için bir dizin oluşturun ve ardından komutlarınızı içerecek modülünüzü oluşturun. Örneğin, mymodule adında bir modül oluşturacağız:

cd /var/www/html/drupal/web # Drupal kök dizinine gidin
mkdir -p modules/custom/mymodule/src/Commands

Bu komut, mymodule için gerekli dizin yapısını oluşturur: modules/custom/mymodule ve komut sınıfımızın yer alacağı src/Commands.

Aşama 2: mymodule.info.yml Dosyası Oluşturma

Her Drupal modülü gibi, özel Drush komut modülünüzün de bir .info.yml dosyasına ihtiyacı vardır. Bu dosya, Drupal’a modülünüz hakkında temel bilgileri sağlar.

# modules/custom/mymodule/mymodule.info.yml
name: 'My Custom Drush Commands'
type: module
description: 'Provides custom Drush commands for specific tasks.'
core_version_requirement: ^9 || ^10
package: 'Custom'

Bu dosyayı modules/custom/mymodule/mymodule.info.yml yoluna kaydedin.

Aşama 3: drush.services.yml Dosyası Oluşturma

Bu dosya, Drush’a komut sınıfınızın bir servis olarak nasıl yükleneceğini bildirir. Bu, Drush’ın komutlarınızı bulması ve çalıştırması için kritik öneme sahiptir.

# modules/custom/mymodule/drush.services.yml
services:
  mymodule.commands:
    class: Drupal\mymodule\Commands\MyModuleCommands
    tags:
      - { name: drush.command }

Bu dosyayı modules/custom/mymodule/drush.services.yml yoluna kaydedin. class anahtarı, komut sınıfınızın tam nitelikli adını (namespace dahil) belirtir. tags: - { name: drush.command } kısmı ise Drush’a bu servisin bir Drush komut servisi olduğunu söyler.

Aşama 4: Komut Sınıfını Yazma (src/Commands/MyModuleCommands.php)

Şimdi asıl komut mantığımızı içeren PHP sınıfını oluşturalım. Bu sınıf, DrushCommands sınıfını extend etmeli ve komut metodlarını içermelidir.


 * Defines Drush commands for the MyModule module.
 */
class MyModuleCommands extends DrushCommands {

  /
   * Says hello to the user.
   *
   * @command mymodule:hello
   * @aliases mh
   * @usage mymodule:hello
   *   Says hello to the current user.
   */
  public function hello() {
    $this->say("Merhaba, Drush komutları dünyasına hoş geldiniz!");
  }

  /
   * Greets a specified person.
   *
   * @command mymodule:greet
   * @param string $name The name of the person to greet.
   * @option string $salutation The salutation to use (e.g., "Hello", "Hi").
   * @aliases mg
   * @usage mymodule:greet John --salutation="Selam"
   *   Greets John with a custom salutation.
   */
  public function greet($name, $options = ['salutation' => 'Merhaba']) {
    $salutation = $options['salutation'];
    $this->say("$salutation, $name!");
  }

}

Bu dosyayı modules/custom/mymodule/src/Commands/MyModuleCommands.php yoluna kaydedin.

  • namespace Drupal\mymodule\Commands;: Modülünüzün namespace’ini tanımlar.
  • use Drush\Commands\DrushCommands;: Drush komutları için temel sınıfı import eder.
  • class MyModuleCommands extends DrushCommands: Komut sınıfımızın DrushCommands sınıfından türetildiğini belirtir.
  • @command mymodule:hello: Bu anotasyon, hello() metodunu mymodule:hello olarak çağrılabilecek bir Drush komutu olarak tanımlar.
  • @aliases mh: Komut için kısa bir takma ad tanımlar.
  • @usage: Komutun nasıl kullanılacağına dair bir örnek sunar.
  • $this->say(): Drush’ın çıktıyı kullanıcıya göstermek için kullandığı standart bir metottur.
  • @param ve @option: Komutun alacağı argümanları ve seçenekleri tanımlar. Drush, bu anotasyonlara göre komut satırı girdilerini otomatik olarak PHP metodunuzdaki parametrelerle eşleştirir.

Gelişmiş Komut Özellikleri ve Pratik Kullanım

Sadece basit mesajlar göstermek yerine, Drush komutlarınızı Drupal API’si ile etkileşim kurarak çok daha güçlü hale getirebilirsiniz.

Servis Enjeksiyonu

Drush komut sınıflarınızda, Drupal’ın servislerini (veritabanı, yapılandırma, varlık yöneticisi vb.) kullanmak oldukça yaygındır. Bunu yapmak için constructor injection (yapıcı enjeksiyonu) kullanmalısınız.


 * Defines Drush commands for the MyModule module with service injection.
 */
class MyModuleCommands extends DrushCommands {

  /
   * The logger channel factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $loggerFactory;

  /
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /
   * Constructs a MyModuleCommands object.
   *
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
   *   The logger channel factory.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(LoggerChannelFactoryInterface $logger_factory, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct();
    $this->loggerFactory = $logger_factory;
    $this->entityTypeManager = $entity_type_manager;
  }

  /
   * Creates a test node.
   *
   * @command mymodule:create-test-node
   * @option string $title The title of the node.
   * @aliases mctn
   * @usage mymodule:create-test-node --title="My Test Node"
   *   Creates a new 'article' node with the given title.
   */
  public function createTestNode($options = ['title' => 'Default Test Node Title']) {
    try {
      $node = $this->entityTypeManager->getStorage('node')->create([
        'type' => 'article',
        'title' => $options['title'],
        'uid' => 1, // Admin user
        'status' => 1, // Published
      ]);
      $node->save();
      $this->say("Yeni makale oluşturuldu: " . $node->getTitle() . " (NID: " . $node->id() . ")");
      $this->loggerFactory->get('mymodule')->info('Yeni makale oluşturuldu: {title} (NID: {nid})', [
        'title' => $node->getTitle(),
        'nid' => $node->id(),
      ]);
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('mymodule')->error('Makale oluşturulurken hata oluştu: {message}', ['message' => $e->getMessage()]);
      $this->say("Hata: " . $e->getMessage());
    }
  }

}

Yukarıdaki örnekte:

  • LoggerChannelFactoryInterface ve EntityTypeManagerInterface servisleri, yapıcı metot (__construct) aracılığıyla enjekte edilir.
  • createTestNode komutu, EntityTypeManagerInterface kullanarak yeni bir “article” (makale) içerik tipi oluşturur.
  • LoggerChannelFactoryInterface kullanılarak Drupal loglarına mesajlar yazılır. Bu, hata ayıklama ve denetim için çok önemlidir.

Veritabanı İşlemleri

Doğrudan veritabanı sorguları çalıştırmak için \Drupal::database() servisini kullanabilirsiniz. Ancak mümkün olduğunca Drupal’ın Entity API’sini veya Query API’sini kullanmanız önerilir, çünkü bu daha güvenli ve geleceğe dönük bir yaklaşımdır.

  /
   * Updates a specific field for a node.
   *
   * @command mymodule:update-node-status
   * @param int $nid The node ID to update.
   * @param int $status The new status (0 for unpublished, 1 for published).
   * @usage mymodule:update-node-status 5 0
   *   Unpublishes node with NID 5.
   */
  public function updateNodeStatus($nid, $status) {
    if (!is_numeric($nid) || !is_numeric($status) || ($status != 0 && $status != 1)) {
      $this->logger()->error('Geçersiz NID veya durum girildi.');
      return;
    }

    try {
      $node = $this->entityTypeManager->getStorage('node')->load($nid);
      if (!$node) {
        $this->say("NID $nid bulunamadı.");
        return;
      }
      $node->set('status', (bool) $status);
      $node->save();
      $this->say("NID $nid durumu güncellendi: " . ($status ? 'Yayınlandı' : 'Yayınlanmadı'));
    }
    catch (\Exception $e) {
      $this->logger()->error('Düğüm durumu güncellenirken hata oluştu: {message}', ['message' => $e->getMessage()]);
      $this->say("Hata: " . $e->getMessage());
    }
  }

Bu örnek, entityTypeManager kullanarak belirli bir düğümün yayınlanma durumunu günceller. Bu, doğrudan SQL sorguları yazmaktan daha güvenli ve Drupal’ın varlık yaşam döngüsüne uygun bir yoldur.

Kullanıcıdan Girdi Alma

Komutlarınızı interaktif hale getirmek için kullanıcıdan girdi alabilirsiniz:

  /
   * Asks for user confirmation.
   *
   * @command mymodule:confirm-action
   * @usage mymodule:confirm-action
   *   Asks the user for confirmation before proceeding.
   */
  public function confirmAction() {
    if ($this->io()->confirm('Bu işlemi yapmak istediğinizden emin misiniz?')) {
      $this->say('İşlem onaylandı. Devam ediliyor...');
      // Gerçek işlemi burada yapın.
    } else {
      $this->say('İşlem iptal edildi.');
    }
  }

$this->io()->confirm() metodu, kullanıcıya bir soru sorar ve “evet” veya “hayır” yanıtına göre boolean bir değer döndürür.

VPS Ortamında Komutları Test Etme ve Dağıtma

VPS’inizde komutları oluşturduktan sonra, bunları etkinleştirmeniz ve test etmeniz gerekir.

Modülü Etkinleştirme

Drush komutlarınızın Drupal tarafından tanınması için öncelikle modülünüzü etkinleştirmeniz gerekir:

drush en mymodule -y

Bu komut, mymodule‘ü etkinleştirir. -y seçeneği, onay istemlerini atlar.

Drush Önbelleğini Temizleme

Yeni Drush komutları ekledikten veya mevcut komutları değiştirdikten sonra Drush’ın önbelleğini temizlemek mutlaka gereklidir. Aksi takdirde Drush yeni komutlarınızı bulamaz.

drush cr

Komutu Çalıştırma

Artık komutlarınızı çalıştırabilirsiniz:

drush mymodule:hello
drush mymodule:greet 'Alice' --salutation='Hello there'
drush mymodule:create-test-node --title="My Drush Node"
drush mymodule:update-node-status 10 0 # NID 10'u yayınlamadan kaldır
drush mymodule:confirm-action

Tüm mevcut Drush komutlarınızı görmek için drush list komutunu kullanabilirsiniz. Kendi komutlarınız da bu listede yer almalıdır.

Hata Ayıklama İpuçları

  • drush cr: Yeni kod değişikliklerinden sonra her zaman önbelleği temizleyin.
  • PHP Hata Kayıtları: VPS’inizin PHP hata kayıtlarını (genellikle /var/log/apache2/error.log veya /var/log/nginx/error.log gibi bir yerde) kontrol edin.
  • Drush Hata Ayıklama: drush -vvv mymodule:my-command komutu, daha ayrıntılı çıktı vererek sorunları tespit etmenize yardımcı olabilir.
  • $this->logger()->error(): Komutlarınızda hata mesajlarını Drupal’ın log sistemine yazmak, sorunları izlemek için en iyi yöntemdir.

Dağıtım Stratejileri

VPS ortamında, özel Drush komut modüllerinizi dağıtmak için genellikle Git tabanlı bir iş akışı kullanılır. Modülünüzü bir Git deposuna ekleyin ve sunucunuzda bu depoyu çekerek güncellemeleri uygulayın. Dağıtım sonrası her zaman drush en mymodule -y (ilk dağıtım için) ve drush cr komutlarını çalıştırmayı unutmayın.

Sonuç

Kendi Drush komutlarınızı tanımlamak, Drupal geliştirme ve yönetim süreçlerinizde size inanılmaz bir güç ve esneklik sağlar. Bu rehberde öğrendiğiniz adımları takip ederek, tekrarlayan görevleri otomatikleştirebilir, Drupal API’si ile derinlemesine etkileşim kurabilir ve VPS ortamınızda verimliliğinizi artırabilirsiniz. Drush’ın sunduğu imkanları keşfetmekten çekinmeyin ve kendi özel çözümlerinizi yaratın.

Sıkça Sorulan Sorular (SSS)

1. Drush komutum neden çalışmıyor?

En yaygın nedenler şunlardır: modülünüz etkinleştirilmemiştir (drush en mymodule -y), Drush önbelleği temizlenmemiştir (drush cr), drush.services.yml dosyanızda veya komut sınıfınızın namespace’inde/adında bir hata vardır. Ayrıca PHP sözdizimi hataları da komutun yüklenmesini engelleyebilir; PHP hata günlüklerinizi kontrol edin.

2. Komutuma nasıl parametre veya seçenek eklerim?

@param anotasyonu ile zorunlu argümanları (örneğin mymodule:greet ) ve @option anotasyonu ile isteğe bağlı seçenekleri (örneğin mymodule:greet --salutation="Hello") tanımlayabilirsiniz. Metod imzasında bunları PHP parametreleri olarak belirtmeniz gerekir.

3. Veritabanı ile nasıl etkileşim kurarım?

Doğrudan SQL sorguları için \Drupal::database() servisini kullanabilirsiniz. Ancak Drupal’ın varlıklarını (node, user vb.) değiştirmek veya oluşturmak için EntityTypeManagerInterface servisini kullanmak daha güvenli ve önerilen yöntemdir. Yapıcı enjeksiyonu ile bu servisi komut sınıfınıza dahil edebilirsiniz.

4. Komutumu başka bir modülden veya koddan çağırabilir miyim?

Evet, Drush komutlarınızı doğrudan PHP kodunuzdan çağırabilirsiniz. Bunun için Drush\Drush::drush() statik metodunu kullanabilirsiniz. Örneğin: Drush\Drush::drush('mymodule:hello');. Ancak, bir komutun mantığını başka bir yerden çağıracaksanız, o mantığı ayrı bir servise taşıyıp hem Drush komutundan hem de diğer koddan bu servisi kullanmak daha iyi bir tasarım pratiğidir.

5. Drush komutları güvenli midir?

Drush komutları genellikle sunucuya SSH erişimi olan yetkili kullanıcılar tarafından çalıştırıldığı için güvenlik riski düşüktür. Ancak, komutlarınızı yazarken her zaman güvenlik en iyi uygulamalarını (girdi doğrulama, yetkilendirme kontrolü, doğru API kullanımı) takip etmelisiniz. Asla doğrudan kullanıcı girdisini SQL sorgularına enjekte etmeyin.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Mobil sürümden çık