Jekyll2022-10-19T13:10:06+00:00https://oguzcandemircan.com/feed.xmloguzcandemircan.github.ioMy personal websiteOğuzcan Demircanoguzcandemircan@gmail.comLaravel Queue Nedir ? Laravel Queue Nasıl Yapılır ?2019-05-15T00:00:00+00:002019-05-15T00:00:00+00:00https://oguzcandemircan.com/laravel-queue-nedir-laravel-nasil-yapilir<h4 id="laravel-queue-nedir-">Laravel Queue Nedir ?</h4>
<p>Laravel Queue, e-posta göndermek vb. gibi zaman alıcı bir görevin işlenmesini daha sonra işlenmek üzere ertelemenizi sağlayan yapıdır. Bu zaman alıcı görevlerin ertelenmesi, uygulamanıza yapılan web isteklerini büyük ölçüde hızlandırır. Laravel Queue (Kuyruklama / Sıralama), Beanstalk, Amazon SQS, Redis ve hatta ilişkisel bir veritabanı gibi çeşitli kuyruk arka uçlarında birleşik bir API sağlar.</p>
<hr />
<h4 id="laravel-jobs-nedir-">Laravel Jobs Nedir ?</h4>
<p>Laravel Jobs, uygulamamızın normalden farklı, özel olarak yapmasını istediğimiz işlerin, görevlerin tanımlandığı sınıf (class) yapısıdır. Laravel Jobs ile uygulamamızın yaptığı işleri ayrı ayrı tanımlayıp Laravel Queue ile de sıraya sokarak dilediğimiz bir zamanda yaptırabiliriz.</p>
<hr />
<h4 id="sorun-yaratalım--neden-kullanalım-">Sorun Yaratalım / Neden Kullanalım ?</h4>
<p>Örnek vermek gerekirse bir sosyal medya uygulamamız var. Bir kullanıcı yeni bir gönderi oluşturduğunda tüm takipçilerine e-posta (e-mail) göndermek istiyorsunuz. Kullanıcının 1000 takipçisi olduğunu farz edersek. Kullanıcı gönderiyi paylaş butonuna bastıktan sonra 1000 adet e-postanın takipçilerine ulaşmasını beklemek zorunda. Zamanın çok önemli olduğu bir çağda kullanıcıyı o kadar süre bekletmek istemezsiniz. Bekletmek isteseniz bile muhtemelen zaman aşımı (timeout) hatası ile karşılaşacaksınız :). İşte tamda burda çözüm olarak devreye <strong>Laravel Queue</strong> giriyor.</p>
<hr />
<blockquote>
<p>Not: Laravel Jobs ile yapılacak bir iş / görev tanımlayıp daha sonra Laravel Queue ile de bu işleri, bir işlem kuyruğuna ekleyip istediğimiz bir zamanda sırayla yaptırabiliyoruz.</p>
</blockquote>
<hr />
<h4 id="yarattığımız-sorunu-çözelim">Yarattığımız Sorunu Çözelim</h4>
<p>Örneğimiz üzerinden devam edersek, sorunumuz kullanıcı bir gönderi paylaştığında, kullanıcının tüm takipçilerine e-posta gönderirken kullacının takipçilerinin çok olması sebebiyle zaman aşımı (timeout) hatası ile karşılaşmamız. Peki <strong>Laravel Jobs</strong> ve <strong>Laravel Queue</strong> bu ile sorunu nasıl çözeriz ?</p>
<p>Kurulumları anlatıp uzun olan bir makaleyi daha da uzatmamak için örneği docker üzerinden vereceğim.</p>
<p>Yeni klasör oluşturup içerisine de <strong>Laradock</strong> projesini dahil edelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>Laravel-Queue
<span class="nb">cd </span>Laravel-Queue
git clone https://github.com/Laradock/laradock.git
</code></pre></div></div>
<blockquote>
<p>Laradock hakkında herhangi bir bilginiz yok ise <a href="yeni-nesil-gelistirme-ortami-bolum-3-laradock">Yeni Nesil Geliştirme Ortamı Docker Serisinin 3. Bölümünde Laradock</a>’ tan bahsettim okuyabilirsiniz.</p>
</blockquote>
<p>Laradock klasörüne içerisinde ki env-example dosyasını “.env” olarak kopyalayalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>laradock
<span class="nb">cp </span>env-example .env
</code></pre></div></div>
<p>Gerekli servisleri(konteyner) başlatalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose up <span class="nt">-d</span> nginx mysql
</code></pre></div></div>
<blockquote>
<p>Not : Laradock ‘ u ilk defa çalıştırdığınızda bu kısım biraz uzun sürebilir</p>
</blockquote>
<p>Workspace servisimizin içerisine “laradock” kullanıcısı ile girelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose <span class="nb">exec</span> <span class="nt">--user</span><span class="o">=</span><span class="s2">"laradock"</span> workspace bash
</code></pre></div></div>
<p>Yeni Laravel projesi oluşturalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer create-project <span class="nt">--prefer-dist</span> laravel/laravel laravel <span class="s2">"5.8"</span>
</code></pre></div></div>
<p>laravel klasörü içerisindeki dosyaları bir üst dizine taşıyalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mv </span>laravel/<span class="o">{</span>.,<span class="o">}</span><span class="k">*</span> ./
</code></pre></div></div>
<p>veritabanı ayarlarımızı yapalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#.env</span>
...
<span class="nv">DB_CONNECTION</span><span class="o">=</span>mysql
<span class="nv">DB_HOST</span><span class="o">=</span>mysql
<span class="nv">DB_PORT</span><span class="o">=</span>3306
<span class="nv">DB_DATABASE</span><span class="o">=</span>default
<span class="nv">DB_USERNAME</span><span class="o">=</span>root
<span class="nv">DB_PASSWORD</span><span class="o">=</span>root
...
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">QUEUE_CONNECTION</code> “database” olarak ayarlıyalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#.env</span>
...
<span class="nv">QUEUE_CONNECTION</span><span class="o">=</span>database
...
</code></pre></div></div>
<!-- `routes/web.php` içersine aşağıdaki kodları ekliyelim.
```php
Route::get('share-post', function() {
Post::create([
'title' => 'başlık',
'content' => 'içerik'
]);
foreach(User::find(1)->followers as $follower) {
new Mail($follower);
}
});
``` -->
<p>Artisan komutları ile <strong>Job (İş / Görev)</strong> oluşturalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php artisan make:job SendEmail
</code></pre></div></div>
<p>Yukarıda ki komut ile <code class="language-plaintext highlighter-rouge">app\Jobs</code> dizini altında <code class="language-plaintext highlighter-rouge">SendEmail</code> ismiyile bir job (iş/görev) oluşmuş oldu.
SendEmail.php içerisine de ki <code class="language-plaintext highlighter-rouge">handle</code> methodtuna aşağıdaki komutları yerleştirelim.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#app\Jobs\SendEmail.php</span>
<span class="mf">...</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">handle</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1"># e-posta göndermek yerine 1 saniye gecikme ekliyoruz.</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="mf">...</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">routes\web.php</code> içerisine de aşağıdaki komutları yerleştirelim.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="nc">Route</span><span class="o">::</span><span class="nf">get</span><span class="p">(</span><span class="s1">'share-post'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
<span class="cd">/**
* Post Oluşturma vb. diğer işlemler
*/</span>
<span class="k">for</span> <span class="p">(</span><span class="nv">$i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o"><</span> <span class="mi">10</span><span class="p">;</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="c1"># e-posta göndermek yerine 1 saniye gecikme ekliyoruz.</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="s1">'Gönderiniz yayınlandı'</span><span class="p">;</span>
<span class="p">});</span>
<span class="nc">Route</span><span class="o">::</span><span class="nf">get</span><span class="p">(</span><span class="s1">'share-post-with-queue'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
<span class="cd">/**
* Post Oluşturma vb. diğer işlemler
*/</span>
<span class="k">for</span> <span class="p">(</span><span class="nv">$i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o"><</span> <span class="mi">10</span><span class="p">;</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nc">App\Jobs\SendMail</span><span class="o">::</span><span class="nf">dispatch</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="s1">'Gönderiniz yayınlandı.'</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>
<blockquote>
<p>E-posta ayarları ile uğraşmamak için, e-posta göndermek yerine <code class="language-plaintext highlighter-rouge">sleep()</code> methodu ile 1 saniye gecikme ekliyoruz. Siz dilerseniz e-posta ayarlarını yapılandırıp e-posta gönderebilirsiniz.</p>
</blockquote>
<p>Tarayıcıda 2 sekme veya pencere açarak birinden <strong><a href="http://localhost/share-post" target="_blank" rel="nofollow">localhost/share-post</a></strong> adresine, diğerinde de <strong><a href="http://localhost/share-post-with-queue" target="_blank" rel="nofollow">localhost/share-post-with-queue</a></strong> adresine istek atalım.</p>
<p><strong><a href="http://localhost/share-post" target="_blank" rel="nofollow">localhost/share-post</a></strong> adresine attığınız istek ekrana 10 saniye sonra “Gönderiniz yayınlandı” çıktısını verirken, <strong><a href="http://localhost/share-post-with-queue" target="_blank" rel="nofollow">localhost/share-post-with-queue</a></strong> adresine attığınız istek ekrana direk “Gönderiniz yayınlandı” çıktısını verecektir.</p>
<p>Bunun sebebi “share-post” rotası(route) sleep(1) işlemini siz butona basar basmaz gerçekleştirirken, “share-post-with-queue” rotası siz istek yaptıktan sonra veritabanında ki <strong>jobs</strong> tablosuna daha sonra gerçekleştirilmek üzere 10 adet <code class="language-plaintext highlighter-rouge">SendMail</code> görevi ekler ve direk ekrana “Gönderiniz yayınlandı sonucunu basar”.</p>
<p>Veritabanına eklenen görevlerin gerçekleştirilmesi için terminalden <code class="language-plaintext highlighter-rouge">php artisan queue:work</code> komutu çalıştırılmalıdır. <code class="language-plaintext highlighter-rouge">php artisan queue:work</code> komutu ile birlikte <strong>Laravel Queue</strong>, <strong>jobs</strong> tablosundan daha önce eklenmiş ve gerçekleştirme zamanı gelmiş olan görevleri çeker. <code class="language-plaintext highlighter-rouge">handle</code> methodu içerisine yazılmış olan işlemleri sırayla gerçekleştirir.</p>
<blockquote>
<p>Not: <code class="language-plaintext highlighter-rouge">php artisan queue:work</code> komutunu çalıştırmadan önce veritabanında “jobs” tablosuna bakarsanız. 10 adet kayıt göreceksiniz. <code class="language-plaintext highlighter-rouge">php artisan queue:work</code> komutu çalıştırdığınızda sırayla işler gerçekleştirilecek ve kayıtlar tablodan silinecektir.</p>
</blockquote>
<p>Biraz karmaşık bir konu olduğu için daha rahat anlaşılması için küçük bir video hazırladım.</p>
<video autoplay="" loop="" controls="">
<source src="/assets/posts/9/laravel-queue-example.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
<blockquote>
<p>Video üzerine tıklayarak daha net bir şekilde videoyu görüntüleyebilirsiniz.</p>
</blockquote>
<p>Örneği veritabanı üzerinden vermemin sebebi phpmyadmin vb. ile kolayca jobs tablosuna gidip olan biteni izlemeniz içindi. Ama gelin görünki gerçek hayatta bu tarz uygulamalar için ilişkisel veritabanları biraz hantal kalıyor, dolayısı ile redis vb. teknolojilere ihtiyaç duyuyoruz. Laravel, <strong>Beanstalk</strong>, <strong>Amazon SQS</strong>, <strong>Redis</strong> vb. teknolojilere tam destek sağlıyor. Biz genellikle tercih edilen <strong>Redis</strong> üzerinden devam edelim.</p>
<hr />
<h4 id="laravel-queue-redis-entegrasyonu">Laravel Queue Redis Entegrasyonu</h4>
<p>Laravel ile Redis kullanabilmemiz için “predis” paketini kuralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require predis/predis
</code></pre></div></div>
<p>Redis ayarlarını yapınlandıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#.env</span>
...
<span class="nv">REDIS_HOST</span><span class="o">=</span>redis
<span class="nv">REDIS_PASSWORD</span><span class="o">=</span>null
<span class="nv">REDIS_PORT</span><span class="o">=</span>6379
...
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">QUEUE_CONNECTION</code> “redis” olarak ayarlıyalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#.env</span>
...
<span class="nv">QUEUE_CONNECTION</span><span class="o">=</span>redis
...
</code></pre></div></div>
<p>Redis servisimizi ayağa kaldıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose up <span class="nt">-d</span> redis
</code></pre></div></div>
<p>Redis yapılandırması ve entegrasyonu Bu kadar basit :)</p>
<hr />
<h4 id="laravel-queue-gecikme-delay">Laravel Queue Gecikme (Delay)</h4>
<p>İşlerimize gecikme eklemek istersek, <code class="language-plaintext highlighter-rouge">delay()</code> methodunuz kullanabiliriz.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">App\Jobs\SendMail</span><span class="o">::</span><span class="nf">dispatch</span><span class="p">()</span><span class="o">-></span><span class="nf">delay</span><span class="p">(</span><span class="nf">now</span><span class="p">()</span><span class="o">-></span><span class="nf">addMinutes</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span>
</code></pre></div></div>
<hr />
<h4 id="eş-zamanlı-i̇şler-synchronous-dispatching">Eş Zamanlı İşler (Synchronous Dispatching)</h4>
<p>Bir işi derhal (eşzamanlı olarak) göndermek istiyorsak, <code class="language-plaintext highlighter-rouge">dispatchNow</code> methodunu kullanabilirsiniz. Bu methodu kullanırken, iş kuyruğa alınmayacak ve hemen geçerli işlem içinde çalıştırılacaktır.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">App\Jobs\SendMail</span><span class="o">::</span><span class="nf">dispatchNow</span><span class="p">()</span>
</code></pre></div></div>
<hr />
<h4 id="i̇ş-zincirilemesi-job-chaining-nedir-">İş Zincirilemesi (Job Chaining) nedir ?</h4>
<p>İş zincirlemesi, sırayla çalıştırılması gereken işlem kuyruğuna alınmış işlerin bir listesini belirlememiz sağlar. Sıradaki bir iş başarısız olursa, işlerin geri kalanı çalışmayacaktır. Kuyruğa alınmış bir iş zincirini yürütmek için, <code class="language-plaintext highlighter-rouge">withChain</code> methodunu kullanabiliriz.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">App\Jobs\SendMail</span><span class="o">::</span><span class="nf">withChain</span><span class="p">([</span>
<span class="k">new</span> <span class="nc">IkinciBirIs</span><span class="p">,</span>
<span class="k">new</span> <span class="nc">UcuncuBirIs</span><span class="p">,</span>
<span class="p">])</span><span class="o">-></span><span class="nf">dispatch</span><span class="p">()</span>
</code></pre></div></div>
<hr />
<h4 id="job-events-i̇ş-etkinlikleri">Job Events (İş Etkinlikleri)</h4>
<p>Laravel Queue ile işlem kuyruğuna aldığımız işler/görevler işlenirken. <code class="language-plaintext highlighter-rouge">JobProcessing</code>, <code class="language-plaintext highlighter-rouge">JobProcessed</code> ve <code class="language-plaintext highlighter-rouge">JobFailed</code> olmak üzere 3 adet etkinlik(event) tetikler. Bizde bu etkinlikleri dinleyerek(listening), Bir iş işlenirken, işlendikten sonra veya başarısız olduğunda yapılacak işlemleri tanımlayabiliriz.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#App/Providers/AppServiceProvider.php</span>
<span class="mf">...</span>
<span class="kn">use</span> <span class="nc">Illuminate\Support\Facades\Queue</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Support\ServiceProvider</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Queue\Events\JobFailed</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Queue\Events\JobProcessed</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Queue\Events\JobProcessing</span><span class="p">;</span>
<span class="mf">...</span>
<span class="mf">...</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">boot</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1"># İşler işlenirken</span>
<span class="nc">Queue</span><span class="o">::</span><span class="nf">before</span><span class="p">(</span><span class="k">function</span> <span class="p">(</span><span class="kt">JobProcessing</span> <span class="nv">$event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// $event->connectionName</span>
<span class="c1">// $event->job</span>
<span class="c1">// $event->job->payload()</span>
<span class="p">});</span>
<span class="c1">#İşler işlendikten sonra</span>
<span class="nc">Queue</span><span class="o">::</span><span class="nf">after</span><span class="p">(</span><span class="k">function</span> <span class="p">(</span><span class="kt">JobProcessed</span> <span class="nv">$event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// $event->connectionName</span>
<span class="c1">// $event->job</span>
<span class="c1">// $event->job->payload()</span>
<span class="p">});</span>
<span class="c1">#İşler başarısız olduğunda</span>
<span class="nc">Queue</span><span class="o">::</span><span class="nf">failing</span><span class="p">(</span><span class="k">function</span> <span class="p">(</span><span class="kt">JobFailed</span> <span class="nv">$event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// $event->connectionName</span>
<span class="c1">// $event->job</span>
<span class="c1">// $event->exception</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="mf">...</span>
</code></pre></div></div>
<hr />
<h4 id="başarısız-i̇şler-failed-jobs">Başarısız İşler (Failed Jobs)</h4>
<p>Laravel Queue’ da herhangi bir sebepten dolayı iş başarısız olursa, iş sınıfı içerisindeki <code class="language-plaintext highlighter-rouge">failed</code> methodu tetiklenir(çağırılır/çalıştırılır). Tanımladığımız iş başarısız olduğunda yapılacak işlemleri <code class="language-plaintext highlighter-rouge">failed</code> methodu altında tanımlayabiliriz.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cd">/**
* The job failed to process.
*
* @param Exception $exception
* @return void
*/</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">failed</span><span class="p">(</span><span class="kt">Exception</span> <span class="nv">$exception</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// işlem başarısız olunca gerçekleştirilecek işlemler</span>
<span class="p">}</span>
</code></pre></div></div>
<hr />
<h3 id="sonuç">Sonuç</h3>
<p>Sonuç olarak, <strong>Laravel Queue</strong> nedir? ne değildir? <strong>Laravel Queue</strong> nasıl kullanırız? vb. soruların cevaplarını öğrendik. İyi hoş güzelde gerçek hayatta ne işimize yarayacak dememeniz için, gerçek hayatta karşılaşabileceğimiz örnek bir sorun yaratıp çözdük. Umarım <strong>Laravel Queue</strong> hakkında kafanızda soru işareti kalmamıştır. Herhangi bir sorunuz var ise yorumlar bölümünden belirtebilirsiniz. Bir sonraki makalede görüşmek üzere.</p>
<hr />
<p>Kaynak:</p>
<ul>
<li><a href="https://laravel.com/docs/5.8/queues" target="_blank" rel="nofollow">Laravel Queue</a></li>
</ul>Oğuzcan Demircanoguzcandemircan@gmail.comLaravel Queue Nedir ? Laravel Queue, e-posta göndermek vb. gibi zaman alıcı bir görevin işlenmesini daha sonra işlenmek üzere ertelemenizi sağlayan yapıdır. Bu zaman alıcı görevlerin ertelenmesi, uygulamanıza yapılan web isteklerini büyük ölçüde hızlandırır. Laravel Queue (Kuyruklama / Sıralama), Beanstalk, Amazon SQS, Redis ve hatta ilişkisel bir veritabanı gibi çeşitli kuyruk arka uçlarında birleşik bir API sağlar.Laravel ile Api Authentication Nasıl Yapılır ? Laravel Passport Nedir ?2019-04-15T00:00:00+00:002019-04-15T00:00:00+00:00https://oguzcandemircan.com/laravel-ile-api-authentication-nasil-yapilir-laravel-passport-nedir<p><strong>Laravel ile api authentication (kimlik doğrulaması)</strong> yapmak için bir çok farklı yöntem ve paket mevcut.
Bugün bu paketlerden, Laravel’ in resmi paketi olan <strong>Laravel Passport</strong> paketi ile api kimlik doğrulama işlemini gerçekleştireceğiz.</p>
<p>Gereksinimler:</p>
<ul>
<li>Temel seviyede api bilgisi</li>
<li>Temel seviyede php ve laravel bilgisi</li>
<li>Php, Mysql ve Postman yüklü bilgisayar</li>
</ul>
<p><em>Apimizi test etmek için <strong>Postman</strong> kullanacağız. Eğer bilgisayarınızda Postman yoksa <a href="https://www.getpostman.com/downloads/">burayı tıklayarak</a> indirebilirsiniz.</em></p>
<hr />
<!-- #### Api Nedir ?
Günümüz projeleri, Masaüstü, Tarayıcı, Mobil vb. birden çok platforma çıkmakta. Her platforma ayrı özel uygulama geliştirmektense uygulamayı sunucu tarafı (server) ve kullanıcı tarafı (client) olarak 2 ye ayırıp. Tek bir sunucu taraflı uygulama (api) geliştirip diğer platformlara ise sadece kullanıcı taraflı uygulama geliştirerek bu sorunu çözmektedirler.
--- -->
<h4 id="laravel-passport-nedir-">Laravel Passport Nedir ?</h4>
<p>Laravel ile yazdığımız apilerde authentication (kimlik doğrulaması) yapabilmemizi kolaylaştıran resmi laravel paketidir.</p>
<hr />
<h4 id="laravel-passport-kullanarak-örnek-api-authentication-yapalım">Laravel Passport Kullanarak Örnek Api Authentication Yapalım</h4>
<p>Laravel kurulumunu gerçekleştirelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer create-project <span class="nt">--prefer-dist</span> laravel/laravel api <span class="s2">"5.8.*"</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">Laravel Passport</code> paketinin kurulumunu yapalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require laravel/passport
</code></pre></div></div>
<blockquote>
<p>Not: Laravel 5.4 ve aşağısı için config/app.php providers kısmına “ Laravel\Passport\PassportServiceProvider::class “ ifadesini eklemeniz gerekmektedir. Laravel 5.5 ve üzeri sürümlerde buna gerek yoktur.</p>
</blockquote>
<p><code class="language-plaintext highlighter-rouge">.env</code> dosyasında veritabanı bağlantı ayarlarımızı yaptıktan sonra veritabanına tablolarımızı ekliyelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php artisan migrate
</code></pre></div></div>
<p>Uygulamamıza apiyi kullanacak kullanıcı (Client) ekliyelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php artisan passport:install
</code></pre></div></div>
<p><img src="/assets/posts/8/passport-install-client-ekleme.png" alt="php artisan passport:install komutu ile client ekleme örnek görüntüsü" /></p>
<p><strong>password grant</strong> ile kimlik doğrulama işlemini gerçekleştireceğimiz için client id si 2 olan kullanıcı bilgilerini bir yere not edelim.</p>
<p><code class="language-plaintext highlighter-rouge">App/User.php</code> içerisine <code class="language-plaintext highlighter-rouge">\Laravel\Passport\HasApiTokens</code> traitini ekliyoruz.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">use</span> <span class="nc">Laravel</span> <span class="nc">Passport</span> <span class="nc">HasApiTokens</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">App/User.php</code> içeriği aşağıdaki gibi olmalıdır.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#App/User.php </span>
<span class="kn">namespace</span> <span class="nn">App</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Notifications\Notifiable</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Contracts\Auth\MustVerifyEmail</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Foundation\Auth\User</span> <span class="k">as</span> <span class="nc">Authenticatable</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Laravel\Passport\HasApiTokens</span><span class="p">;</span>
<span class="kd">class</span> <span class="nc">User</span> <span class="kd">extends</span> <span class="nc">Authenticatable</span>
<span class="p">{</span>
<span class="kn">use</span> <span class="nc">Notifiable</span><span class="p">,</span> <span class="nc">HasApiTokens</span><span class="p">;</span>
<span class="cd">/**
* The attributes that are mass assignable.
*
* @var array
*/</span>
<span class="k">protected</span> <span class="nv">$fillable</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'name'</span><span class="p">,</span> <span class="s1">'email'</span><span class="p">,</span> <span class="s1">'password'</span><span class="p">,</span>
<span class="p">];</span>
<span class="cd">/**
* The attributes that should be hidden for arrays.
*
* @var array
*/</span>
<span class="k">protected</span> <span class="nv">$hidden</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'password'</span><span class="p">,</span> <span class="s1">'remember_token'</span><span class="p">,</span>
<span class="p">];</span>
<span class="cd">/**
* The attributes that should be cast to native types.
*
* @var array
*/</span>
<span class="k">protected</span> <span class="nv">$casts</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'email_verified_at'</span> <span class="o">=></span> <span class="s1">'datetime'</span><span class="p">,</span>
<span class="p">];</span>
<span class="p">}</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">App/Providers/AuthServiceProvider.php</code> içerisinde ki <code class="language-plaintext highlighter-rouge">boot</code> methoduna <code class="language-plaintext highlighter-rouge">\Laravel\Passport\Passport::routes();</code> ifadesini ekliyoruz.
Bu ifade ile <strong>Laravel Passport</strong> paketi içerisinde tanımlanan rotaları (route) uygulamamıza tanıtmış oluyoruz.</p>
<p><code class="language-plaintext highlighter-rouge">config/auth.php</code> dosyasındaki api driver kısmını <strong>passport</strong> olarak ayarlıyoruz.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="s1">'guards'</span> <span class="o">=></span> <span class="p">[</span>
<span class="s1">'web'</span> <span class="o">=></span> <span class="p">[</span>
<span class="s1">'driver'</span> <span class="o">=></span> <span class="s1">'session'</span><span class="p">,</span>
<span class="s1">'provider'</span> <span class="o">=></span> <span class="s1">'users'</span><span class="p">,</span>
<span class="p">],</span>
<span class="s1">'api'</span> <span class="o">=></span> <span class="p">[</span>
<span class="s1">'driver'</span> <span class="o">=></span> <span class="s1">'passport'</span><span class="p">,</span>
<span class="s1">'provider'</span> <span class="o">=></span> <span class="s1">'users'</span><span class="p">,</span>
<span class="p">],</span>
<span class="p">],</span>
</code></pre></div></div>
<p>Laravel Tinker kullanarak uygulamamıza kullanıcı ekliyelim ve bilgilerini dilediğimiz bir yere not edelim.</p>
<p>Tinker ‘ a giriş yapalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php artisan tinker
</code></pre></div></div>
<p>Daha sonra aşağıdaki komut ile kullanıcı ekliyelim.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">App\User</span><span class="o">::</span><span class="nf">create</span><span class="p">([</span><span class="s1">'name'</span> <span class="o">=></span> <span class="s1">'deneme'</span><span class="p">,</span> <span class="s1">'email'</span> <span class="o">=></span> <span class="s1">'deneme@oguzcandemircan.com'</span><span class="p">,</span> <span class="s1">'password'</span> <span class="o">=></span> <span class="nf">bcrypt</span><span class="p">(</span><span class="s1">'123456'</span><span class="p">)]);</span>
<span class="c1"># exit komutunu kullanarak Tinker' dan çıkış yapabiliriz.</span>
</code></pre></div></div>
<p><img src="/assets/posts/8/tinker-ile-kullanici-ekleme.png" alt="Laravel Tinker kullanıcı ekleme örneği görütünsü" /></p>
<p>Daha sonra postman ile <strong>/oauth/token</strong> adresine daha önceden not aldığımız bilgiler ile istek atalım.</p>
<blockquote>
<p>Benim not aldığım bilgiler aşağıdaki tabloda ki gibidir. Sizde farklılık gösterebiliriz. Siz kendi not aldığınız bilgiler ile işlemi gerçekleştirin.</p>
</blockquote>
<table>
<thead>
<tr>
<th>Anahtar(Key)</th>
<th>Değer(Value)</th>
</tr>
</thead>
<tbody>
<tr>
<td>client_id</td>
<td>2</td>
</tr>
<tr>
<td>client_secret</td>
<td>cenwr6FTzsnFRumMvuEuv2GMY3EeMVyZ2Hn0Pj9mSzAtered</td>
</tr>
<tr>
<td>grant_type</td>
<td>password</td>
</tr>
<tr>
<td>username</td>
<td>deneme@oguzcandemircan.com</td>
</tr>
<tr>
<td>password</td>
<td>123456</td>
</tr>
</tbody>
</table>
<p><img src="/assets/posts/8/postman-token-istegi.png" alt="postman oauth token isteği örnek görüntüsü" /></p>
<p>Yukarıdaki resimde gördüğünüz gibi <strong>/oauth/token</strong> adresine istek attığımızda tipi <strong>Bearer</strong> olan bir <strong>erişim anahtarı(access token)</strong> döndü.</p>
<p>Bu erişim anahtarı ile <strong>/api/user</strong> adresine <strong>Authorization</strong> headerini ekleyip değerini de <strong>Bearer {bir_önceki_istekten_dönen_erişim_anahtarı}</strong> olarak ayarlayıp istek atalım.</p>
<p><img src="/assets/posts/8/postman-token-ile-kullanici-bilgilerini-getirme.png" alt="Laravel token ile kullanıcı bilgilerini getirme" /></p>
<p>Yukarıdaki resimde de gördüğümüz gibi <strong>erişim anahtarı(access token)</strong> ile <strong>/api/user</strong> adresine istek attığımızda kullanıcı bilgilerine eriştik.</p>
<hr />
<p>Kaynaklar:</p>
<ul>
<li><a href="https://laravel.com/docs/5.8/passport" target="_blank">Laravel Passport</a></li>
</ul>Oğuzcan Demircanoguzcandemircan@gmail.comLaravel ile api authentication (kimlik doğrulaması) yapmak için bir çok farklı yöntem ve paket mevcut. Bugün bu paketlerden, Laravel’ in resmi paketi olan Laravel Passport paketi ile api kimlik doğrulama işlemini gerçekleştireceğiz.Docker ile Vue Js Projesi Nasıl Oluşturulur, Geliştirilir ve Yayınlanır ?2019-04-11T00:00:00+00:002019-04-11T00:00:00+00:00https://oguzcandemircan.com/docker-ile-vuejs-projesi-nasil-olusturulur-gelistirlir-ve-yayinlanir<p>Bu makalede <strong>Docker</strong> kullanarak yeni bir <strong>Vue Js</strong> projesi <strong>oluşturacağız</strong> <strong>geliştireceğiz</strong> ve <strong>yayınlıyacağız</strong>.</p>
<p>Gereksinimler:</p>
<ul>
<li>Temel seviyede Docker bilgisi</li>
<li>Temel seviyede Vue-Cli bilgisi</li>
<li>Docker yüklü bir bilgisayar</li>
</ul>
<p><em>Docker hakkında hiç bilginiz yok ise “ <a href="/yeni-nesil-gelistirme-ortami-bolum-1-docker">yeni-nesil-gelistirme-ortami-bolum-1-docker</a> “ makalemi okuyabilisiniz.</em></p>
<hr />
<h4 id="docker-ve-vue-cli-ile-yeni-bir-vue-js-projesi-nasıl-oluşturulur-">Docker ve Vue Cli ile Yeni Bir Vue Js Projesi Nasıl Oluşturulur ?</h4>
<p>Yeni bir poje oluşturmak için aşağıdaki kodu çalıştıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>vue-docker <span class="o">&&</span> <span class="nb">cd</span> <span class="s2">"</span><span class="nv">$_</span><span class="s2">"</span> <span class="o">&&</span> docker run <span class="nt">--rm</span> <span class="nt">-v</span> <span class="s2">"</span><span class="k">${</span><span class="nv">PWD</span><span class="k">}</span><span class="s2">:/</span><span class="si">$(</span><span class="nb">basename</span> <span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span><span class="si">)</span><span class="s2">"</span> <span class="nt">-w</span> <span class="s2">"/</span><span class="si">$(</span><span class="nb">basename</span> <span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span><span class="si">)</span><span class="s2">"</span> <span class="nt">-it</span> node:11.1-alpine sh <span class="nt">-c</span> <span class="s2">"yarn global add @vue/cli && vue create ."</span>
</code></pre></div></div>
<blockquote>
<p>Not: Yeni bir poje oluştururken “vue-docker” kısmını kendi proje adınız ile değiştirebilirsiniz. “vue create .” kımını “vue init webpack .” vb. değiştirerek herhangi bir vue-cli komutu ile projenizi oluşturabilirsiniz.</p>
</blockquote>
<hr />
<h4 id="docker-ile-vue-js-projesi-yayınlamak-deploy">Docker ile Vue Js Projesi Yayınlamak (Deploy)</h4>
<p>Vue Js projemizi Docker ile yayınlamak (deploy) için Dockerfile oluşturalım ve içerisine aşağıdaki kodları yerleştirelim.</p>
<div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># develop stage</span>
<span class="k">FROM</span><span class="s"> node:11.1-alpine as develop-stage</span>
<span class="k">WORKDIR</span><span class="s"> /app</span>
<span class="k">COPY</span><span class="s"> package*.json ./</span>
<span class="k">RUN </span>yarn <span class="nb">install</span>
<span class="k">COPY</span><span class="s"> . .</span>
<span class="c"># build stage</span>
<span class="k">FROM</span><span class="s"> develop-stage as build-stage</span>
<span class="k">RUN </span>yarn build
<span class="c"># production stage</span>
<span class="k">FROM</span><span class="s"> nginx:1.15.7-alpine as production-stage</span>
<span class="k">COPY</span><span class="s"> --from=build-stage /app/dist /usr/share/nginx/html</span>
<span class="k">EXPOSE</span><span class="s"> 80</span>
<span class="k">CMD</span><span class="s"> ["nginx", "-g", "daemon off;"]</span>
</code></pre></div></div>
<p>Dockerfile’ ı <code class="language-plaintext highlighter-rouge">vue-docker</code> ismiyle etiketleyerek imaj (image) alalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">-t</span> vue-docker <span class="nb">.</span>
</code></pre></div></div>
<p>Docker Konteynerı(Container) çalıştıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-it</span> <span class="nt">-p</span> 80:80 <span class="nt">--rm</span> vue-docker
</code></pre></div></div>
<p>Şimdi tarayıcımızdan <strong>http://localhost</strong> adresine gidelim.</p>
<p><img src="/assets/posts/7/vue-deploy.png" alt="Docker ile vue js projesi yayınlama örneği" /></p>
<p>Yukarıdaki görüntü ile karşılaştıysak her şey yolunda demektir.</p>
<hr />
<h4 id="docker-ile-vue-js-projesi-nasıl-geliştirilir-development">Docker ile Vue JS Projesi Nasıl Geliştirilir (Development)</h4>
<p><strong>Docker</strong> ile <strong>VueJS</strong> projesi geliştirmek için <strong>docker-compose</strong> kullanacağız.</p>
<p><code class="language-plaintext highlighter-rouge">docker-compose.yml</code> ismi ile dosya oluşturup içerisine aşağıdaki komutları yerleştirelim.</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">version</span><span class="pi">:</span> <span class="s1">'</span><span class="s">3.5'</span>
<span class="na">services</span><span class="pi">:</span>
<span class="na">frontend</span><span class="pi">:</span>
<span class="na">build</span><span class="pi">:</span>
<span class="na">context</span><span class="pi">:</span> <span class="s">.</span>
<span class="na">target</span><span class="pi">:</span> <span class="s1">'</span><span class="s">develop-stage'</span>
<span class="na">ports</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s1">'</span><span class="s">8080:8080'</span>
<span class="na">volumes</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s1">'</span><span class="s">.:/app'</span>
<span class="na">command</span><span class="pi">:</span> <span class="s">/bin/sh -c "yarn serve"</span>
</code></pre></div></div>
<p>frontend servisini <code class="language-plaintext highlighter-rouge">hedefi(target)</code> <strong>“develop-stage”</strong> olarak çalıştıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose up <span class="nt">-d</span>
</code></pre></div></div>
<p>Şimdi tarayıcımızdan http://localhost:8000 adresine gidelim.</p>
<!-- `hedefi(target)` **"developer-stage"** olarak ayarladığımız için -->
<p>Her zaman çalıştığımız gibi kodumuzda herhangi bir değişiklik yaptığımız zaman kodumuz derlenecek ve tarayıcımız otomatik olarak yeniden yüklenecek.</p>
<hr />
<p>Projemize herhangi bir başka paket yüklemek için aşağıdaki komutu kullanabiliriz.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose <span class="nb">exec </span>frontend yarn add <paket-ismi>
</code></pre></div></div>
<hr />
<p>Kaynaklar:</p>
<ul>
<li><a href="https://vuejs.org/v2/cookbook/dockerize-vuejs-app.html" target="_blank">Dockerize Vue.js App</a></li>
<li><a href="https://medium.com/@jwdobken/vue-with-docker-initialize-develop-and-build-51fad21ad5e6" target="_blank">Vue with Docker; initialize, develop and build</a></li>
</ul>Oğuzcan Demircanoguzcandemircan@gmail.comBu makalede Docker kullanarak yeni bir Vue Js projesi oluşturacağız geliştireceğiz ve yayınlıyacağız.Vue Js ile Express Kullanarak Server Side Rendering (SSR) Nasıl Yapılır ?2019-04-08T00:00:00+00:002019-04-08T00:00:00+00:00https://oguzcandemircan.com/vue-js-ile-express-kullanarak-server-side-rendering-nasil-yapilir<h4 id="client-side-rendering-csr-nedir-">Client Side Rendering (CSR) Nedir ?</h4>
<p>Client side rendering de sunucumuz tarayıcıya basit düz bir html sayfası döner. Daha sonra sunucumuzun döndüğü html sayfası kullanıcının tarayıcısında
javascript ile derlenerek anlamlı bir html çıktısı elde edilir. Elde edilen html çıktısıda tarayıcı tarafından derlenerek kullanıcının kullanımına sunulur.</p>
<hr />
<h4 id="server-side-rendering-ssr-nedir-">Server Side Rendering (SSR) Nedir ?</h4>
<p>Server side rendering de ise ana içerik sunucumuzda derlenir ve tarayıcıya bitmiş bir html sayfası dönülür.</p>
<hr />
<h4 id="örnek-uygulama-yapalım">Örnek Uygulama yapalım.</h4>
<p>Öncelikle <strong>npm</strong> kuralım</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>npm <span class="nt">-y</span>
</code></pre></div></div>
<p>Daha sonra vue-ssr ismiyle klasör oluşturup içerisine girelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>vue-ssr
<span class="nb">cd </span>vue-ssr
</code></pre></div></div>
<p>Yeni bir proje oluşturalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm init
</code></pre></div></div>
<p>vue, express ve Vue Js ile server side rendering yapmak için <code class="language-plaintext highlighter-rouge">vue-server-renderer</code> paketlerini kuralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm <span class="nb">install </span>vue vue-server-renderer express <span class="nt">--save</span>
</code></pre></div></div>
<p>index.js ismiyle dosya oluşturalım ve içerisine aşağıdaki kodları yerleştirelim.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Gerekli tanımlamaları yapıyoruz.</span>
<span class="kd">const</span> <span class="nx">Vue</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">vue</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">)()</span>
<span class="kd">const</span> <span class="nx">renderer</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">vue-server-renderer</span><span class="dl">'</span><span class="p">).</span><span class="nx">createRenderer</span><span class="p">()</span>
<span class="c1">// " * " işareti ile tüm istekleri tek bir yerde topluyoruz.</span>
<span class="nx">server</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// Vue tanımlaması yapıyoruz.</span>
<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">languages</span><span class="p">:</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">javascript</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">java</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">python</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">php</span><span class="dl">'</span><span class="p">],</span>
<span class="p">},</span>
<span class="na">template</span><span class="p">:</span>
<span class="s2">`
<div>
<ul>
<li v-for="(language, index) in languages" v-bind:key="index">{{ language }}</li>
</ul>
</div>
`</span>
<span class="p">})</span>
<span class="c1">// renderToString fonksiyonuna tanımladığımız vue yu gönderiyoruz.</span>
<span class="nx">renderer</span><span class="p">.</span><span class="nx">renderToString</span><span class="p">(</span><span class="nx">app</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">html</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// renderToString fonkisyonundan dönen html verisini ekrana yazdırıyoruz.</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="s2">`
<!DOCTYPE html>
<html lang="en">
<head><title>Vue Js - Server Side Rendering(SSR) Örneği</title></head>
<body></span><span class="p">${</span><span class="nx">html</span><span class="p">}</span><span class="s2"></body>
</html>
`</span><span class="p">)</span>
<span class="p">})</span>
<span class="p">})</span>
<span class="c1">// 8000 portundan websitemizi yayınlıyoruz.</span>
<span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">8000</span><span class="p">)</span>
</code></pre></div></div>
<p>Yukarıdaki kodları biraz açıklamak gerekirse. Npm ile yüklediğimiz paketleri kullanabilmek için gerekli tanımlamaları yapıyoruz. Express ile tüm istekleri tek bir yerde topluyoruz (yönlendiriyoruz). İçerisinde programlama dillerini içeren bir dizi barındıran ve bu diziyi ekrana yazdıran basit bir vue tanımlaması yapıyoruz. <code class="language-plaintext highlighter-rouge">vue-server-renderer</code> paketi içerisinde yer alan <code class="language-plaintext highlighter-rouge">renderToString</code> fonksiyonuna tanımladığımız vue örneğini (instance) ve isimsiz bir fonksiyon gönderiyoruz. <code class="language-plaintext highlighter-rouge">renderToString</code> fonksiyonu gönderdiğimiz <code class="language-plaintext highlighter-rouge">Vue</code> örneğini (instance) renderlayıp bize <strong>html</strong> dönüyor. Dönen html verisini ekrana yazdırıyoruz ve 8000 portundan websitemizi yayınlıyoruz.</p>
<p>Okadar anlattık şimdi index.js dosyasını çalıştırıp sonucu görelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>node index.js
</code></pre></div></div>
<p>Tarayıcımızdan <code class="language-plaintext highlighter-rouge">http://localhost:8000/</code> adresine gidelim ve kaynak kodunu görüntülüyelim.
<img src="/assets/posts/6/vue-ssr-ornegi.png" alt="Vuejs server side rendering örneği" /></p>
<p>Kaynak kodunda <code class="language-plaintext highlighter-rouge">data-server-rendered="true"</code> etiketini görüyorsak <strong>Vue JS ile server side rendering</strong> işlemimiz başarı ile gerçekleşmiştir.</p>
<p><strong>Kaynak</strong> : <a href="https://ssr.vuejs.org/guide/" target="_blank">vue js ssr guide</a></p>Oğuzcan Demircanoguzcandemircan@gmail.comClient Side Rendering (CSR) Nedir ? Client side rendering de sunucumuz tarayıcıya basit düz bir html sayfası döner. Daha sonra sunucumuzun döndüğü html sayfası kullanıcının tarayıcısında javascript ile derlenerek anlamlı bir html çıktısı elde edilir. Elde edilen html çıktısıda tarayıcı tarafından derlenerek kullanıcının kullanımına sunulur.Laravel Broadcasting Nedir ? Laravel Echo + Redis + Socket.io + Vue JS + Docker Kullanarak Gerçek Zamanlı Bildirim Nasıl Gönderilir ?2019-04-05T00:00:00+00:002019-04-05T00:00:00+00:00https://oguzcandemircan.com/laravel-broadcasting-nedir-laravel-echo-redis-socketio-vue-js-docker-kullanarak-gercek-zamanli-bildirim-nasil-gonderilir<p>Günümüzde birçok modern web uygulaması kullanıcı deneyimini en üst seviyeye çıkartmak için <strong>“gerçek zamanlı (real time)”</strong> güncellenen arayüzler kullanır.
Gerçek zamanlı arayüzler oluşturmak için ise <strong>“WebSoket (WebSocket)”</strong> teknolojisinden yararlanırlar.</p>
<p>Bu tür uygulamaları oluşturmamıza yardımcı olmak için Laravel, <strong>“Brodcasting”</strong> servisini oluşturdu. Bu servis, sunucu tarafında (sever side) oluşan değişiklikleri WebSoket ile ön yüze (frontend) aktarmayı kolaylaştırdı.</p>
<hr />
<h4 id="laravel-broadcasting-nedir-">Laravel Broadcasting Nedir ?</h4>
<p>Laravel Broadcasting, Laravel etkinliklerinizi (Events) yayınlamak, aynı etkinlik adlarını sunucu taraflı kodunuz ve istemci taraflı JavaScript uygulamanız arasında paylaşmanıza olanak sağlayan servistir.</p>
<hr />
<h4 id="laravel-echo-nedir-">Laravel Echo Nedir ?</h4>
<p><strong>Laravel Echo</strong>, Laravel tarafından oluşturulan <strong>kanallara(channels)</strong> abone olmayı ve Laravel tarafından yayınlanan <strong>etkinlikleri (Events)</strong> dinlemeyi kolaylaştıran bir JavaScript kütüphanesidir.</p>
<hr />
<h4 id="redis-nedir-">Redis Nedir ?</h4>
<p>En basit haliyle Redis, <strong>anahtar-değer( key-value )</strong> şeklinde tasarlanmış bir NoSQL veritabanıdır. Memcache benzeri verileri sabit diske yazmadan <strong>ram</strong> üzerinde tutarak veriye erişim hızını arttırmayı amaçlayan teknolojidir. Redis’ in Memcahe’ den farkı NoSql mantığı ile çalıştığı için sunucu kapansa dahi verilerin kaybolmasını önler.</p>
<hr />
<h4 id="vue-js-nedir-">Vue Js Nedir ?</h4>
<p>Modern web arayüzleri oluşturmak için kullanılan Javascript kütüphanesidir.</p>
<hr />
<h4 id="basit-gerçek-zamanlı-bildirim-gönderen-uygulama-yapalım">Basit Gerçek Zamanlı Bildirim Gönderen Uygulama Yapalım</h4>
<p>Sıfırdan redis vs. kurulumu ile uğraşmamak için docker kullanarak yapmayı tercih ediyorum.</p>
<p>Yeni bir klasör oluşturup içerisine laradock projesini dahil edelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>broadcasting
<span class="nb">cd </span>broadcasting
git clone https://github.com/Laradock/laradock.git
</code></pre></div></div>
<p>laradock klasörüne içerisinde ki env-example dosyasını “.env” olarak kopyalayalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>laradock
<span class="nb">cp </span>env-example .env
</code></pre></div></div>
<p>Gerekli servisleri başlatalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose up <span class="nt">-d</span> nginx mysql laravel-echo-server redis
</code></pre></div></div>
<blockquote>
<p>Not : Laradock ‘ u ilk defa çalıştırdığınızda bu kısım biraz uzun sürebilir</p>
</blockquote>
<p>Workspace konteynerımızın(container) içerisine girelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose <span class="nb">exec</span> <span class="nt">--user</span><span class="o">=</span><span class="s2">"laradock"</span> workspace bash
</code></pre></div></div>
<p>yeni bir laravel projesi oluşturalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer create-project <span class="nt">--prefer-dist</span> laravel/laravel laravel
</code></pre></div></div>
<p>laravel klasörü içerisindeki dosyaları bir üst dizine taşıyalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mv </span>laravel/<span class="k">*</span> <span class="nb">.</span>
</code></pre></div></div>
<p>Laravel ile redis kullanabilmemiz için <strong>predis</strong> paketini kuralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require predis/predis
</code></pre></div></div>
<p><em>“config/app.php”</em> dosyasını açın providers(sağlayıcılar) dizisi içerisinde ki <strong>App\Providers\BroadcastServiceProvider::class</strong> yorum satırı olmaktan kurtarın.</p>
<p>Bu sağlayıcı <em>“routes/channels.php”</em> dosyası içerisinde tanımlanan yayınlama(broadcasting) rotalarını (route) etkinleştirecektir.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">App\Providers\BroadcastServiceProvider</span><span class="o">::</span><span class="n">class</span><span class="p">,</span>
</code></pre></div></div>
<p>“.env” dosyasını oluşturalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">touch</span> .env
</code></pre></div></div>
<p>Ve gerekli tanımlamaları yapalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">APP_NAME</span><span class="o">=</span>broadcasting
<span class="nv">APP_ENV</span><span class="o">=</span><span class="nb">local
</span><span class="nv">APP_KEY</span><span class="o">=</span><span class="nb">base64</span>:Imv6pjPkcuVgNOiiKnEEq8IbdskDOCZnLWkVjzp4QCA<span class="o">=</span>
<span class="nv">APP_DEBUG</span><span class="o">=</span><span class="nb">true
</span><span class="nv">APP_URL</span><span class="o">=</span>http://broadcasting.local
<span class="nv">LOG_CHANNEL</span><span class="o">=</span>stack
<span class="nv">DB_CONNECTION</span><span class="o">=</span>mysql
<span class="nv">DB_HOST</span><span class="o">=</span>mysql
<span class="nv">DB_PORT</span><span class="o">=</span>3306
<span class="nv">DB_DATABASE</span><span class="o">=</span>default
<span class="nv">DB_USERNAME</span><span class="o">=</span>root
<span class="nv">DB_PASSWORD</span><span class="o">=</span>root
<span class="nv">BROADCAST_DRIVER</span><span class="o">=</span>redis
<span class="nv">CACHE_DRIVER</span><span class="o">=</span>file
<span class="nv">QUEUE_CONNECTION</span><span class="o">=</span><span class="nb">sync
</span><span class="nv">SESSION_DRIVER</span><span class="o">=</span>file
<span class="nv">SESSION_LIFETIME</span><span class="o">=</span>120
<span class="nv">REDIS_HOST</span><span class="o">=</span>redis
<span class="nv">REDIS_PASSWORD</span><span class="o">=</span>null
<span class="nv">REDIS_PORT</span><span class="o">=</span>6379
<span class="nv">MAIL_DRIVER</span><span class="o">=</span>smtp
<span class="nv">MAIL_HOST</span><span class="o">=</span>smtp.mailtrap.io
<span class="nv">MAIL_PORT</span><span class="o">=</span>2525
<span class="nv">MAIL_USERNAME</span><span class="o">=</span>null
<span class="nv">MAIL_PASSWORD</span><span class="o">=</span>null
<span class="nv">MAIL_ENCRYPTION</span><span class="o">=</span>null
<span class="nv">PUSHER_APP_ID</span><span class="o">=</span>
<span class="nv">PUSHER_APP_KEY</span><span class="o">=</span>
<span class="nv">PUSHER_APP_SECRET</span><span class="o">=</span>
<span class="nv">PUSHER_APP_CLUSTER</span><span class="o">=</span>mt1
<span class="nv">MIX_PUSHER_APP_KEY</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">PUSHER_APP_KEY</span><span class="k">}</span><span class="s2">"</span>
<span class="nv">MIX_PUSHER_APP_CLUSTER</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">PUSHER_APP_CLUSTER</span><span class="k">}</span><span class="s2">"</span>
</code></pre></div></div>
<p>Yeni bir <strong>etkinlik(Event)</strong> oluşturalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php artisan make:event NotificationEvent
</code></pre></div></div>
<p>Yukarıdaki kod ile App\Events dizini altında <code class="language-plaintext highlighter-rouge">NotificationEvent.php</code> ismiyle bir dosya oluştu.
Oluşturduğumuz etklinliği yayınlayabilmek için etkinliğimiz <code class="language-plaintext highlighter-rouge">ShouldBroadcast</code> sınıfını uygulaması (implement) gerekmetedir.</p>
<p>Satırını</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">NotificationEvent</span>
</code></pre></div></div>
<p>Aşağıdaki şekilde değiştirelim.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">NotificationEvent</span> <span class="kd">implements</span> <span class="nc">ShouldBroadcast</span>
</code></pre></div></div>
<p>Satırını</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="k">new</span> <span class="nc">PrivateChannel</span><span class="p">(</span><span class="s1">'channel-name'</span><span class="p">);</span>
</code></pre></div></div>
<p>Aşağıdaki şekilde değiştirerek. Kanalımızı herkese açalım ve isimlendirelim.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="k">new</span> <span class="nc">Channel</span><span class="p">(</span><span class="s1">'notification-event'</span><span class="p">);</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">broadcastWith</code> methodu ile kanalımıza veri gönderebiliriz. Aşağıdaki satırları ekleyerek <code class="language-plaintext highlighter-rouge">notification-event</code> kanalımıza veri gönderelim.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">function</span> <span class="n">broadcastWith</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="p">[</span>
<span class="s1">'title'</span> <span class="o">=></span> <span class="s1">'Bildirim başlığı'</span><span class="p">,</span>
<span class="s1">'message'</span> <span class="o">=></span> <span class="s1">'Bildirim mesajı'</span><span class="p">,</span>
<span class="p">];</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>App\Events\NotificationEvent.php</strong> dosyasının son hali aşağıdaki gibi olmalıdır.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
<span class="kn">namespace</span> <span class="nn">App\Events</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Broadcasting\Channel</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Queue\SerializesModels</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Broadcasting\PrivateChannel</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Broadcasting\PresenceChannel</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Foundation\Events\Dispatchable</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Broadcasting\InteractsWithSockets</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Illuminate\Contracts\Broadcasting\ShouldBroadcast</span><span class="p">;</span>
<span class="kd">class</span> <span class="nc">NotificationEvent</span> <span class="kd">implements</span> <span class="nc">ShouldBroadcast</span>
<span class="p">{</span>
<span class="kn">use</span> <span class="nc">Dispatchable</span><span class="p">,</span> <span class="nc">InteractsWithSockets</span><span class="p">,</span> <span class="nc">SerializesModels</span><span class="p">;</span>
<span class="cd">/**
* Create a new event instance.
*
* @return void
*/</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//</span>
<span class="p">}</span>
<span class="cd">/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">broadcastOn</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">Channel</span><span class="p">(</span><span class="s1">'notification-event'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">broadcastWith</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="p">[</span>
<span class="s1">'title'</span> <span class="o">=></span> <span class="s1">'Bildirim başlığı'</span><span class="p">,</span>
<span class="s1">'message'</span> <span class="o">=></span> <span class="s1">'Bildirim mesajı'</span><span class="p">,</span>
<span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Etkinliklerimizi yayınlamak için <code class="language-plaintext highlighter-rouge">broadcast()</code> yardımcı(helper) methodundan yararlanabiliriz.
Test için “add-notification” ismi ile rota oluşturup. <code class="language-plaintext highlighter-rouge">broadcast()</code> yardımcı methodu ile etkinliğimizi yayınlıyalım.
<strong>Routes/web.php</strong> içerisine aşağıdaki rota(route) tanımlamasını yapalım.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Route</span><span class="o">::</span><span class="nf">get</span><span class="p">(</span><span class="s1">'add-notification'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nf">broadcast</span><span class="p">(</span><span class="k">new</span> <span class="err">\</span><span class="nc">App\Events\NotificationEvent</span><span class="p">);</span>
<span class="k">return</span> <span class="s1">'Bildirim Gönderildi.'</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">resouces/views/welcome.blade.php</code> dosyasında body etkiketi(tag) içerisini aşağıdaki kodları yerleştirelim.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
<span class="nt"><example-component></example-component></span>
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"/js/app.js"</span><span class="nt">></script></span>
</code></pre></div></div>
<p>Javascript bağımlılıklarını (paketleri) yükleyelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm <span class="nb">install
</span>npm <span class="nb">install</span> <span class="nt">--save</span> socket.io-client
npm <span class="nb">install</span> <span class="nt">--save</span> laravel-echo
</code></pre></div></div>
<p><strong>“resources/js/bootstrap.js”</strong> dosyasını açın, en alt satırına aşağıdaki kodu yerleştirin.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">Echo</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">laravel-echo</span><span class="dl">'</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">io</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">socket.io-client</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">Echo</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Echo</span><span class="p">({</span>
<span class="na">broadcaster</span><span class="p">:</span> <span class="dl">'</span><span class="s1">socket.io</span><span class="dl">'</span><span class="p">,</span>
<span class="na">host</span><span class="p">:</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">hostname</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">:6001</span><span class="dl">'</span>
<span class="p">});</span>
</code></pre></div></div>
<blockquote>
<p>not: bootstrap.js dosyası Laravel 5.6 ve daha alt sürümlerde resources/assets/js/bootstrap.js dizininde bulunur.</p>
</blockquote>
<p><strong>“resources/js/components/ExampleComponent.vue”</strong> dosyasının içerisindeki mounted methodunun içerisine aşağıdaki kodu yerleştirin.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">window</span><span class="p">.</span><span class="nx">Echo</span><span class="p">.</span><span class="nx">channel</span><span class="p">(</span><span class="dl">'</span><span class="s1">notification-event</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="dl">'</span><span class="s1">NotificationEvent</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="s2">`title: </span><span class="p">${</span><span class="nx">e</span><span class="p">.</span><span class="nx">title</span><span class="p">}</span><span class="s2"> , message: </span><span class="p">${</span><span class="nx">e</span><span class="p">.</span><span class="nx">message</span><span class="p">}</span><span class="s2">`</span><span class="p">)</span>
<span class="p">});</span>
</code></pre></div></div>
<p>Yukarıdaki satırları biraz açıklamak gerekirse <code class="language-plaintext highlighter-rouge">channel</code> methodu ile <code class="language-plaintext highlighter-rouge">notification-event</code> kanalına gelen <code class="language-plaintext highlighter-rouge">NotificationEvent</code> etkinliğini <code class="language-plaintext highlighter-rouge">listen</code> method ile dinliyoruz. <code class="language-plaintext highlighter-rouge">NotificationEvent</code> eklinliğinden gelen verileri de alert ile yazdırıyoruz.</p>
<p><strong>“resources/js/components/ExampleComponent.vue”</strong> dosyasının son hali aşağıdaki gibi olmadıdır.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><template></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"container"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"row justify-content-center"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"col-md-8"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"card"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"card-header"</span><span class="nt">></span>Example Component<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"card-body"</span><span class="nt">></span>
I'm an example component.
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></template></span>
<span class="nt"><script></span>
<span class="k">export</span> <span class="k">default</span> <span class="p">{</span>
<span class="nx">mounted</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Component mounted.</span><span class="dl">'</span><span class="p">)</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">Echo</span><span class="p">.</span><span class="nx">channel</span><span class="p">(</span><span class="dl">'</span><span class="s1">notification-event</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="dl">'</span><span class="s1">NotificationEvent</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="s2">`title: </span><span class="p">${</span><span class="nx">e</span><span class="p">.</span><span class="nx">title</span><span class="p">}</span><span class="s2"> , message </span><span class="p">${</span><span class="nx">e</span><span class="p">.</span><span class="nx">message</span><span class="p">}</span><span class="s2">`</span><span class="p">)</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>Javascript tarafında yaptığımız değişikliklerin derlenmesi için aşağıdaki kodu çalıştıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm run dev
</code></pre></div></div>
<p>Tarayıcıdan <code class="language-plaintext highlighter-rouge">http://localhost</code> adresine gidelim. Daha sonra Yeni bir sekme açarak <code class="language-plaintext highlighter-rouge">http://localhost/add-notification</code> adresine gidelim.
<img src="/assets/posts/5/add-notification.png" alt="laravel add notification" />
<code class="language-plaintext highlighter-rouge">http://localhost</code> adresine geri dönelim.</p>
<p><img src="/assets/posts/5/notification-example.png" alt="laravel broadcasting - bildirim örneği" /></p>
<p>Yukarıdaki çıktıyı aldıysanız her şey yolunda demektir.</p>
<hr />
<h4 id="sonuç">Sonuç</h4>
<p>Laravel Broadcasting, Echo, Redis, Vue Js nedir ? vb. sorulara cevap aradık. Basit gerçek zamanlı bildirim(notification) uygulaması ile öğrendiklerimizi pekiştirdik.</p>
<p>Daha detaylı bilgi için <a href="https://laravel.com/docs/5.8/broadcasting#presence-channels" target="_blank">Laravel</a> Dökümantasyonunu ziyaret edebilirsiniz.</p>
<p>Kaynak kodlarını <a href="https://github.com/oguzcandemircan/Laravel-Broadcasting-Real-Time-Notification-App" target="_blank">Github</a> ‘ da bulabilirsiniz.</p>
<p>Makaleyi oluştururken yararlandığım <a href="https://medium.com/@dennissmink/laravel-echo-server-how-to-24d5778ece8b" target="_blank">Kaynak</a></p>
<hr />Oğuzcan Demircanoguzcandemircan@gmail.comGünümüzde birçok modern web uygulaması kullanıcı deneyimini en üst seviyeye çıkartmak için “gerçek zamanlı (real time)” güncellenen arayüzler kullanır. Gerçek zamanlı arayüzler oluşturmak için ise “WebSoket (WebSocket)” teknolojisinden yararlanırlar.Yeni Nesil Geliştirme Ortamı Bölüm 3: Laradock2019-04-02T00:00:00+00:002019-04-02T00:00:00+00:00https://oguzcandemircan.com/yeni-nesil-gelistirme-ortami-bolum-3-laradock<p><strong>Yeni nesil geliştirme ortami</strong> serimizin 3. bölümüne hoş geldiniz.
Bu bölümde konumuz “<strong>Laradock</strong>”</p>
<hr />
<h4 id="laradock-nedir-">Laradock Nedir ?</h4>
<p><strong>Laradock</strong>, PHP ile uygulama geliştirmek için oluşturulmuş “Docker” altyapısı kullanan geliştirme ortamıdır. Adını her ne kadar “ Laravel + Docker “ kelimerinin ilk hecelerinden almış ve ilk çıkış amacı “Docker” ile “Laravel” geliştirme ortamı sunmak olsada. Zamanla Topluluğun desteğiyle Symfony, CodeIgniter WordPress, Drupal vb. diğer PHP projelerini destekler hale geldi.</p>
<hr />
<h4 id="hem-tekli-hemde-çoklu-proje-örneği-yapalım">Hem Tekli Hemde Çoklu Proje Örneği Yapalım</h4>
<h5 id="laradock-kurulumu">Laradock Kurulumu:</h5>
<p>Öncelikle githubta ki laradock projesini bilgisayarımıza kopyalayalım ve içerisine girelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/Laradock/laradock.git
<span class="nb">cd </span>laradock
</code></pre></div></div>
<p>Daha sonra .env-example dosyasını .env ismiyle kopyalayalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp </span>env-example .env
</code></pre></div></div>
<p><a href="#Tek-proje-örneği">Tek proje örneği için buraya tıklayın </a></p>
<p><a href="#çoklu-proje-örneği">Çoklu proje örneği için buraya tıklayın </a></p>
<hr />
<!-- Nginx, varsayılan konfigürasyonun da "index.html" dosyasını, Laradock ".env" dosyasında "APP_CODE_PATH_HOST" değişkeni ile belirtilen yolun içerisinde ki public klasörü içerisinde arar. Laradock ".env" dosyasında yer alan "APP_CODE_PATH_HOST" değişkeninin değeri ../ -->
<h4 id="tek-proje-örneği">Tek Proje Örneği</h4>
<p>Nginx servisini(Konteyner) bağımsız (detached) modda başlatalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># İlk defa çalıştırdığınızda bu kısım biraz uzun sürebilir.</span>
docker-compose up <span class="nt">-d</span> nginx mysql
</code></pre></div></div>
<p>Laradock klasörünün bir üst dizinine geçelim ve aşağıda ki kodları çalıştıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#public ismiyle klasör oluşturuyoruz.</span>
<span class="nb">mkdir </span>public
<span class="c">#public klasörünün içerisine index.html ismiyle dosya oluşturuyoruz.</span>
<span class="nb">touch </span>public/index.html
<span class="c">#index.html içerisine "<h1>Hello World</h1>" satırını ekliyoruz.</span>
<span class="nb">echo</span> <span class="s2">"<h1>Hello World</h1>"</span> <span class="o">></span> public/index.html
</code></pre></div></div>
<p>Tarayıcımızdan http://localhost adresine gidelim.
<img src="/assets/posts/3/one-project-example.jpg" alt="Laradock Tek Proje Örneği" /></p>
<p>Yukarıdaki çıktıyı aldıysak her şey yolunda demektir.</p>
<hr />
<h4 id="laravel-ile-çoklu-proje-örneği">Laravel ile Çoklu Proje Örneği</h4>
<!-- Nginx, varsayılan konfigürasyonuna göz atalım. -->
<p>Laradock klasörüne geçelim ve Laravel projemiz için gerekli olan Nginx ve Mysql servislerini bağımsız (detached) modda başlatalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># İlk defa çalıştırdığınızda bu kısım biraz uzun sürebilir.</span>
docker-compose up <span class="nt">-d</span> nginx mysql
</code></pre></div></div>
<p>Nginx konfigürasyonlarının tanımlandığı klasöre 2 adet yeni konfigürasyon dosyası oluşturalım ve gerekli tanımlamaları yapalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">touch </span>nginx/sites/project1.conf
<span class="nb">touch </span>nginx/sites/project2.conf
</code></pre></div></div>
<p><strong>“laradock/nginx/sites/project1.conf”</strong> dosyasının içerisine aşağıda ki tanımlamaları yapalım.</p>
<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
<span class="kn">listen</span> <span class="s">[::]:80</span><span class="p">;</span>
<span class="c1"># For https</span>
<span class="c1"># listen 443 ssl;</span>
<span class="c1"># listen [::]:443 ssl ipv6only=on;</span>
<span class="c1"># ssl_certificate /etc/nginx/ssl/default.crt;</span>
<span class="c1"># ssl_certificate_key /etc/nginx/ssl/default.key;</span>
<span class="kn">server_name</span> <span class="s">project1.local</span><span class="p">;</span>
<span class="kn">root</span> <span class="n">/var/www/project1/public</span><span class="p">;</span>
<span class="kn">index</span> <span class="s">index.php</span> <span class="s">index.html</span> <span class="s">index.htm</span><span class="p">;</span>
<span class="kn">location</span> <span class="n">/</span> <span class="p">{</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="nv">$uri</span><span class="n">/</span> <span class="n">/index.php</span><span class="nv">$is_args$args</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="p">~</span> <span class="sr">\.php$</span> <span class="p">{</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="n">/index.php</span> <span class="p">=</span><span class="mi">404</span><span class="p">;</span>
<span class="kn">fastcgi_pass</span> <span class="s">php-upstream</span><span class="p">;</span>
<span class="kn">fastcgi_index</span> <span class="s">index.php</span><span class="p">;</span>
<span class="kn">fastcgi_buffers</span> <span class="mi">16</span> <span class="mi">16k</span><span class="p">;</span>
<span class="kn">fastcgi_buffer_size</span> <span class="mi">32k</span><span class="p">;</span>
<span class="kn">fastcgi_param</span> <span class="s">SCRIPT_FILENAME</span> <span class="nv">$document_root$fastcgi_script_name</span><span class="p">;</span>
<span class="c1">#fixes timeouts</span>
<span class="kn">fastcgi_read_timeout</span> <span class="mi">600</span><span class="p">;</span>
<span class="kn">include</span> <span class="s">fastcgi_params</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="p">~</span> <span class="sr">/\.ht</span> <span class="p">{</span>
<span class="kn">deny</span> <span class="s">all</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="n">/.well-known/acme-challenge/</span> <span class="p">{</span>
<span class="kn">root</span> <span class="n">/var/www/letsencrypt/</span><span class="p">;</span>
<span class="kn">log_not_found</span> <span class="no">off</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">error_log</span> <span class="n">/var/log/nginx/project1_error.log</span><span class="p">;</span>
<span class="kn">access_log</span> <span class="n">/var/log/nginx/project1_access.log</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>“laradock/nginx/sites/project2.conf”</strong> dosyasının içerisine de aşağıda ki tanımlamaları yapalım.</p>
<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
<span class="kn">listen</span> <span class="s">[::]:80</span><span class="p">;</span>
<span class="c1"># For https</span>
<span class="c1"># listen 443 ssl;</span>
<span class="c1"># listen [::]:443 ssl ipv6only=on;</span>
<span class="c1"># ssl_certificate /etc/nginx/ssl/default.crt;</span>
<span class="c1"># ssl_certificate_key /etc/nginx/ssl/default.key;</span>
<span class="kn">server_name</span> <span class="s">project2.local</span><span class="p">;</span>
<span class="kn">root</span> <span class="n">/var/www/project2/public</span><span class="p">;</span>
<span class="kn">index</span> <span class="s">index.php</span> <span class="s">index.html</span> <span class="s">index.htm</span><span class="p">;</span>
<span class="kn">location</span> <span class="n">/</span> <span class="p">{</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="nv">$uri</span><span class="n">/</span> <span class="n">/index.php</span><span class="nv">$is_args$args</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="p">~</span> <span class="sr">\.php$</span> <span class="p">{</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="n">/index.php</span> <span class="p">=</span><span class="mi">404</span><span class="p">;</span>
<span class="kn">fastcgi_pass</span> <span class="s">php-upstream</span><span class="p">;</span>
<span class="kn">fastcgi_index</span> <span class="s">index.php</span><span class="p">;</span>
<span class="kn">fastcgi_buffers</span> <span class="mi">16</span> <span class="mi">16k</span><span class="p">;</span>
<span class="kn">fastcgi_buffer_size</span> <span class="mi">32k</span><span class="p">;</span>
<span class="kn">fastcgi_param</span> <span class="s">SCRIPT_FILENAME</span> <span class="nv">$document_root$fastcgi_script_name</span><span class="p">;</span>
<span class="c1">#fixes timeouts</span>
<span class="kn">fastcgi_read_timeout</span> <span class="mi">600</span><span class="p">;</span>
<span class="kn">include</span> <span class="s">fastcgi_params</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="p">~</span> <span class="sr">/\.ht</span> <span class="p">{</span>
<span class="kn">deny</span> <span class="s">all</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="n">/.well-known/acme-challenge/</span> <span class="p">{</span>
<span class="kn">root</span> <span class="n">/var/www/letsencrypt/</span><span class="p">;</span>
<span class="kn">log_not_found</span> <span class="no">off</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">error_log</span> <span class="n">/var/log/nginx/project2_error.log</span><span class="p">;</span>
<span class="kn">access_log</span> <span class="n">/var/log/nginx/project2_access.log</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Yukarıda tanımlamış olduğumuz nginx konfigürasyonlarının, nginx tarafından tanınması için nginx servisimizi yeniden başlatalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># laradock klasörü içerisinde</span>
docker-compose restart nginx
</code></pre></div></div>
<p>Tarayıcıdan http://project1.local adresinde gittiğimizde <strong>“project1”</strong> klasörü altındaki websitesini http://project2.local adresine gittiğimizde <strong>“project2”</strong> klasörü altındaki websitemizi getirmesi için.
“hosts” dosyasını düzenliyelim. Linux ‘ ta hosts dosyası “/etc” dizininde bulunurken windows ‘ ta “C:\Windows\System32\drivers\etc" dizininde bulunur.
İşletim sistemimize göre host dosyamızı bulduktan sonra içerisine aşağıdaki satırları ekliyelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>127.0.0.1 project1.local
127.0.0.1 project2.local
</code></pre></div></div>
<p>Daha sonra “workspace” servisimizin (Konteyner) içerisine “laradock” kullanıcısı ile girelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose <span class="nb">exec</span> <span class="nt">--user</span><span class="o">=</span><span class="s2">"laradock"</span> workspace bash
</code></pre></div></div>
<p>workspace servisimizin içerisinde composer, git, node, npm vb. bir çok gerekli araç gereç bulunuyor.
Laravel projelerimizi kurmak için workspace içerisinde ki Composer ‘ ı kullanacağız.
Workspace içerisindeyken aşağıdaki kodu çalıştıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer create-project <span class="nt">--prefer-dist</span> laravel/laravel project1
composer create-project <span class="nt">--prefer-dist</span> laravel/laravel project2
</code></pre></div></div>
<p>Tarayıcıdan <strong>http://project1.local</strong> ve <strong>http://project.2.local</strong> adreslerine gidelim.</p>
<p><img src="/assets/posts/3/laravel-welcome-page.jpg" alt="Laravel hoşgeldin sayfası - laradock örneği" /></p>
<p>Her iki adreste de yukardaki sayfa ile karşılaştıysak doğru yoldayız demektir.</p>
<hr />
<h4 id="mysql">Mysql</h4>
<p>“project1” projesine <strong>mysql</strong> bağlantısı yapalım.</p>
<p>project1 klasörü içerisinde ki “.env” dosyasını açalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">DB_HOST</span><span class="o">=</span>127.0.0.1
<span class="nv">DB_PORT</span><span class="o">=</span>3306
<span class="nv">DB_DATABASE</span><span class="o">=</span>homestead
<span class="nv">DB_USERNAME</span><span class="o">=</span>homestead
<span class="nv">DB_PASSWORD</span><span class="o">=</span>secret
</code></pre></div></div>
<p>olan satırları aşağıdaki gibi değiştirelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">DB_CONNECTION</span><span class="o">=</span>mysql
<span class="nv">DB_HOST</span><span class="o">=</span>mysql
<span class="nv">DB_PORT</span><span class="o">=</span>3306
<span class="nv">DB_DATABASE</span><span class="o">=</span>default
<span class="nv">DB_USERNAME</span><span class="o">=</span>root
<span class="nv">DB_PASSWORD</span><span class="o">=</span>root
</code></pre></div></div>
<p>workspace servisimizin içerisindeyken aşağıda ki komutları çalıştıralım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># project1 klasörü içerisine giriyoruz.</span>
<span class="nb">cd </span>project1
php artisan migrate
php artisan make:auth
</code></pre></div></div>
<p><strong>http://project1.local/register</strong> adresine gidelim ve gerekli alanları doldurarak kayıt işlemini gerçekleştirelim.
<img src="/assets/posts/3/register.png" alt="laravel kayıt sayfası - laradock" /></p>
<p>kayıt olduktan sonra <strong>http://project1.local/home</strong> adresine yönlendirileceksiniz.</p>
<p><img src="/assets/posts/3/home.png" alt="laravel home - laradock" /></p>
<p>Yukarıda ki gibi bir sayfa ile karşılaştıysak kayıt işlemimiz başarıyla gerçekleşmiştir.</p>
<p>Yaptığımız işlemleri veri tabanında görmek için <strong>“PhpMyAdmin”</strong> servisimizi başlatalım.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># laradock klasörü içerisinde iken</span>
docker-compose up <span class="nt">-d</span> phpmyadmin
</code></pre></div></div>
<p>PhpMyAdmin ‘ e erişmek için <strong>http://localhost:8080/</strong> adresine gidelim.</p>
<p><img src="/assets/posts/3/phpyadmin.png" alt="Laradock - PhpMyAdmin" /></p>
<p>Yukarıda ki gibi bir görüntü ile karşılaştıysak doğru yoldayız demektir.</p>
<table>
<tbody>
<tr>
<td>Sunucu</td>
<td>mysql</td>
</tr>
<tr>
<td>Kullanıcı Adı</td>
<td>root</td>
</tr>
<tr>
<td>Parola</td>
<td>root</td>
</tr>
</tbody>
</table>
<p>Gerekli alanları yukarıdaki tabloda verilen bilgilerle doldurup giriş yaplabiliriz.</p>
<p>Giriş yaptıktan sonra “default” veritabanının “users” tablosuna giderek kullanıcı kaydımızın gerçekleşip gerçekleşmediğini teyit edebiliriz.</p>
<p><img src="/assets/posts/3/phpmyadmin-2.png" alt="Laradock - PhpMyAdmin" /></p>
<p>Gördüğünüz gibi kayıt işlemimiz gerçekleşmiş. :)</p>
<hr />
<blockquote>
<p>Not: Veri tabanı ayarlarını yaparken root kullanıcısının şifresinin neden root olduğunu vs. merak ediyorsanız. Laradock klasörü altında <strong>“.env”</strong> dosyasını incelemenizi tavsiye ediyorum.
Laradock hakkında daha detaylı bilgi için <a href="http://laradock.io/">laradock.io</a> adresini ziyaret edebilirsiniz.</p>
</blockquote>
<hr />
<h3 id="sonuç">Sonuç</h3>
<p>“Yeni nesil geliştirme ortamı” serimizin 3. bölümünde konumuz Laradock ‘ tu. Bu bölümde
Laradock nedir ? Nasıl kullanılır öğrenmiş olduk. Hem tekli hemde çoklu proje örnekleri ile öğrendiklerimizi pekiştirdik.
Sizinde fark edeceğiniz üzere her yeni proje için, önce nginx konfigürasyonlarını ayarlıyoruz ve nginx servisimizi yeniden başlatıyoruz. Daha sonra etc dosyamızı düzenliyoruz. Son olarak da workspace servisimizin içerisine girip gerekli dosyaları composer vs. araçlar ile oluşturuyoruz. “Yeni nesil geliştirme ortamı” serimizin 4. bölümünde bu soruna değineceğiz ve bu işlemleri nasıl tek satır kod ile halledebileceğimizi öğreneceğiz. 4. bölümde görüşmek üzere.</p>Oğuzcan Demircanoguzcandemircan@gmail.comYeni nesil geliştirme ortami serimizin 3. bölümüne hoş geldiniz. Bu bölümde konumuz “Laradock”Yeni nesil geliştirme ortamı Bölüm 1: Docker2019-03-27T00:00:00+00:002019-03-27T00:00:00+00:00https://oguzcandemircan.com/yeni-nesil-gelistirme-ortami-bolum-1-docker<p><strong>Yeni nesil geliştirme ortamı</strong> adı altında başladığımız, 4.bölümlük yazı dizisinin 1. bölümüne hoş geldiniz.</p>
<p>Bu bölümde Docker, Dockerfile, Docker Container(Konteyner), Docker Image(imaj), nedir ? Docker biz geliştiriciler için ne ifade ediyor ? Neden Docker kullanalım ? Dockerı nasıl kullanırız vb. gibi sorulara cevap arıyacağız.</p>
<h4 id="docker-nedir-">Docker Nedir ?</h4>
<p>Docker çeşitli sanallaştırma ortamları Virtual box ve benzerlerine alternatif uygulama
geliştirme ve yayınlama alt yapı aracıdır.</p>
<blockquote>
<p>Not: bu makalede Docker ve Docker teknojisinden ziyade. Docker biz geliştiriciler için ne ifade ediyor ? Neden Docker kullanalım ? Dockerı nasıl kullanırız vb. gibi sorulara cevap arıyoruz. Docker ve Docker teknolojisi hakkında detaylı bilgi için Gökhan Şengünün <a href="https://gokhansengun.com" target="_blank">websitesini</a> ziyaret edebilirsiniz.</p>
</blockquote>
<hr />
<h4 id="dockerfile-nedir-">Dockerfile Nedir ?</h4>
<p>Dockerfile geliştirdiğimiz uygulamamızın / yazılımın gerekliklerinin ( örneğin: nginx apache mysql vb.) tanımlandığı dosyadır.</p>
<hr />
<h4 id="docker-image-nedir-">Docker Image Nedir ?</h4>
<p>Docker image, Dockerfile da tanımladığımız gerekliliklerin kurulup hazırlanmış görüntüsüdür.</p>
<hr />
<h4 id="docker-container-nedir-">Docker Container Nedir ?</h4>
<p>Docker Container, Docker imajlarımızın (image) çalıştırıldığı alandır.</p>
<hr />
<h4 id="peki-docker-bunu-nasıl-yapıyor---nasıl-çalışıyor-">Peki Docker Bunu Nasıl Yapıyor / Nasıl Çalışıyor ?</h4>
<p>Docker, Dockerfile da tanımlanan gereklilikleri <code class="language-plaintext highlighter-rouge">docker build .</code> komutu ile
yeni bir Docker İmajı oluşturup içerisine,
Dockerfile da tanımladığımız komutları tek tek çalıştırıp, gerekliliklerin kurulumlarını gerçekleştiriyor.
Sistemin çalışır halde olduğunu onayladıktan sonra
sistemin yedeğini yani imajını (image) alıp saklıyor. Hazırlanıp saklanan imajları</p>
<p><code class="language-plaintext highlighter-rouge">docker images</code> komutu ile görüntüleyebiliriz.</p>
<p><code class="language-plaintext highlighter-rouge">docker run {çalıştırmak_istediğimiz_imaj_idsi}</code> komut ile de imajını aldığımız sistemleri Docker Konteynerına koyup çalıştırıyor.
Hali hazırda çalışan imajları
<code class="language-plaintext highlighter-rouge">docker ps</code> komutu ile görüntüleyebiliriz.
<code class="language-plaintext highlighter-rouge">docker ps -a</code> komutu ile daha önce çalıştırılmış fakat şuanda çalışmayan konteynerları görüntüleyebiliriz.</p>
<hr />
<h3 id="biz-geliştiriciler-i̇çin-docker-ne-anlam-i̇fade-ediyor-">Biz Geliştiriciler İçin Docker Ne Anlam İfade Ediyor ?</h3>
<p>Geliştirdiğimiz herhangi bir uygulamayı yayına alırken kendi bilgisayarımızda çalışırken
sunucuda çalışmadığına en az 1 kere şahit olmuşuzdur. Docker sayesinde “ benim bilgisayarımda çalışıyordu “ sendromundan kurtuluyoruz. :)
Çünkü Docker sunucu ve çalışma ortamınızı eşitliyor. Kulağa hoş geliyor değil mi ?</p>
<hr />
<h3 id="docker-kurulumu">Docker Kurulumu</h3>
<p>Kurulumu Linux üzerinden anlatacağım diğer işletim sistemleri için docker dökümantasyonunda ki kurulum adımlarını takip edebilirsiniz.</p>
<p><a href="https://docs.docker.com/docker-for-windows/install/">Windows</a> - <a href="https://docs.docker.com/docker-for-mac/install/">Mac</a></p>
<p>Docker kurulumu:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># https://docs.docker.com/install/linux/docker-ce/ubuntu/</span>
<span class="nb">sudo </span>apt-get <span class="nb">install </span>apt-transport-https ca-certificates curl software-properties-common
curl <span class="nt">-fsSL</span> https://download.docker.com/linux/ubuntu/gpg | <span class="nb">sudo </span>apt-key add -
<span class="nb">sudo </span>add-apt-repository <span class="s2">"deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"</span>
<span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nb">install </span>docker-ce
</code></pre></div></div>
<p>Docker Compose kurulumu:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># https://docs.docker.com/compose/install/</span>
<span class="nb">sudo </span>curl <span class="nt">-L</span> https://github.com/docker/compose/releases/download/1.20.0/docker-compose-<span class="sb">`</span><span class="nb">uname</span> <span class="nt">-s</span><span class="sb">`</span>-<span class="sb">`</span><span class="nb">uname</span> <span class="nt">-m</span><span class="sb">`</span> <span class="nt">-o</span> /usr/local/bin/docker-compose
<span class="nb">sudo chmod</span> +x /usr/local/bin/docker-compose
</code></pre></div></div>
<p>Herhangi bir izin problemiyle karşılaşmamak için. “docker” kullanıcı grubu oluşturuyoruz ve mevcut kullanıcımızı oluşturduğumuz “docker” kullanıcı grubuna atıyoruz.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># https://docs.docker.com/install/linux/linux-postinstall/</span>
<span class="nb">sudo </span>groupadd docker
<span class="nb">sudo </span>usermod <span class="nt">-aG</span> docker <span class="nv">$USER</span>
</code></pre></div></div>
<hr />
<h3 id="basit-bir-örnek-yapalım">Basit Bir Örnek Yapalım</h3>
<p>Linux kullandığım için Linux komut satırı ( terminal ) üzerinden devam edeceğim.</p>
<p>İlk önce bir klasör oluşturalım ve içerisine girelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#docker-example adında klasör oluşturuyoruz.</span>
<span class="nb">mkdir </span>docker-example
<span class="c">#docker-example klasörünün içerisine giriyoruz</span>
<span class="nb">cd </span>docker-example
<span class="c">#Dockerfile ismiyle dosya oluşturuyoruz.</span>
<span class="nb">touch </span>Dockerfile
<span class="c">#www adında klasör oluşturuyoruz.</span>
<span class="nb">mkdir </span>www
<span class="c">#oluşturduğumuz www klasörünün içerisine " index.html" adında bir dosya oluşturuyoruz.</span>
<span class="nb">touch </span>www/index.html
<span class="c"># bir üst satırda oluşturduğumuz index.html içerisine ' <h1>Hello World</h1>' satırını ekliyoruz.</span>
<span class="nb">echo</span> <span class="s2">"<h1>Hello World</h1>"</span> <span class="o">></span> www/index.html
</code></pre></div></div>
<p>Dockerfile oluşturalım. Ve içerisine aşağıdaki komutları yazalım.</p>
<div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># nginx imajını referans alıyoruz.</span>
<span class="k">FROM</span><span class="s"> nginx </span>
<span class="c"># www klasörümüzü Docker konteyner içerisinde ki /usr/share/nginx/html içerisine kopyalıyoruz.</span>
<span class="k">COPY</span><span class="s"> /www /usr/share/nginx/html</span>
<span class="c"># Docker konteynerımızın içerisindeki 80 portunu dışarıya açıyoruz.</span>
<span class="k">EXPOSE</span><span class="s"> 80</span>
</code></pre></div></div>
<p>Dockerfile ile görüntü oluşturalım. Daha rahat kullanım için etiketliyelim. Ve görüntünün oluşup oluşmadığını kontrol edelim.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#Oluşturduğumuz Dockerfile ile görüntü(image) alıyoruz / oluşturuyoruz.</span>
docker build <span class="nt">-t</span> oguzcandemircan/nginx:1.0 <span class="nb">.</span>
<span class="c">#docker images komutu ile görüntümüzün(image) oluşup oluşmadığını kontrol ediyoruz.</span>
docker images
</code></pre></div></div>
<p>Aşığıdakine benzer bir çıktı almalısınız.
<img src="/assets/posts/1/docker-ps.png" alt="docker images çıktısı" /></p>
<p>Oluşturduğumuz imajı çalıştırıyoruz.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#Oluşturduğumuz imajı(image) çalıştırıyoruz.</span>
docker run <span class="nt">-p</span> 81:80 oguzcandemircan/nginx:1.0
<span class="c">#curl istek atıyoruz.</span>
curl http://localhost:81
</code></pre></div></div>
<p>curl yüklü değilse Herhangi bir tarayıcıdan http://localhost:81 adresine giderek aynı işlemi gerçekleştirebilirsiniz.</p>
<p>Herhangi bir sorun ile karşılaşmadıysanız aşağıda ki çıktıyı almalısınız.
<img src="/assets/posts/1/curl.png" alt="docker - curl istek çıktısı" /></p>
<hr />
<h3 id="sonuç">Sonuç</h3>
<p>Bu makalede <strong>Docker</strong>, <strong>Dockerfile</strong>, <strong>Docker Image</strong>, <strong>Docker Container</strong> nedir ? Nasıl
çalışır ? Öğrenmiş olduk. Basit bir örnekle öğrendiklerimizi uygulamaya dökerek pekiştirdik.
4 bölümlük “ yeni nesil geliştirme ortamı “ serisinin 1. bölümünü tamamladık.
Bir sonraki bölümde <strong>Docker Compose</strong> ile oluşturduğumuz konteynerları yönetme konusuna değineceğiz.</p>Oğuzcan Demircanoguzcandemircan@gmail.comYeni nesil geliştirme ortamı adı altında başladığımız, 4.bölümlük yazı dizisinin 1. bölümüne hoş geldiniz.Yeni Nesil Geliştirme Ortamı Bölüm 2: Docker Compose2019-03-27T00:00:00+00:002019-03-27T00:00:00+00:00https://oguzcandemircan.com/yeni-nesil-gelistirme-ortami-bolum-2-docker-compose<p><strong>Yeni Nesil Geliştirme Ortamı</strong> serimizin 2.bölümüne hoş geldiniz. 2. bölümde <br /> <strong>” Docker Compose “</strong> konusuna değineceğiz.
Docker Compose Nedir ? DockerHub Nedir ? docker-compose.yml nedir ? Docker Compose Nasıl çalışır ? vb. sorulara cevap arıyacağız.</p>
<hr />
<h4 id="docker-compose-nedir-">Docker Compose Nedir ?</h4>
<p>Docker Composer, Docker Konteynerların (Container) tek bir yml uzantılı dosya ile yönetmemize olanak sağlayan orkestrasyon aracıdır.</p>
<hr />
<h4 id="dockerhub-nedir-">DockerHub Nedir ?</h4>
<p>Github benzeri Docker imajlarının (Dockerfile) saklandığı uzak sunucudur.
<code class="language-plaintext highlighter-rouge">docker pull docker_hub_kullanıcı_adı/docker_imaj_adı</code> komutu ile uzaktaki imajı kendi bilgisayarımıza çekebiliriz.</p>
<hr />
<h4 id="docker-compose-nasıl-çalışır-">Docker Compose Nasıl Çalışır ?</h4>
<p><strong>Docker Compose</strong> çalışmak için bir adet “ <strong>docker-compose.yml</strong> “ ayar (config) dosyasına ihtiyaç duyar. Docker Compose “ docker-compose.yml “ dosyasında tanımlanan servisleri (Container) <code class="language-plaintext highlighter-rouge">docker-compose build</code> komutu ile imajını alır. <code class="language-plaintext highlighter-rouge">docker-compose up</code> komutu ile de Docker Container içersine koyar çalıştır. <code class="language-plaintext highlighter-rouge">docker-compose stop</code> komutu ile çalışan servisleri durdurabilir veya <code class="language-plaintext highlighter-rouge">docker-compose down</code> ile silebiliriz.</p>
<p>Hali hazırda çalışan servisleri görüntülemek için <code class="language-plaintext highlighter-rouge">docker-compose ps</code> komutunu kullanabiliriz.</p>
<hr />
<h4 id="basit-bir-örnek-yapalım">Basit Bir Örnek Yapalım</h4>
<p>Linux kullandığım için Linux komut satırı (terminal) üzerinden gideceğim. Terminal deyince hemen korkmanıza gerek yok basit klasör / dosya oluştur vb. işlemleri yapacağız. Siz isterseniz sağtık klasör/dosya oluştur vs. ile de yapabilirsiniz.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># docker-compose-example ismiyle bir klasör oluşturuyoruz.</span>
<span class="nb">mkdir </span>docker-compose-example
<span class="c"># docker-compose-example klasörünün içerisine giriyoruz.</span>
<span class="nb">cd </span>docker-compose-example
<span class="c"># musul ismiyle klasör oluşturuyoruz.</span>
<span class="nb">mkdir </span>musul
<span class="c"># musul klasörünün içerisine index.html oluşturuyoruz.</span>
<span class="nb">touch </span>musul/index.html
<span class="c"># musul klasörünün içerisinede ki index.html içerisine " <h1>Musul</h1> " satırını ekliyoruz.</span>
<span class="nb">echo</span> <span class="s2">"<h1>Welcome Musul</h1>"</span> <span class="o">></span> musul/index.html
<span class="c"># kerkuk ismiyle klasör oluşturuyoruz.</span>
<span class="nb">mkdir </span>kerkuk
<span class="c"># kerkuk klasörünün içerisine index.html oluşturuyoruz.</span>
<span class="nb">touch </span>kerkuk/index.html
<span class="c"># kerkük klasörünün içerisinede ki index.html içerisine " <h1>Kerkuk</h1> " satırını ekliyoruz.</span>
<span class="nb">echo</span> <span class="s2">"<h1>Welcome Kerkuk</h1>"</span> <span class="o">></span> kerkuk/index.html
<span class="c"># docker-compose.yml ismiyle bir dosya oluşturuyouz.</span>
<span class="nb">touch </span>docker-compose.yml
<span class="c"># oluşturduğumuz dosyanın içerisini dolduruyoruz.</span>
<span class="nb">echo</span> <span class="s1">'version: "3"
services:
website1:
image: nginx
ports:
- "82:80"
volumes:
- ./musul:/usr/share/nginx/html
website2:
image: nginx
ports:
- "83:80"
volumes:
- ./kerkuk:/usr/share/nginx/html
database:
image: mysql
restart: always
environment:
- MYSQL_DATABASE=veri_tabanı_adı
- MYSQL_ROOT_PASSWORD=root_sifresi
- MYSQL_USER=mysql_kullanicisi
- MYSQL_PASSWORD=mysql_kullanici_sifresi
ports:
- "8989:3306"'</span> <span class="o">></span> docker-compose.yml
</code></pre></div></div>
<!-- **" docker-compose.yml "** ismiyle bir dosya oluşturup içerisine aşağıdaki komutları yazalım. -->
<p>Tüm adımları eksiksiz uyguladıysak <strong>” docker-compose.yml “</strong> dosyamız aşığda ki gibi görünmelidir.</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">version</span><span class="pi">:</span> <span class="s1">'</span><span class="s">3'</span>
<span class="na">services</span><span class="pi">:</span>
<span class="na">website1</span><span class="pi">:</span>
<span class="na">image</span><span class="pi">:</span> <span class="s">nginx</span>
<span class="na">ports</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">82:80"</span>
<span class="na">volumes</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">./musul:/usr/share/nginx/html</span>
<span class="na">website2</span><span class="pi">:</span>
<span class="na">image</span><span class="pi">:</span> <span class="s">nginx</span>
<span class="na">ports</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">83:80"</span>
<span class="na">volumes</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">./kerkuk:/usr/share/nginx/html</span>
<span class="na">database</span><span class="pi">:</span>
<span class="na">image</span><span class="pi">:</span> <span class="s">mysql</span>
<span class="na">restart</span><span class="pi">:</span> <span class="s">always</span>
<span class="na">environment</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">MYSQL_DATABASE=veri_tabanı_adı</span>
<span class="pi">-</span> <span class="s">MYSQL_ROOT_PASSWORD=root_sifresi</span>
<span class="pi">-</span> <span class="s">MYSQL_USER=mysql_kullanicisi</span>
<span class="pi">-</span> <span class="s">MYSQL_PASSWORD=mysql_kullanici_sifresi</span>
<span class="na">ports</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">8989:3306"</span>
</code></pre></div></div>
<p>Dosyanın içeriğini inceliyelim.</p>
<table>
<thead>
<tr>
<th>Değer</th>
<th>Açıklaması</th>
</tr>
</thead>
<tbody>
<tr>
<td>Version</td>
<td>adından da anlaşılacağı üzere docker-compose version numaramız</td>
</tr>
<tr>
<td>services</td>
<td>kullanacağımız servislerin tanımlandığı alan.</td>
</tr>
<tr>
<td>website1</td>
<td>servisimizin adını tanımladığımız alan.</td>
</tr>
<tr>
<td>website2</td>
<td>diğer bir servisimizin adı.</td>
</tr>
<tr>
<td>mysql</td>
<td>bir başka servisimizin adı.</td>
</tr>
<tr>
<td>image</td>
<td>servizimizin kullanacağı imajı(image) adı.</td>
</tr>
<tr>
<td>volumes</td>
<td>Docker Konteyner ile kendi bilgisayarımızda ki klasörleri eşitlediğimiz alan</td>
</tr>
<tr>
<td>ports</td>
<td>servisimizin dışarıya açılan portun kendi bilgisayarımızda hangi porta karşılık geleceğini tanımladığımız alan.</td>
</tr>
<tr>
<td>restart</td>
<td>servisimiz herhangi bir sebepten ötürü durursa ne sıklıkta yeniden başlamayı deniyeceğini belirttiğimiz alan. örnek: “ always “ her zaman</td>
</tr>
<tr>
<td>environment</td>
<td>servisimizin ortam değişkenlerini tanımladığımız alan.</td>
</tr>
</tbody>
</table>
<p>daha iyi anlaşılması için bir kaç kısmı daha açıklayalım.</p>
<ul>
<li>
<p><strong>Volume</strong> :
<code class="language-plaintext highlighter-rouge">./musul:/usr/share/nginx/html </code> ifadesi ile bilgisayarımızda yer alan “musul” klasörünü servisimizin içerisinde ki “/usr/share/nginx/html” klasörüne eşitlemiş oluyoruz.</p>
</li>
<li>
<p><strong>Ports</strong> :
docker-compose.yml da yer alan <code class="language-plaintext highlighter-rouge">82:80</code> ifadesi ile servisimizin dışarıya açık olan “80” portunu bilgisayarımzda ki “82” portuna eşitlemiş oluyoruz.
daha sonra tarayıcımızdan http://localhost:82 yazarak servisimize erişebiliriz.</p>
</li>
<li>
<p><strong>environment</strong> :
<code class="language-plaintext highlighter-rouge">MYSQL_DATABASE=veri_tabanı_adı</code> ifadesi ile servisimizin içerisinde yer alan <code class="language-plaintext highlighter-rouge">MYSQL_DATABASE</code> değişkenini “veri_tabanı_adı” olarak ayarlamış oluyoruz.</p>
</li>
</ul>
<p><code class="language-plaintext highlighter-rouge">docker-compose up -d</code> komut ile servislerimizi ayağa kaldıralım.
<!-- herhangi bir sorun ile karşılaşmadıysanız aşağıdakine benzer bir çıktı almalısınız. -->
<!-- ![docker compose up komutu çıktı görüntüsü](/assets/posts/2/docker-compose-up.jpg) --></p>
<p>Tarayıcıdan önce http://localhost:82
<img src="/assets/posts/2/ornek-musul.jpg" alt="docker compose - ornek musul" />
daha sonra http://localhost:83 adresine gidelim.
<img src="/assets/posts/2/ornek-kerkuk.jpg" alt="docker compose - ornek kerkuk" /></p>
<p>Yukarıda ki çıktıları aldıysanız doğru yoldasınız demektir.</p>
<p><code class="language-plaintext highlighter-rouge">docker-compose exec {service_adı} {komut}</code> komutu ile servislerimizin içerisinde komut çalıştırabilmekteyiz. Örneğin :</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose <span class="nb">exec </span>database mysql <span class="nt">-uroot</span> <span class="nt">-proot_sifresi</span>
</code></pre></div></div>
<p>çıktı:
<img src="/assets/posts/2/docker-compose-database-connect.jpg" alt="docker compose exec örneği" /></p>
<p>veri tabanında ki tabloları görüntüleyelim.</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">show</span> <span class="n">databases</span><span class="p">;</span>
</code></pre></div></div>
<p>çıktı:
<img src="/assets/posts/2/docker-compose-mysql-show-database.jpg" alt="docker compose - show database" /></p>
<p>oluşturduğumuz.</p>
<p>“<strong>veri_tabanı_adi</strong>” adlı veri tabanını (database) görmekteyiz.</p>
<hr />
<h3 id="sonuç">Sonuç</h3>
<p>Docker Compose, docker-compose.yml, DockerHub, Nedir ? öğrenmiş olduk. Öğrendiklerimizide basit bir örnekle pekiştirdik.
“Yeni nesil geliştirme ortamı “ serimizin 2.bölümünü tamamladık. 3. bölümde “ <strong>Laradock</strong> “ konusuna değineceğiz.</p>Oğuzcan Demircanoguzcandemircan@gmail.comYeni Nesil Geliştirme Ortamı serimizin 2.bölümüne hoş geldiniz. 2. bölümde ” Docker Compose “ konusuna değineceğiz. Docker Compose Nedir ? DockerHub Nedir ? docker-compose.yml nedir ? Docker Compose Nasıl çalışır ? vb. sorulara cevap arıyacağız.