Opencart Gmail SMTP Ayarları (Güncel 2022)


Opencart mail ayarlarınızda GMAIL hesabınızı kullanmak istiyorsanız aşağıdaki adımları sırayla uygulayın:

1. Opencart Admin Ayarları:
  • E-Posta Protokol: SMTP Mail
  • SMTP Host Adı: ssl://smtp.gmail.com
  • SMTP Kullanıcı Adı: your_mail_address@gmail.com
  • SMTP Parola: your_password
  • SMTP Port: 465
  • SMTP Zaman Aşımı: 60

2. Gmail Güvenlik Ayarları:




Bu ayarlardan sonra artık hazırsınız. Mağazanızdan deneme yapabilirsiniz. Üye olarak, sipariş durumunu güncelleyerek, yorum yazarak, ..vb bir işlem ile sistemin mail göndermesini test ediniz. Mümkünse farklı birkaç mail adresi ile test ediniz (gmail, hotmail, icloud, yahoo, ...vb).

Son Güncelleme: 28/12/2021

Terminal - Autocomplete Eklentisi




Terminal'de bir komut yazarken otomatik tamamlama önerileri almak ister misiniz? Bunun için iki yöntem vereceğim fakat benim tercihim birincisidir (popup autocomplete). Tabiki ikisini aynı zamanda kullanabilirsiniz.

1. Popup Autocomplete


Popup pencere içinde komut önerilerini listeleyen harika bir eklenti. fig.io adresinden eklentinin sayfasına ulaşabilirsiniz.


2. Standard Autocomplete


MacOs işletim sisteminde input autocomplete varsayılan olarak kapalıdır. Bu özelliği açarsanız komutun birkaç harfini yazıp "tab" tuşuna bastığınızda otomatik tamamlanır. Örneğin "cd des" + Tab yaptığınızda otomatik olarak "cd desktop" olacaktır. Tabiki burada birkaç farklı sonuç listelenmiyor, yada komut önerisi/yardımcısı gibi bir tamamlama yapmıyor. Yine de faydalı bir özellik ve açmak isterseniz terminalde sırayla şu işlemleri yapınız:

nano ~/.inputrc

.inputrc dosyası nano (terminal editörü) editöründe açılacaktır. (Bu dosya Users/KulanıcıAdınız/.inputrc konumundadır ve gizlidir. Farklı bir editörle bu dosyayı açarak da yapabilirsiniz. Eğer bu dosya yok ise kendiniz oluşturunuz.) Ardından aşağıdaki satırları kopyalayıp .inputrc dosyasına ekleyin ve kaydedip çıkın (kntrl + x tuşlarına basın ve kaydedilsin mi sorusuna Y ile cevap verin).

set completion-ignore-case on
set show-all-if-ambiguous on
TAB: menu-complete

Terminalden çıkıp tekrar açınız. Artık cd des yazıp tab tuşuna basarak deneyebilirsiniz.

Opencart'da "Error while sending QUERY packet. PID=" Hatası ve Çözümü


PHP Warning:  Error while sending QUERY packet. PID=29811 in /public_html/system/library/db/mpdo.php on line 57 gibi bir hata alıyorsanız bunun nedeni sorgulamalarınızın izin verilen maksimum değeri geçmesi olabilir. 

Bu hatanın çözümü için, ilgili dosyaya (system/library/db/mpdo.php) aşağıdaki satırı eklemenizi öneririm:
$this->connection->exec("SET GLOBAL max_allowed_packet=524288000");

Ben bu şekilde sorunu çözdüm. Kodu eklediğinizde aşağıdaki gibi olacaktır:

public function __construct($hostname, $username, $password, $database, $port = '3306') {
    try {
        $this->connection = new \PDO("mysql:host=" . $hostname . ";port=" . $port . ";dbname=" . $database, $username, $password, array(\PDO::ATTR_PERSISTENT => true));
    } catch(\PDOException $e) {
        throw new \Exception('Failed to connect to database. Reason: \'' . $e->getMessage() . '\'');
    }

    $this->connection->exec("SET NAMES 'utf8'");
    $this->connection->exec("SET CHARACTER SET utf8");
    $this->connection->exec("SET CHARACTER_SET_CONNECTION=utf8");
    $this->connection->exec("SET SQL_MODE = ''");
    $this->connection->exec("SET GLOBAL max_allowed_packet=524288000");
}


