Web tabanlı bir Satış Noktası (POS) sistemi geliştirmek, en büyük sıkıntılardan birini getirir: Yazdırma.
<p>Eğer daha önce bir web tabanlı fatura uygulaması geliştirdiyseniz, o süreci bilirsiniz. `window.print()` çağrısı yaparsınız, tarayıcı bir yazdırma diyalogu açar, kullanıcı yazıcıyı seçmek zorundadır, belki de kenar boşluklarını ayarlayıp sonunda "Yazdır" tuşuna basar.</p>
<p>Yoğun bir perakende kasiyeri için, her işlemdeki 5 saniyelik gecikme kabul edilemez.</p>
<p>Ben yakın zamanda PagoraPOS adlı bir TALL stack (Tailwind, Alpine, Laravel, Livewire) POS sistemi geliştirdim. Amacım, bunu yerel bir masaüstü uygulaması gibi hissettirmekti. Bu da demek oluyor ki, yazdırma işlemi anlık, sessiz ve termal kağıtta piksel mükemmelliğinde olmalıydı.</p>
<p>İşte bu "Web'den Termal Yazıcıya" zorluğunu PHP kullanarak, tarayıcı diyalogunu tamamen atlayarak nasıl çözdüm.</p>
<p><strong>window.print() ile İlgili Problemler</strong><br/>Standart tarayıcı yazdırması, CSS'e dayanır. Bir sayfayı fatura gibi görünmesi için şekillendirebilirsiniz (genişlik: 80mm), fakat hızla sınırlamaların farkına varırsınız.</p>
<p><strong>Çözüm: Raw ESC/POS Komutları</strong><br/>Termal yazıcılar (Epson, Star, Xprinter) "ESC/POS" adında bir ham dilde konuşurlar. Bir HTML resmi göndermek yerine, hex komutları gönderirsiniz.</p>
<p>Örneğin, `x1B\x40` komutu yazıcıyı başlatır. `x1D\x56\x42\x00` komutu ise kağıdı keser.</p>
<p>PHP ekosisteminde, bu işlemi gerçekleştiren en iyi kütüphane mike42/escpos-php'dir.</p>
<p><strong>> Adım 1: Kurulum</strong><br/>Önce, Laravel projemde kütüphaneyi kurdum:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>composer require mike42/escpos-php<p><strong>> Adım 2: Sunucuda Faturanın Oluşturulması</strong><br/>Bir Blade görünümü render etmek yerine, yazdırma komutlarını oluşturmaktan sorumlu bir Servis Sınıfı oluşturdum.</p>
<p>İşte basitleştirilmiş PrinterService'im:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kn">use</span> <span class="nc">Mike42\Escpos\Printer</span><span class="p">;</span>use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;
use Mike42\Escpos\CapabilityProfile;
class ThermalPrintService
{
public function printReceipt($transaction)
{
// 1. Yazıcıya bağlan (örneğin, LAN’daki Ağ Yazıcısı)
// Gerçek uygulamada, bu IP veritabanı ayarlarından gelir
$connector = new NetworkPrintConnector(“192.168.1.87”, 9100);
<span class="c1">// 2. Profilleri yükle (Epson/Star gibi belirli markalar için optimize eder)</span>
<span class="nv">$profile</span> <span class="o">=</span> <span class="nc">CapabilityProfile</span><span class="o">::</span><span class="nf">load</span><span class="p">(</span><span class="s2">"default"</span><span class="p">);</span>
<span class="c1">// 3. Yazıcıyı başlat</span>
<span class="nv">$printer</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Printer</span><span class="p">(</span><span class="nv">$connector</span><span class="p">,</span> <span class="nv">$profile</span><span class="p">);</span>
<span class="k">try</span> <span class="p">{</span>
<span class="c1">// --- BAŞLIK ---</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">setJustification</span><span class="p">(</span><span class="nc">Printer</span><span class="o">::</span><span class="no">JUSTIFY_CENTER</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">selectPrintMode</span><span class="p">(</span><span class="nc">Printer</span><span class="o">::</span><span class="no">MODE_DOUBLE_WIDTH</span> <span class="o">|</span> <span class="nc">Printer</span><span class="o">::</span><span class="no">MODE_BOLD</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">text</span><span class="p">(</span><span class="s2">"PAGORA STORE</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">selectPrintMode</span><span class="p">();</span> <span class="c1">// Sıfırla</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">text</span><span class="p">(</span><span class="s2">"123 Laravel Blvd, Code City</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">feed</span><span class="p">();</span>
<span class="c1">// --- ÜRÜNLER ---</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">setJustification</span><span class="p">(</span><span class="nc">Printer</span><span class="o">::</span><span class="no">JUSTIFY_LEFT</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">text</span><span class="p">(</span><span class="s2">"--------------------------------</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$transaction</span><span class="o">-></span><span class="n">items</span> <span class="k">as</span> <span class="nv">$item</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Metni hizalamak için yardımcı fonksiyon</span>
<span class="nv">$line</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">formatRow</span><span class="p">(</span><span class="nv">$item</span><span class="o">-></span><span class="n">name</span><span class="p">,</span> <span class="nv">$item</span><span class="o">-></span><span class="n">qty</span> <span class="mf">.</span> <span class="s1">'x '</span> <span class="mf">.</span> <span class="nv">$item</span><span class="o">-></span><span class="n">price</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">text</span><span class="p">(</span><span class="nv">$line</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">text</span><span class="p">(</span><span class="s2">"--------------------------------</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span>
<span class="c1">// --- TOPLAM ---</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">setJustification</span><span class="p">(</span><span class="nc">Printer</span><span class="o">::</span><span class="no">JUSTIFY_RIGHT</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">setEmphasis</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">text</span><span class="p">(</span><span class="s2">"TOPLAM: $"</span> <span class="mf">.</span> <span class="nv">$transaction</span><span class="o">-></span><span class="n">total</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">setEmphasis</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">feed</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="c1">// --- DONANIM FONKSİYONLARI ---</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">cut</span><span class="p">();</span> <span class="c1">// Kağıdı kes</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">pulse</span><span class="p">();</span> <span class="c1">// Nakit çekmecesini aç (Kick)</span>
<span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
<span class="nv">$printer</span><span class="o">-></span><span class="nf">close</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">function</span> <span class="n">formatRow</span><span class="p">(</span><span class="nv">$left</span><span class="p">,</span> <span class="nv">$right</span><span class="p">,</span> <span class="nv">$width</span> <span class="o">=</span> <span class="mi">32</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// "Ürün Adı ...... $10.00" düzenini oluşturmak için basit bir mantık</span>
<span class="nv">$len</span> <span class="o">=</span> <span class="nv">$width</span> <span class="o">-</span> <span class="nb">strlen</span><span class="p">(</span><span class="nv">$right</span><span class="p">);</span>
<span class="k">return</span> <span class="nb">str_pad</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$left</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nv">$len</span><span class="p">),</span> <span class="nv">$len</span><span class="p">)</span> <span class="mf">.</span> <span class="nv">$right</span><span class="p">;</span>
<span class="p">}</span>}