Opencart Ajax Filter by Dreamvention


Opencart standart yapısında kullanılışlı bir filtreleme maalesef bulunmuyor. Ajax yani sayfa yenilenmeden filtreleme yapabileceğiniz ücretsiz bir eklenti arıyorsanız Dreamvention tarafından yayınlanan Ajax Filter Free eklentisini öneririm:

MODÜL İÇİN TAVSİYE ETTİĞİM AYARLAR:
Aşağıdaki ayarlar tavsiye niteliğindedir fakat bazı ayarlar modülün çalışmasını direk etkilediği için önemlidir.







GÖRDÜĞÜM HATALAR ve ÇÖZÜMLERİ:

Buradan sonra yazacaklarım Opencart 2.3.0.2 versiyonu ve eklentisi için geçerlidir, diğer versiyonlarda benzer sorunlar mevcut ise uygulayabilirsiniz. 

Sorun 1: Bir kategori sayfasını açtınız diyelim ve hiç beklemeden menüden başka bir kategoriye tıkladınız. Bu durumda hala ilk tıkladığınız kategorinin ürünlerini görmeye devam ediyorsanız, bunun nedeni Ajax Filter eklentisinin veritabanındaki TEMP tablodan işlem yapmasıdır. Arada az zaman geçtiği için hala eski sorgudaki ürünleri listelemektedir.

Çözüm: Eklentiyi indirip kurduktan sonra aşağıdaki kodları bir xml dosyası olarak kaydedip vqmod/xml klasörünüze ekleyiniz. Vqmod kullanmıyorsanız ilgili dosyalardan bu değişiklikleri manuel olarak yapabilirsiniz. Burada HTTP_USER_AGENT hatası ile ilgili ek olarak bir düzeltme daha var, onu da eklemenizi tavsiye ederim.
  <file path="catalog/controller/extension/module/d_ajax_filter.php">
  <operation info="HTTP_USER_AGENT error">
      <search><![CDATA[if (preg_match('/(iPhone|iPod|iPad|Android|Windows Phone)/', $this->request->server['HTTP_USER_AGENT'])) {]]></search>
      <add position="replace"><![CDATA[
      if ( isset($this->request->server['HTTP_USER_AGENT']) && preg_match('/(iPhone|iPod|iPad|Android|Windows Phone)/', $this->request->server['HTTP_USER_AGENT']) ) {
      ]]></add>
  </operation>
  </file>
  <file path="catalog/model/extension/module/d_ajax_filter.php">
  <operation info="fix temp database">
      <search><![CDATA[$this->db->query($sql);]]></search>
      <add position="before" index="1"><![CDATA[
      $this->db->query("DROP TEMPORARY TABLE IF EXISTS `".DB_PREFIX."af_temporary`");
      ]]></add>
  </operation>
  </file>

Sorun 2: "Kurdum, ayarlamaları yaptım, fakat ajax mode çalışmıyor. Yani filtreleme yaptığımda hiçbir değişiklik olmuyor." diyorsanız bunun nedeni muhtemelen modülün ayarlarında bulunan Content Path'in doğru girilmemesidir. Burada bir jquery seçici girilmiştir. Fakat sizin temanıza ait kategori listeleme sayfasında bu id'ye sahip bir div elemanı bulunmadığı için ajax modu çalışmamaktadır.

Çözüm: Kendi temanıza ait kategori listeleme sayfasını açın ve <div id="content"> elemanından sonra gelen ilk div'e ait id'yi bulup buraya girin. Bu düzenlemeyi yukarıdaki modül ayarlarına ait resimlerde görebilirsiniz.

PHP Fonksiyonu Çağıran Sayfa Bilgilerini Almak

debug_backtrace()

Php'de fonksiyon ve metodlar çeşitli sayfalardan çağrılabilir. Bir hata durumunda metoda parametre gönderen sayfayı görmek isteyebilirsiniz. Bu gibi hata ayıklama durumlarında kullanabileceğiniz debug_backtrace fonksiyonu için aşağıdaki kodu kullanabilirsiniz.

$trace = debug_backtrace();
$caller = array(
    "file" => $trace[1]['file'],
    "line" => $trace[1]['line'],
    "function" => $trace[1]['function'],
    "class" => $trace[1]['class'],
);
var_dump( $caller );

ÖNEMLİ NOT: Burada dikkat etmeniz gereken husus; direk olarak var_dump( debug_backtrace() ) şeklinde kullanarak bütün sonucu bastırmamanızdır. Projenize göre değişmekle birlikte MB'larca bir sonuç döndürebilir. Bu nedenle dizideki 4 değeri çıktı olarak almanızı öneririm.

var_dump yerine error dosyasına yazdırmak için var_error_log($caller) kullanabilirsiniz.

CSS Opacity Kullanımı - Tüm Tarayıcılar


CSS Opacity - All Browsers

Eğer çok eski tarayıcıları desteklesin gibi bir derdiniz yoksa kısaca şu 3 satır işinizi görecektir. Tavsiye edilen kullanımdır. zoom ve filter komutları IE içindir (başımızın belası:))
zoom: 1;
filter: alpha(opacity=85);
opacity: 0.85;

Eğer önemli bir projeniz var ve tüm tarayıcılarda sorunsuz görünmesi gerekiyorsa (en eski tarayıcılarda dahi) o zaman bu uzun versiyonu kullanmanız tavsiye edilir.
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; /* IE 8 */
filter: alpha(opacity=85);  /* IE 5-7 */
-moz-opacity: 0.85; /* Netscape */
-khtml-opacity: 0.85; /* Safari 1.x */
opacity: 0.85; /* Good browsers */

Opencart PHP Zip & Download (Ajax Method)


Opencart sayfasındaki bir butona tıklayarak dosyaları indirmek için ajax metodunu kullanabilirsiniz. Bunun için controller ve view dosyalarına ekleyeceğiniz kodlar aşağıdadır.

Controller:
public function downloadAllFiles() {
    $json = array();

    $zip_files = array(
        "file-1.jpg",
        "file-2.jpg",
        "file-3.jpg",
    );
    
    if ( count($zip_files) > 0 ) {
        $zipname = "indir.zip";
        $zip = new ZipArchive;
        $zip->open($_SERVER['DOCUMENT_ROOT']."/store/image/download/".$zipname, ZipArchive::CREATE);
        foreach ($zip_files as $file) {
          $zip->addFile($_SERVER['DOCUMENT_ROOT']."/store/image/download/".$file, $file);
        }
        $zip->close();

        //success and send zip file path
        $json['success'] = 'https://example.com/store/image/download/'.$zipname;
        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }
    else {
        $json['error'] = "İndirilecek dosya bulunamadı! Lütfen kontrol ediniz.";
        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }
}

View:
<!-- Add Download Button -->
<button id="btn-download-zip" data-loading-text="<?php echo $text_downloading; ?>" class="btn btn-info"><?php echo $text_download; ?> <i class="fa fa-download"></i></button>

<!-- Add Ajax Script -->
<script type="text/javascript">
    $(document).delegate('#btn-download-zip', 'click', function() {
        $.ajax({
            url: 'index.php?route=sale/order/downloadallfiles',
            type: 'post',
            dataType: 'json',
            beforeSend: function() {
                $('#btn-download-zip').button('loading');
            },
            complete: function() {
                $('#btn-download-zip').button('reset');
            },
            success: function(json) {
                $('.alert').remove();

                if (json['error']) {
                    $('#content > .container-fluid').prepend('<div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> ' + json['error'] + '</div>');
                }
                else {
                    //download zip file
                    window.location.href = json['success'];
                }
            },
            error: function(xhr, ajaxOptions, thrownError) {
                alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
            }
        });
    });
</script>