<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Mehmet Koca on Medium]]></title>
        <description><![CDATA[Stories by Mehmet Koca on Medium]]></description>
        <link>https://medium.com/@mhmtkc?source=rss-c2f08b6241ed------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*gC8Xv_hao8gZGorfG-05Ag.jpeg</url>
            <title>Stories by Mehmet Koca on Medium</title>
            <link>https://medium.com/@mhmtkc?source=rss-c2f08b6241ed------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 13 Jul 2026 12:41:36 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@mhmtkc/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Server Side Swift: Vapor 3 — Bölüm 3: Leaf ile Templating Part 2/2]]></title>
            <link>https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-3-leaf-ile-templating-part-2-2-e4288c29cd7d?source=rss-c2f08b6241ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/e4288c29cd7d</guid>
            <category><![CDATA[vapor]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[server-side-swift]]></category>
            <category><![CDATA[tutorial]]></category>
            <dc:creator><![CDATA[Mehmet Koca]]></dc:creator>
            <pubDate>Thu, 31 May 2018 07:29:32 GMT</pubDate>
            <atom:updated>2018-05-31T07:36:41.681Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/950/1*NAQHE8BCl_xQudufB0yexQ.png" /></figure><p>Merhaba 👋🏻</p><p>Leaf’e <a href="https://medium.com/@mhmtkc/server-side-swift-vapor-3-bölüm-3-leaf-ile-templating-part-1-2-5d80fa1d6536">birinci bölümde</a> giriş yaptıktan sonra bu bölümde;</p><ul><li>User &amp; Genre listeleme ve işlemleri</li><li>Song ekleme</li><li>Song güncelleme ve silme</li></ul><p>konularına bakacağız. Bunları API oluşturma bölümünde anlattığım şekilde (Rested ile istek atarak) de yapmıştık, farklı olarak burada UI üzerinde yapmış olacağız.</p><h3><strong>Users &amp; Genres</strong></h3><p>Üç tane page oluşturacağız; <strong>all users page</strong>, <strong>genre page, all genres page</strong>.</p><p><strong>All Users page</strong> ile başlayalım; ilk önce tüm userları getireceğimiz fonksiyon yapısı ile başlayalım. WebsiteController içerisinde tüm user’ları getirecek fonksiyonu yazıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/72d2129634460f8dca1a1b43b70bb24b/href">https://medium.com/media/72d2129634460f8dca1a1b43b70bb24b/href</a></iframe><p>Bu işlemi yaparken context’i oluşturup render etmek için WebsiteController altında bir struct oluşturuyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e5147317d1c56d0abc435b82c000172c/href">https://medium.com/media/e5147317d1c56d0abc435b82c000172c/href</a></iframe><p>Son olarak boot fonksiyonu içerisinde allUserHandler fonksiyonuınu kullanacağımız router’ı tanımlıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a1f6db7a06870d97a61effd0832967e4/href">https://medium.com/media/a1f6db7a06870d97a61effd0832967e4/href</a></iframe><p>View kısmı için <strong>allUsers.leaf</strong> dosyası oluşturuyoruz. İçeriği aşadağı gibi olacak;</p><pre>#set(&quot;content&quot;){</pre><pre>&lt;h1&gt;All Users&lt;/h1&gt;</pre><pre>#if(users) {</pre><pre>&lt;table class=&quot;table table-bordered table-hover&quot;&gt;</pre><pre>&lt;thead class=&quot;thead-light&quot;&gt;</pre><pre>&lt;tr&gt;</pre><pre>&lt;th&gt;Username&lt;/th&gt;</pre><pre>&lt;th&gt;Name&lt;/th&gt;</pre><pre>&lt;/tr&gt;</pre><pre>&lt;/thead&gt;</pre><pre>&lt;tbody&gt;</pre><pre>#for(user in users) {</pre><pre>&lt;tr&gt;&lt;td&gt;#(user.username)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/users/#(user.id)&quot;&gt;#(user.name)&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</pre><pre>}</pre><pre>&lt;/tbody&gt;</pre><pre>&lt;/table&gt;</pre><pre>} else {</pre><pre>&lt;h2&gt;There aren&#39;t any users yet!&lt;/h2&gt;</pre><pre>}</pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p>allUsers.leaf’e base içerisinde de yönlendirme vereceğimiz için <strong>base.leaf </strong>içerisinde küçük bir ekleme yapıyoruz.</p><pre>&lt;li class=&quot;nav-item #if(title == &quot;All Users&quot;){active}&quot;&gt;</pre><pre>&lt;a href=&quot;/users&quot; class=&quot;nav-link&quot;&gt;All Users&lt;/a&gt;</pre><pre>&lt;/li&gt;</pre><p><strong>Genre page</strong> ile devam ediyoruz. Genre page için kullanacağımız fonksiyonu implemente ediyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/12f3a9a026701d6a13ec0a2982d1011d/href">https://medium.com/media/12f3a9a026701d6a13ec0a2982d1011d/href</a></iframe><p>Genre için kullanacağımız context struct’ını WebsiteController.swift altında oluşturuyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/039c1f04b8e01669df4f34805ff50a21/href">https://medium.com/media/039c1f04b8e01669df4f34805ff50a21/href</a></iframe><p>boot fonksiyonu içerisinde route genreHandler’ı kullanacağımız router’ı tanımlıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d46dfd81ad7f8fdbb2fd6110e7925f99/href">https://medium.com/media/d46dfd81ad7f8fdbb2fd6110e7925f99/href</a></iframe><p><strong>genre.leaf</strong> oluşturalım. İçeriği aşağıdaki gibi olacak:</p><pre>#set(&quot;content&quot;) {</pre><pre>&lt;h1&gt;#(genre.name)&lt;/h1&gt;</pre><pre>#if(songs) {</pre><pre>&lt;table&gt;</pre><pre>&lt;thead&gt;</pre><pre>&lt;tr&gt;</pre><pre>&lt;th&gt;Artist&lt;/th&gt;</pre><pre>&lt;th&gt;Title&lt;/th&gt;</pre><pre>&lt;/tr&gt;</pre><pre>&lt;/thead&gt;</pre><pre>&lt;tbody&gt;</pre><pre>#for(song in songs) {</pre><pre>&lt;tr&gt;&lt;td&gt;#(song.artist)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/songs/#(song.id)&quot;&gt;#(song.title)&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</pre><pre>}</pre><pre>&lt;/tbody&gt;</pre><pre>&lt;/table&gt;</pre><pre>} else {</pre><pre>&lt;h2&gt;There aren&#39;t any song yet!&lt;/h2&gt;</pre><pre>}</pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p>Tarayıcıdan kontrol ediyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1z54PHrzB6Can9qA_1i3KA.png" /><figcaption>Tüm kullanıcıları listeledik</figcaption></figure><p>Son olarak tüm genre’ları getirmek için kullanacağımız yapıya geçelim. <strong>allGenresHandler</strong> fonksiyonunu implemente ediyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6b888f4a28fbf2fff5ed374964e786a5/href">https://medium.com/media/6b888f4a28fbf2fff5ed374964e786a5/href</a></iframe><p><strong>allGenresHandler</strong> için kullanacağımız context struct’ını WebSiteController altında tanımlıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/91beba340c7bca83b95bd09d50bf6964/href">https://medium.com/media/91beba340c7bca83b95bd09d50bf6964/href</a></iframe><p>boot fonksiyonu içerisinde route yapısını tanımlıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44a62baf3e6ebd3878405c4c2fa22e54/href">https://medium.com/media/44a62baf3e6ebd3878405c4c2fa22e54/href</a></iframe><p><strong>allGenres.leaf </strong>dosyasını oluşturuyoruz. İçeriği aşağıdaki gibi olacak:</p><pre>#set(&quot;content&quot;){</pre><pre>&lt;h1&gt;All Genres&lt;/h1&gt;</pre><pre>#if(genres) {</pre><pre>&lt;table class=&quot;table table-bordered table-hover&quot;&gt;</pre><pre>&lt;thead class=&quot;thead-light&quot;&gt;</pre><pre>&lt;tr&gt;</pre><pre>&lt;th&gt;Name&lt;/th&gt;</pre><pre>&lt;/tr&gt;</pre><pre>&lt;/thead&gt;</pre><pre>&lt;tbody&gt;</pre><pre>#for(genre in genres) {</pre><pre>&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;/genres/#(genre.id)&quot;&gt;#(genre.name)&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</pre><pre>}</pre><pre>&lt;/tbody&gt;</pre><pre>&lt;/table&gt;</pre><pre>} else {</pre><pre>&lt;h2&gt;There aren&#39;t any genres yet!&lt;/h2&gt;</pre><pre>}</pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p><strong>base.leaf</strong> içerisinde de all genres’i sekme olarak ekleyelim.</p><pre>&lt;li class=&quot;nav-item #if(title == &quot;All Genres&quot;){active}&quot;&gt;</pre><pre>&lt;a href=&quot;/genres&quot; class=&quot;nav-link&quot;&gt;All Genres&lt;/a&gt;</pre><pre>&lt;/li&gt;</pre><p>— Her song birden fazla genre’da olabileceği için SongContext struct’ı içerisinde küçük bir değişiklik yapıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/efb64808698812cf379fd7eada10ed74/href">https://medium.com/media/efb64808698812cf379fd7eada10ed74/href</a></iframe><p><strong>songHandler</strong> fonksiyonu içerisinde de değişiklik yapmamız gerekiyor.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0a4d6e5de191edf200e512049fa4c974/href">https://medium.com/media/0a4d6e5de191edf200e512049fa4c974/href</a></iframe><p>Her song’un ait olduğu genre’yı gösterebilmek için view içerisinde de eklemeleri yapalım. <strong>song.leaf</strong> sonunda aşağıdaki eklemeyi yapalım.</p><pre>#if(genres) {</pre><pre>&lt;h3&gt;Genres&lt;/h3&gt;</pre><pre>&lt;ul&gt;</pre><pre>#for(genre in genres) {</pre><pre>&lt;li&gt;</pre><pre>&lt;a href=&quot;/genres/#(genre.id)&quot;&gt;#(genre.name)&lt;/a&gt;</pre><pre>&lt;/li&gt;</pre><pre>}</pre><pre>&lt;/ul&gt;</pre><pre>}</pre><p>Tarayıcıdan kontrol ediyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qt9F-igyFz5b63APrwXedw.png" /><figcaption>Tüm Genre’ları listeledik</figcaption></figure><h3>Adding Songs</h3><p>Song ekleme işlemini web üzerinden yapmak için ilk önce WebsiteController.swift içerisinde fonksiyonlarımızı ve route yapımızı tanımlayacağız. Daha sonra view kısmını tamamlayıp Song ekleme işlemini test edeceğiz.</p><p>İlk olarak Song ekleme fonksiyonumuzu yazdık.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6ff1d715a70057e0b158e746b6c7842b/href">https://medium.com/media/6ff1d715a70057e0b158e746b6c7842b/href</a></iframe><p>Fonksiyon üzerindeki yorum satırlarında bahsettiğim gibi, ilgili sayfada kullanmamız gereken bir yapı olacağı için her zaman yaptığımız gibi AddSongContext adında bir struct oluşturduk:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/941285bce8a5f8337ef7aa0840944c87/href">https://medium.com/media/941285bce8a5f8337ef7aa0840944c87/href</a></iframe><p>boot fonksiyonu içerisinde fonksiyonumuzun route yapısını tanımlıyoruz:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/40b8735a594db28364bd436756173ba2/href">https://medium.com/media/40b8735a594db28364bd436756173ba2/href</a></iframe><p>View kısmına geçiyoruz. Views klasörü altında <strong>addSong.leaf</strong> adında bir dosya oluşturalım.</p><p>Oluşturduğumuz form tag’ı içerisinde method’u post olarak belirttiğimize dikkat ediyoruz.</p><pre>#set(&quot;content&quot;) {</pre><pre>&lt;h1&gt;Add Song&lt;/h1&gt;</pre><pre>&lt;form method=&quot;post&quot;&gt;</pre><pre>&lt;div class=&quot;form-group&quot;&gt;</pre><pre>&lt;label for=&quot;songArtist&quot;&gt;Artist&lt;/label&gt;</pre><pre>&lt;input type=&quot;text&quot; name=&quot;songArtist&quot; class=&quot;form-control&quot; id=&quot;songArtist&quot;/&gt;</pre><pre>&lt;/div&gt;</pre><pre>&lt;div class=&quot;form-group&quot;&gt;</pre><pre>&lt;label for=&quot;songTitle&quot;&gt;Title&lt;/label&gt;</pre><pre>&lt;input type=&quot;text&quot; name=&quot;songTitle&quot; class=&quot;form-control&quot; id=&quot;songTitle&quot;/ &gt;</pre><pre>&lt;/div&gt;<br></pre><pre>&lt;div class=&quot;form-group&quot;&gt;</pre><pre>&lt;label for=&quot;user&quot;&gt;User&lt;/label&gt;</pre><pre>&lt;select name=&quot;user&quot; class=&quot;form-control&quot; id=&quot;user&quot;&gt;</pre><pre>#for(user in users) {</pre><pre>&lt;option value=&quot;#(user.id)&quot;&gt;</pre><pre>#(user.name)</pre><pre>&lt;/option&gt;</pre><pre>}</pre><pre>&lt;/select&gt;</pre><pre>&lt;/div&gt;<br></pre><pre>&lt;button type=&quot;submit&quot; class=&quot;btn btn-success&quot;&gt;Send&lt;/button&gt;</pre><pre>&lt;/form&gt;</pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p>Inputlar ve User’ları listelediğimiz option yapısı yukarıdaki gibi oluşturuldu.</p><p>Sonraki aşamada view’da aldığımız bu dataları yine bir fonksiyon aracılığı ile göndermemiz gerekiyor. Bunun için <em>addSongPostHandler</em> fonksiyonu oluşturuyoruz. Fonksiyon içerisinde yorum satırları ile ayrıntılı açıklamayı yaptım:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/39517326f004b11a21f9233d2494ea41/href">https://medium.com/media/39517326f004b11a21f9233d2494ea41/href</a></iframe><p>Data için oluşturduğumuz struct:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/752f64ce889cb7cdfc2b84c912b98551/href">https://medium.com/media/752f64ce889cb7cdfc2b84c912b98551/href</a></iframe><blockquote>Url Encoded Form ile ilgili daha detaylı bilgi için aşağıdaki linki kullanabilirsiniz:</blockquote><blockquote><a href="https://docs.vapor.codes/3.0/url-encoded-form/overview/">https://docs.vapor.codes/3.0/url-encoded-form/overview/</a></blockquote><p>Fonksiyonun boot içerisinde route yapısını tanımlayalım:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9f542f2e3ae92a15f43dea17085d4946/href">https://medium.com/media/9f542f2e3ae92a15f43dea17085d4946/href</a></iframe><p>Son olarak anasayfaya <em>Add Song</em> sekmesi ekleyelim. Bu işlemi <strong>base.leaf</strong> içerisinde nav-bar bloğunda yapıyoruz:</p><pre>&lt;li class=&quot;nav-item #if(title == &quot;Add Song&quot;){active}&quot;&gt;</pre><pre>&lt;a href=&quot;/add-song&quot; class=&quot;nav-link&quot;&gt;Add Song&lt;/a&gt;</pre><pre>&lt;/li&gt;</pre><p>Değişikliklerimizi kontrol ediyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zN6ulcCLl4wpheUb_aXVKA.png" /><figcaption>Add Song sayfası</figcaption></figure><h3>Edit &amp; Delete Songs</h3><p>Bu bölümde edit ve delete işlemlerine bakacağız. Adım adım hangi yolu izlediğimizi anlatıyor olacağım.</p><p>Edit sayfamızı render edecek fonksiyonumuzla başlayalım:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8500323d9d1c4433cfa32fdad69b9f13/href">https://medium.com/media/8500323d9d1c4433cfa32fdad69b9f13/href</a></iframe><p>Context için her zamanki gibi struct oluşturuyoruz:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7cc2d59c65dd02ed8b4c491899266193/href">https://medium.com/media/7cc2d59c65dd02ed8b4c491899266193/href</a></iframe><blockquote>editing değişkeni uygulama içerisinde bir flag işlevi görecek. Durum özelinde View üzerinde değişiklikler veya işlemler yapmamızı sağlayacak.</blockquote><p>boot fonksiyonu içerisindeki route yapımız:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fdc0911a3f536c0d87fec90bc14effa9/href">https://medium.com/media/fdc0911a3f536c0d87fec90bc14effa9/href</a></iframe><p>View kısmında ise yine <em>addSong.leaf</em>’i kullanacağımız için biraz önce bahsettiğim editing değişkeni işimize yarayacak. Örneğin; edit modundaysak label’ları doldurup buton metnini değiştirebileceğiz.</p><pre>#set(&quot;content&quot;) {</pre><pre>&lt;h1&gt;<strong>#if(editing){Edit Song} else {Add Song}</strong>&lt;/h1&gt;</pre><pre>&lt;form method=&quot;post&quot;&gt;</pre><pre>&lt;div class=&quot;form-group&quot;&gt;</pre><pre>&lt;label for=&quot;songArtist&quot;&gt;Artist&lt;/label&gt;</pre><pre>&lt;input type=&quot;text&quot; name=&quot;songArtist&quot; class=&quot;form-control&quot; id=&quot;songArtist&quot; <strong>#if(editing){value=&quot;#(song.artist)&quot;}</strong>/&gt;</pre><pre>&lt;/div&gt;</pre><pre>&lt;div class=&quot;form-group&quot;&gt;</pre><pre>&lt;label for=&quot;songTitle&quot;&gt;Title&lt;/label&gt;</pre><pre>&lt;input type=&quot;text&quot; name=&quot;songTitle&quot; class=&quot;form-control&quot; id=&quot;songTitle&quot; <strong>#if(editing){value=&quot;#(song.title)&quot;}</strong>/&gt;</pre><pre>&lt;/div&gt;</pre><pre>&lt;div class=&quot;form-group&quot;&gt;</pre><pre>&lt;label for=&quot;user&quot;&gt;User&lt;/label&gt;</pre><pre>&lt;select name=&quot;user&quot; class=&quot;form-control&quot; id=&quot;user&quot;&gt;</pre><pre>#for(user in users) {</pre><pre>&lt;option value=&quot;#(user.id)&quot; <strong>#if(editing){#if(song.creatorID == user.id){selected}}</strong>&gt;</pre><pre>#(user.name)</pre><pre>&lt;/option&gt;</pre><pre>}</pre><pre>&lt;/select&gt;</pre><pre>&lt;/div&gt;</pre><pre>&lt;button type=&quot;submit&quot; class=&quot;btn btn-success&quot;&gt;<strong>#if(editing){Update} else {Send}</strong>&lt;/button&gt;</pre><pre>&lt;/form&gt;</pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p><strong>addSong.leaf </strong>dosyasının güncel hali yukarıdaki gibi olacak. Son halinden farklı olarak yaptığım değişiklikleri bold olarak işaretledim.</p><p>Yapılan edit işlemi sonucunda yeni verileri post işlemi ile yeniden sunucuya göndermemiz ve veritabanına kaydetmemiz gerekiyor.</p><p>Post işlemini gerçekleştirecek fonksiyonumuz şu şekilde olacak:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/563615f08b1f617df5ffb55047379f27/href">https://medium.com/media/563615f08b1f617df5ffb55047379f27/href</a></iframe><p>boot fonksiyonu içerisinde edit post fonksiyonunun route yapısı:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b08c7fcb3e9a8f6c1ee792041ffff4f0/href">https://medium.com/media/b08c7fcb3e9a8f6c1ee792041ffff4f0/href</a></iframe><p><em>Song.leaf </em>dosyasında her şarkı altına Edit butonu, Delete butonu bırakalım ve ekstra olarak varsa Genre’ları da görelim. <em>Song.leaf’</em>in güncel hali aşağıdaki gibi olacak:</p><pre>#set(&quot;content&quot;) {</pre><pre>&lt;h1&gt;#(song.title)&lt;/h1&gt;</pre><pre>&lt;h2&gt;#(song.artist)&lt;/h2&gt;</pre><pre>&lt;p&gt; Created by &lt;a href=&quot;/users/#(creator.id)/&quot;&gt;#(creator.name)&lt;/a&gt;</pre><pre><strong>#if(genres) {</strong></pre><pre><strong>&lt;h3&gt;Genres&lt;/h3&gt;</strong></pre><pre><strong>&lt;ul&gt;</strong></pre><pre><strong>#for(genre in genres) {</strong></pre><pre><strong>&lt;li&gt;</strong></pre><pre><strong>&lt;a href=&quot;/genres/#(genre.id)&quot;&gt;#(genre.name)&lt;/a&gt;</strong></pre><pre><strong>&lt;/li&gt;</strong></pre><pre><strong>}</strong></pre><pre><strong>&lt;/ul&gt;</strong></pre><pre><strong>}</strong></pre><pre><strong>&lt;form method=&quot;post&quot; action=&quot;/songs/#(song.id)/delete&quot;&gt;</strong></pre><pre><strong>&lt;a class=&quot;btn btn-primary&quot; href=&quot;/songs/#(song.id)/edit&quot; role=&quot;button&quot;&gt;Edit&lt;/a&gt;</strong></pre><pre><strong>&lt;input class=&quot;btn btn-danger&quot; type=&quot;submit&quot; value=&quot;Delete&quot; /&gt;</strong></pre><pre><strong>&lt;/form&gt;</strong></pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p>Delete fonksiyonu ve route tanımını yaptıktan sonra işlemleri tamamlamış olacağız.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/041ab3cfda8a7658f0a9d5aeae247bdf/href">https://medium.com/media/041ab3cfda8a7658f0a9d5aeae247bdf/href</a></iframe><p>boot fonksiyonu içerisindeki route yapısı:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4ae4298b4036b43d2f953d32fbeaf97c/href">https://medium.com/media/4ae4298b4036b43d2f953d32fbeaf97c/href</a></iframe><p>Tüm işlemleri tamamladık. Son olarak ekran görüntülerine bakalım:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yhBaMv0bJYI_n3bvrFRurA.png" /><figcaption>Song sayfasının Edit ve Delete butonları ile birlikte son hali.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MmX5JkGHv6dhNmNQlw1K4g.png" /><figcaption>Edit Song sayfası.</figcaption></figure><p>Leaf ile Templating kısmında anlatacaklarım bu kadardı. Bundan sonraki yazı <strong>authentication</strong> ile ilgili olacak ve Vapor 3 serisi için şimdilik son yazı olacak 🙄</p><p>Leaf ile ilgili daha detaylı bilgi almak isterseniz <a href="https://docs.vapor.codes/3.0/leaf/basics/">bu linkten</a> faydalanabilirsiniz.</p><p>Projenin güncel hali ile tüm kodlarına <a href="https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial">github reposundan</a> ulaşabilirsiniz.</p><p><strong>İletişim: mehmetkoca@outlook.com</strong></p><p>🍻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e4288c29cd7d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-3-leaf-ile-templating-part-2-2-e4288c29cd7d">Server Side Swift: Vapor 3 — Bölüm 3: Leaf ile Templating Part 2/2</a> was originally published in <a href="https://medium.com/nsistanbul">NSIstanbul</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Server Side Swift: Vapor 3 — Bölüm 3: Leaf ile Templating Part 1/2]]></title>
            <link>https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-3-leaf-ile-templating-part-1-2-5d80fa1d6536?source=rss-c2f08b6241ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/5d80fa1d6536</guid>
            <category><![CDATA[api-development]]></category>
            <category><![CDATA[vapor]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Mehmet Koca]]></dc:creator>
            <pubDate>Tue, 27 Mar 2018 20:34:41 GMT</pubDate>
            <atom:updated>2018-05-14T08:16:01.697Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/950/1*-E4xcNe2P-O2mtsYff4FlA.png" /></figure><p>Merhaba🤞🏻,</p><p>API oluşturma işlemini <a href="https://medium.com/@mhmtkc/server-side-swift-vapor-3-bölüm-2-api-oluşturma-part-1-2-809e7cf8485c">Part 1</a> ve <a href="https://medium.com/@mhmtkc/server-side-swift-vapor-3-api-oluşturma-part-2-2-f93923d6db45">Part 2</a> ile tamamladıktan sonra, aynı proje üzerinden templating ile devam ediyoruz.</p><p><strong>Leaf</strong>, Vapor’un yayınladığı bir templating language.</p><h3>Getting Started with Leaf</h3><p><strong>Package.swift </strong>dosyasını açalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mRgadWgplUa5gifyYnDxww.png" /></figure><p>dependencies içerisine Leaf’in git url’ini yazdık ve targets içerisindeki App’e Leaf’i ekledik.</p><p>Templating dosyalarını tutacağımız Views klasörünü oluşturalım ve projeyi yeniden generate edelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RxaPtuKjjB9c9MoVZRrElA.png" /></figure><p><strong>configure.swift </strong>class’ını açıp Leaf’i import ediyoruz.</p><pre>import FluentMySQL</pre><pre>import Vapor</pre><pre><strong>import Leaf</strong></pre><p>Daha sonra <strong>LeafProvider</strong>’ı services’a register etmemiz gerekiyor.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dee603799aef21bb89961774bb13688b/href">https://medium.com/media/dee603799aef21bb89961774bb13688b/href</a></iframe><p>Artık Leaf’i kullanmaya başlayabiliriz. Konsol üzerinden WebsiteController oluşturalım ve projeyi yeniden generate edelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PsQYuS3Uo66vmZhW993Exw.png" /></figure><p>İlk aşamada <strong>WebsiteController.swift</strong> class’ı aşağıdaki gibi olacak:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/34adcb264cab35c7c5abc5db31fc943e/href">https://medium.com/media/34adcb264cab35c7c5abc5db31fc943e/href</a></iframe><p>Controller’dan devam etmeden önce <strong>Routes.swift </strong>içerisinde WebsiteController’ı tanıtalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f6c50747aba3561e89e44c5387408401/href">https://medium.com/media/f6c50747aba3561e89e44c5387408401/href</a></iframe><p>WebsiteController’a dönüyoruz ve son hali aşağıdaki gibi olacak. Kod satırları içerisinde gerekli açıklamaları yaptım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cb00a9de61e0ffd78cfab75229801faa/href">https://medium.com/media/cb00a9de61e0ffd78cfab75229801faa/href</a></iframe><p>Kullandığınız kod editörünü açarak Resorces/Views altında <strong>index.leaf</strong> dosyasını oluşturalım ve içerisine aşağıdaki kodu yazalım:</p><pre>&lt;!DOCTYPE html&gt;</pre><pre>&lt;html lang=&quot;en&quot;&gt;</pre><pre>&lt;head&gt;</pre><pre>&lt;meta charset=&quot;utf-8&quot;/&gt;</pre><pre>&lt;title&gt;Hello World | Songs&lt;/title&gt;</pre><pre>&lt;/head&gt;</pre><pre>&lt;body&gt;</pre><pre>&lt;h1&gt;Hello World&lt;/h1&gt;</pre><pre>&lt;/body&gt;</pre><pre>&lt;/html&gt;</pre><p><strong>index.leaf</strong> dosyasını kaydettikten sonra uygulamamızı Xcode üzerinden çalıştırıyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*b_VjlTk1ZUsHtLk81wi72g.png" /></figure><p><a href="http://lcoalhost:8080">http://localhost:8080</a>&#39;e girdiğimizde yukarıdaki sonucu görmemiz gerekiyor. ✌🏻</p><p>Title’da her zaman sabit bir yazı yazsın istemiyorum. Parametre alan bir yapı kullanarak title’ı dinamik hale getireceğiz. Öncelikle <strong>index.leaf </strong>dosyasında aşağıdaki gibi küçük bir değişiklik yapalım.</p><pre>&lt;!DOCTYPE html&gt;</pre><pre>&lt;html lang=&quot;en&quot;&gt;</pre><pre>&lt;head&gt;</pre><pre>&lt;meta charset=&quot;utf-8&quot;/&gt;</pre><pre>&lt;title&gt;<strong>#(title)</strong> | Songs&lt;/title&gt;</pre><pre>&lt;/head&gt;</pre><pre>&lt;body&gt;</pre><pre>&lt;h1&gt;Hello World&lt;/h1&gt;</pre><pre>&lt;/body&gt;</pre><pre>&lt;/html&gt;</pre><p>WebsiteController içerisinde aşağıdaki birkaç değişikliği yapacağız. İlk önce yine controller class’ında <strong>IndexContent </strong>adında Encodable bir yapı oluşturuyoruz. Tek değişkeni olan title’a index() içerisinde atama yaparak render edildiğinde kullanılmasını sağlıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b878e5c02335081b411adb9d538fd857/href">https://medium.com/media/b878e5c02335081b411adb9d538fd857/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7bed10a561986671dedd1ba4bc55ee3d/href">https://medium.com/media/7bed10a561986671dedd1ba4bc55ee3d/href</a></iframe><p>Uygulamayı Xcode üzerinden tekrar çalıştırdığımızda title’ın kod içerisinde aradığımız <strong>Homepage </strong>olarak görünmesi gerekiyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/796/1*KetxttOchX9TgiWdg9hPJg.png" /></figure><h3>Leaf Features</h3><p>leaf uzantılı dosyamızın body’sinde biraz değişlik yapalım. Leaf’in getirdiği özellikleri de görmüş olacağız.</p><pre>&lt;body&gt;</pre><pre>&lt;h1&gt;Songs&lt;/h1&gt;</pre><pre><strong>#if(songs) { </strong></pre><pre>&lt;table&gt;</pre><pre>&lt;thead&gt;</pre><pre>&lt;tr&gt;</pre><pre>&lt;th&gt;Artist&lt;/th&gt;</pre><pre>&lt;th&gt;Title&lt;/th&gt;</pre><pre>&lt;/tr&gt;</pre><pre>&lt;/thead&gt;</pre><pre>&lt;tbody&gt;</pre><pre><strong>#for(song in songs) {</strong></pre><pre>&lt;tr&gt;&lt;td&gt;<strong>#(song.artist)</strong>&lt;/td&gt;&lt;td&gt;<strong>#(song.title)</strong>&lt;/td&gt;&lt;/tr&gt;</pre><pre><strong>}</strong></pre><pre>&lt;/tbody&gt;</pre><pre>&lt;/table&gt;</pre><pre><strong>}</strong> <strong>else {</strong></pre><pre>&lt;h2&gt;There aren&#39;t any song yet!&lt;/h2&gt;</pre><pre><strong>}</strong></pre><pre>&lt;/body&gt;</pre><p>Basit bir html table oluşturduk. Bold olarak işaretlediklerim leaf’in özelliklerini kullandığımız kısımlar. <strong>if </strong>kontrolü ile herhangi bir song var mı yok mu bunu kontrol ediyoruz; yoksa, bir uyarı mesajı bırakıyoruz. <strong>for</strong> içerisinde ise var olan song’ları artist ve title’ına göre sıralayacağız.</p><p>WebsiteContoller’a dönüyoruz ve daha önceden oluşturduğumuz IndexContent struct’ı içerisine Song tipinde bir dizi oluşturuyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/627397ea14ee1a32d20d39a2accf3d24/href">https://medium.com/media/627397ea14ee1a32d20d39a2accf3d24/href</a></iframe><p>Şimdi index fonksiyonunu güncelleyelim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9829f9c085306079b8855ffe36957be1/href">https://medium.com/media/9829f9c085306079b8855ffe36957be1/href</a></iframe><p>Uygulamayı çalıştırdığımızda veritabanımızda kayıt yoksa şu ekranla karşılaşmamız gerekiyor:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/738/1*bA74TrTdZWMoTt-aByZK2w.png" /></figure><p>User ve Song ekledikten sonraki ekran görüntümüz de şu şekilde olacak:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P2ceg7NIp-AYDHALwHI0gw.png" /></figure><p>Anasayfada gördüğümüz Song’lara link verme konusunu inceleyelim.</p><pre>&lt;tbody&gt;</pre><pre>#for(song in songs) {</pre><pre>&lt;tr&gt;&lt;td&gt;#(song.artist)&lt;/td&gt;&lt;td&gt;<strong>&lt;a href=&quot;/songs/#(song.id)&quot;&gt;</strong>#(song.title)<strong>&lt;/a&gt;</strong>&lt;/td&gt;&lt;/tr&gt;</pre><pre>}</pre><pre>&lt;/tbody&gt;</pre><p>tbody etiketi içerisinde yukarıdaki değişikliği yapıyoruz. Tekrar WebsiteController’a dönelim.</p><p>Song content’i için bir struct oluşturduk.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/34b2572742717b4c773f6844c69458e5/href">https://medium.com/media/34b2572742717b4c773f6844c69458e5/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/97e2e963fa5403d1d561900a0622082c/href">https://medium.com/media/97e2e963fa5403d1d561900a0622082c/href</a></iframe><p>Song için kullanacağımız fonksiyon bu şekilde. Her zaman yaptığımız gibi boot içerisinde bu fonksiyonu kullanalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/503b6d0c0141924078caadf32568ca09/href">https://medium.com/media/503b6d0c0141924078caadf32568ca09/href</a></iframe><p><strong>index.leaf</strong>’i aynı path içerisinde kopyalayıp <strong>song.leaf</strong> dosyasını oluşturalım.</p><pre>&lt;!DOCTYPE html&gt;</pre><pre>&lt;html lang=&quot;en&quot;&gt;</pre><pre>&lt;head&gt;</pre><pre>&lt;meta charset=&quot;utf-8&quot;/&gt;</pre><pre>&lt;title&gt;#(title) | Songs&lt;/title&gt;</pre><pre>&lt;/head&gt;</pre><pre>&lt;body&gt;</pre><pre>&lt;h1&gt;#(song.title)&lt;/h1&gt;</pre><pre>&lt;h2&gt;#(song.artist)&lt;/h2&gt;</pre><pre>&lt;p&gt; Created by #(creator.name)</pre><pre>&lt;/body&gt;</pre><pre>&lt;/html&gt;</pre><p><strong>song.leaf</strong> dosyasının içeriğini yukarıdaki gibi ayarlıyoruz. Uygulamayı çalıştırıp görelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*B-eChRYHyPdympJ80k288g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*htwOMvWsM8Lql8fcKN9oQA.png" /></figure><h3><strong>Embedding Templates</strong></h3><p>Kod tekrarı yapılmasını engellemek için bir leaf dosyası içinde başka bir leaf dosyasının içeriğini gösterebiliriz. Örneğin header ve footer birçok sayfada aynı ise her seferinde ilgili bölümlerin kodlarını yeniden yazmak yerine bir base.leaf dosyası oluşturup içeriğini diğer dosyalardan çekebiliriz.</p><p><strong>index.leaf </strong>dosyasını kopyalayıp yeni leaf dosyasına <strong>base.leaf</strong> olarak adlandıralım.</p><p><strong>base.leaf </strong>body etiketi arasındaki kodları temizleyelim. base.leaf dosyasının en son hali aşağıdaki gibi.</p><pre>&lt;!DOCTYPE html&gt;</pre><pre>&lt;html lang=&quot;en&quot;&gt;</pre><pre>&lt;head&gt;</pre><pre>&lt;meta charset=&quot;utf-8&quot;/&gt;</pre><pre>&lt;title&gt;#(title) | Songs&lt;/title&gt;</pre><pre>&lt;/head&gt;</pre><pre>&lt;body&gt;</pre><pre>&lt;/body&gt;</pre><pre>&lt;/html&gt;</pre><p><strong>index.leaf</strong> dosyası içerisinde sadece if kontrol bloğumuz kalacak ve bu kodları <em>#set(“content”)</em> içerisine alacağız. En altta da <em>#embed(“base”) </em>ile base.leaf içerisinde kullanımını sağlayacağız. <strong>index.leaf</strong>’in son hali aşağıdaki gibi olacak.</p><pre><strong>#set(&quot;content&quot;){</strong></pre><pre>&lt;h1&gt;Songs&lt;/h1&gt;</pre><pre>#if(songs) {</pre><pre>&lt;table&gt;</pre><pre>&lt;thead&gt;</pre><pre>&lt;tr&gt;</pre><pre>&lt;th&gt;Artist&lt;/th&gt;</pre><pre>&lt;th&gt;Title&lt;/th&gt;</pre><pre>&lt;/tr&gt;</pre><pre>&lt;/thead&gt;</pre><pre>&lt;tbody&gt;</pre><pre>#for(song in songs) {</pre><pre>&lt;tr&gt;&lt;td&gt;#(song.artist)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/songs/#(song.id)&quot;&gt;#(song.title)&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</pre><pre>}</pre><pre>&lt;/tbody&gt;</pre><pre>&lt;/table&gt;</pre><pre>} else {</pre><pre>&lt;h2&gt;There aren&#39;t any song yet!&lt;/h2&gt;</pre><pre>}</pre><pre><strong>}</strong></pre><pre><strong>#embed(&quot;base&quot;)</strong></pre><p><strong>base.leaf </strong>içerisinde index.leaf kodlarını nasıl kullanabildik, bakalım. base.leaf’in son hali aşağıdaki gibi olacak.</p><pre>&lt;!DOCTYPE html&gt;</pre><pre>&lt;html lang=&quot;en&quot;&gt;</pre><pre>&lt;head&gt;</pre><pre>&lt;meta charset=&quot;utf-8&quot;/&gt;</pre><pre>&lt;title&gt;#(title) | Songs&lt;/title&gt;</pre><pre>&lt;/head&gt;</pre><pre>&lt;body&gt;</pre><pre><strong>#get(content)</strong></pre><pre>&lt;/body&gt;</pre><pre>&lt;/html&gt;</pre><p>Aynı işlemi song.leaf için de yapıyoruz. song.leaf’in son hali aşağıdaki gibi olacak:</p><pre><strong>#set(&quot;content&quot;) {</strong></pre><pre>&lt;h1&gt;#(song.title)&lt;/h1&gt;</pre><pre>&lt;h2&gt;#(song.artist)&lt;/h2&gt;</pre><pre>&lt;p&gt; Created by #(creator.name)</pre><pre><strong>}</strong></pre><pre><strong>#embed(&quot;base&quot;)</strong></pre><p>Genel anlamda embeded templates kısmı bu şekilde hallediliyor.</p><p>Şimdi Song title’larını linklendirdiğimiz gibi User name’i de linklendirelim ve User sayfasına girdiğimizde eklediği tüm song’ları listeleyelim.</p><p>Öncelikle daha önce yaptığımız gibi bu listeleme için bir struct oluşturalım WebsiteController.swift altında.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f1391284f2488b3a8d15f0a2d436e1ab/href">https://medium.com/media/f1391284f2488b3a8d15f0a2d436e1ab/href</a></iframe><p>Kullanacağımız fonksiyon Song için yaptığımıza çok benzer olacak:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4a2f81c607d3d8ce21df6b605a9e136d/href">https://medium.com/media/4a2f81c607d3d8ce21df6b605a9e136d/href</a></iframe><p>Fonksiyonu boot içerisine kaydedelim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c97bfd5515062a5c552368af5448b01f/href">https://medium.com/media/c97bfd5515062a5c552368af5448b01f/href</a></iframe><p>User sayfası için <strong>user.leaf</strong> dosyasını oluşturalım.</p><pre>#set(&quot;content&quot;) {</pre><pre>&lt;h1&gt;#(user.name)&lt;/h1&gt;</pre><pre>&lt;h2&gt;#(user.username)&lt;/h2&gt;</pre><pre>#if(songs) {</pre><pre>&lt;table&gt;</pre><pre>&lt;thead&gt;</pre><pre>&lt;tr&gt;</pre><pre>&lt;th&gt;Artist&lt;/th&gt;</pre><pre>&lt;th&gt;Title&lt;/th&gt;</pre><pre>&lt;/tr&gt;</pre><pre>&lt;/thead&gt;</pre><pre>&lt;tbody&gt;</pre><pre>#for(song in songs) {</pre><pre>&lt;tr&gt;&lt;td&gt;#(song.artist)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/songs/#(song.id)&quot;&gt;#(song.title)&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</pre><pre>}</pre><pre>&lt;/tbody&gt;</pre><pre>&lt;/table&gt;</pre><pre>} else {</pre><pre>&lt;h2&gt;There aren&#39;t any song yet!&lt;/h2&gt;</pre><pre>}</pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p>Son olarak <strong>song.leaf </strong>içerisinde küçük bir değişiklik yapalım. Song altındaki user’a tıkladığımızda yeni sayfaya yönlendirmesi için.</p><pre>#set(&quot;content&quot;) {</pre><pre>&lt;h1&gt;#(song.title)&lt;/h1&gt;</pre><pre>&lt;h2&gt;#(song.artist)&lt;/h2&gt;</pre><pre>&lt;p&gt; Created by <strong>&lt;a href=&quot;/users/#(creator.id)/&quot;&gt;</strong>#(creator.name)<strong>&lt;/a&gt;</strong></pre><pre>}</pre><pre>#embed(&quot;base&quot;)</pre><p>Uygulamayı çalıştırıyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y9HoqkNGxU7BU_eNJ0VCHw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gWIG3MMoTFjCbSoGsvq4BQ.png" /></figure><h3>Try! Bootstrap</h3><p>Bootstrap’in kullanımı standart html sayfalarındaki gibi olduğu için uzun uzun anlatmayacağım. <strong>base.leaf</strong> içerisinde bootstrap kullanmak için gerekli css ve javascript kodlarını yerleştirdikten sonra istediğiniz şekilde diğer leaf dosyalarını da class’lar ile şekillendirebilirsiniz.</p><p>Yaptığım birkaç değişiklik ile birlikte uygulamanın son halinin sadece ekran görüntüsünü atıyorum. <a href="https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial/tree/master/Resources/Views">Github reposu</a> içinde kodları inceleyebilirsiniz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4rvl0y7BBXb4Ib1i0use3A.png" /></figure><p>Fazla uzatmamak adına bu bölümü burada tamamlıyorum. Leaf ile Templating’in ikinci bölümünde görüşmek üzere 👋🏻</p><p>Github repo: <a href="https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial">https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial</a></p><p><strong>İletişim: mehmetkoca@outlook.com</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5d80fa1d6536" width="1" height="1" alt=""><hr><p><a href="https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-3-leaf-ile-templating-part-1-2-5d80fa1d6536">Server Side Swift: Vapor 3 — Bölüm 3: Leaf ile Templating Part 1/2</a> was originally published in <a href="https://medium.com/nsistanbul">NSIstanbul</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Server Side Swift: Vapor 3 — Bölüm 2: API Oluşturma Part 2/2]]></title>
            <link>https://medium.com/nsistanbul/server-side-swift-vapor-3-api-olu%C5%9Fturma-part-2-2-f93923d6db45?source=rss-c2f08b6241ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/f93923d6db45</guid>
            <category><![CDATA[api-development]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[vapor]]></category>
            <dc:creator><![CDATA[Mehmet Koca]]></dc:creator>
            <pubDate>Tue, 13 Mar 2018 16:20:04 GMT</pubDate>
            <atom:updated>2018-03-27T21:02:34.696Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/950/1*wjRXJiSnl0EbWdAGsVnmdw.jpeg" /></figure><p>Merhaba 👋🏻,</p><p><a href="https://medium.com/@mhmtkc/server-side-swift-vapor-3-bölüm-2-api-oluşturma-part-1-2-809e7cf8485c">Part 1</a>&#39;de oluşturmaya başladığımız API uygulamasına devam ediyoruz. Parent-child ilişkilerine ve Fluent query’lerine geçmeden önce uygulamaya <strong>User</strong> ve <strong>Genre</strong> ekleyelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_etCTbJg8LfECPAyDlNFiw.png" /></figure><p>User ve Genre sınıfları ile bu sınıfların controller’larını da ekledikten sonra uygulamamızı yeniden çalıştırıyoruz.</p><pre>vapor xcode -y</pre><p>User sınıfını implemente edelim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/825013a538599705adfa72d318fcb930/href">https://medium.com/media/825013a538599705adfa72d318fcb930/href</a></iframe><p>Extension’ları User sınıfına ekledikten sonra <strong>configure.swift </strong>sınıfı içerisinde SQLite’in User’ı kullanacağını belirtiyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c84d4f361b4387e6214d5639c124b7dc/href">https://medium.com/media/c84d4f361b4387e6214d5639c124b7dc/href</a></iframe><p>UsersController’ı oluşturmaya başlayalım. Daha önceden yaptığım gibi yorum satırlarında açıklamaları ekledim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3bca3798e2f8c36817afe0c9752f4695/href">https://medium.com/media/3bca3798e2f8c36817afe0c9752f4695/href</a></iframe><p>UsersController’ı kullanabilmek için Routes.swift içerisinde kaydetmeyi unutmuyoruz.</p><p>routes.swift sınıfının son hali şu şekilde olacak:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b2334b4d9d5fd37faf0dcdab3b561d7c/href">https://medium.com/media/b2334b4d9d5fd37faf0dcdab3b561d7c/href</a></iframe><p>Genre sınıfını implemente edelim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8e4ec8471b1ebcb59b34370c17f14d09/href">https://medium.com/media/8e4ec8471b1ebcb59b34370c17f14d09/href</a></iframe><p><strong>configure.swift </strong>sınıfı içerisinde SQLite’in Genre’yı kullanacağını belirtiyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e6cdb478eb4c294de750b31b6377c487/href">https://medium.com/media/e6cdb478eb4c294de750b31b6377c487/href</a></iframe><p>GenresController’ı implemente edelim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e34e52865172427ba96ba45d8e3bf0bc/href">https://medium.com/media/e34e52865172427ba96ba45d8e3bf0bc/href</a></iframe><p>GenresController’ı kullanabilmek için routes.swift içerisinde kaydediyoruz. routes.swift’in son hali şu şekilde olacak;</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/365b58f9fadecb985bd3f325305a69fb/href">https://medium.com/media/365b58f9fadecb985bd3f325305a69fb/href</a></iframe><h3>Parent Child Relationships</h3><p>Elimizde Song, User ve Genre modelleri var. Doğru çalışan bir sistem için bunlar arasında anlamlı bir ilişki kurulması gerekiyor. One to one, one to many gibi modeller arasında bir ilişki kurup implemente edeceğiz.</p><p>Örneğin, User birden fazla Song oluşturabilir. Ama her Song’un bir creator (User)’ı vardır. Fluent ile bu ilişki çok basit bir şekilde tanımlanabiliyor.</p><p>İlk olarak Song sınıfından başlayalım. Her Song için onu oluşturan bir User olduğu için <strong>User.ID</strong> tipinde <strong>creatorID</strong> değişkeni yaratıyoruz ve bunu init() içerisine de ekliyoruz. Daha sonra Song’ için bir computed property yaratıyoruz. Bu property’nin type’ı (Parent&lt;&gt;) ilişkiyi belirtiyor, ve kod bloğu içerisinde parent’ın id’sini geri döndürüyoruz. Daha açıklayıcı olması için yorum satırları ile birlikte Song sınıfının son hali aşağıda görüldüğü gibi olacak.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e33ad882e713ff510ed7acb8564a217b/href">https://medium.com/media/e33ad882e713ff510ed7acb8564a217b/href</a></iframe><p>Child olan Song için parent’ını tanımlama işlemini tamamladık. Şimdi User sınıfı içerisinde Song’ların User’ın child’ı olacağını tanımlayalım.</p><p>User sınıfının son hali şu şekilde olacak;</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6ff58e6a129a3d31cbd6bc3898cbdc59/href">https://medium.com/media/6ff58e6a129a3d31cbd6bc3898cbdc59/href</a></iframe><p>SongsController içerisinde daha işlevsel fonksiyon ekleyelim. Herhangi bir Song’u ekleyen User’ı bulalım. Bunun için aşağıdaki fonksiyonu kullanacağız;</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8169cc3fe4582d1c14ba8fd8ea2481c2/href">https://medium.com/media/8169cc3fe4582d1c14ba8fd8ea2481c2/href</a></iframe><p>Bu fonksiyonu boot kod bloğu içerisine kaydedelim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ca24c9b1255e684aa54d7026aa98d1c4/href">https://medium.com/media/ca24c9b1255e684aa54d7026aa98d1c4/href</a></iframe><p>Şimdi bir User’ın eklediği tüm Song’ları getiren fonksiyonu yazalım. UsersController’ı açıyoruz. Geriye Song array’i döndüren aşağıdaki fonksiyonu yazıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bed6e7f522391e8cfba6fb5306ae3df2/href">https://medium.com/media/bed6e7f522391e8cfba6fb5306ae3df2/href</a></iframe><p>Fonksiyonu boot kod bloğu içerisine kaydedelim.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f32bc06d31f4154f60811bf52ebe4eac/href">https://medium.com/media/f32bc06d31f4154f60811bf52ebe4eac/href</a></iframe><p>Şimdi uygulamamızı çalıştırıp test edelim. İlk önce User oluşturuyorum.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x_-woJdR1bFopd6oCkhFPw.png" /></figure><p>Fluent’in oluşturduğumuz User için verdiği id’yi kopyalayalım. Bu id’yi Song eklerken creatorID parametresi ile göndereceğiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FW8xhupg-5mxMshOU1LmDg.png" /></figure><p>creatorID’miz ile Song’u ekledik. Response Body içerisinde ayrıntılı olarak görüyoruz. Bir Song daha ekleyelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*71umAYycLV-iHpzZMjY4Aw.png" /></figure><p>Şimdi User’ın eklediği tüm Song’ları get isteği ile alalım. Burada kullanacağımız url yapısı;</p><pre>http://localhost:8080/api/users/CREATOR_ID/songs</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_TdXWnrufJvc-XXL3Bz4BA.png" /><figcaption>🤩</figcaption></figure><p>Son olarak Song’u ekleyen User’ı getiren fonksiyonumuzu test edelim. Kullanacağımız route yapısı;</p><pre>http://localhost:8080/api/songs/1/creator</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ou6WnnmVw2mYG3A41EIrTw.png" /></figure><p>Parent child ilişkilerinde bahsetmem gereken kısımlar şimdilik bu kadar. Fluent ile modeller arasında ilişki kurmak kolay bir şekilde gerçekleştirilebiliyor.</p><h3>Sibling Relationships</h3><p>Bir Song birden fazla Genre’ye dahil olabilir. Bir Genre içerisinde de birden fazla Song olabilir. Bu ilişki many to many şeklindedir. Bu ilişkiyi implemente etmek için aralarında “Pivot” oluşturmamız gerekir.</p><p>Uygulamaya SongGenrePivot.swift dosyasını ekleyelim ve projeyi yeniden başlatalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5YkuG1B3wGLmnO0W1rHyiQ.png" /></figure><p>Fluent’in iki model arasında ilişki kuracağını anlaması için gerekli olan iki typealias oluşturmamız gerekiyor. Böylece Fluent pivot’un sol ve sağının ne olduğunu bilecek.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/716e1ca6ce30c801e275d89a190f10bd/href">https://medium.com/media/716e1ca6ce30c801e275d89a190f10bd/href</a></iframe><p>configure.swift içerisinde modelimizi ekliyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/128d6ebcb69ba8ce31c99b275d1c67ef/href">https://medium.com/media/128d6ebcb69ba8ce31c99b275d1c67ef/href</a></iframe><p>Parent child ilişkisinde yaptığımız gibi sibling ilişkisi içinde Modellerimiz içinde computed property oluşturmamız gerekecek.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/60aa58669bd0c6583df055dec52bc767/href">https://medium.com/media/60aa58669bd0c6583df055dec52bc767/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/834bbd00c8c05adc97aa025e352c2a19/href">https://medium.com/media/834bbd00c8c05adc97aa025e352c2a19/href</a></iframe><p>Contoller’lar içerisinde yeni route yapıları tanımlayalım. SongsController ile başlayalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5ac7667e50cdb7e0290f108d96437731/href">https://medium.com/media/5ac7667e50cdb7e0290f108d96437731/href</a></iframe><p>bu fonksiyonu boot kod bloğu içerisinde tanımlayalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8bdc6ac2fca646ffa9c2ec7d071537ca/href">https://medium.com/media/8bdc6ac2fca646ffa9c2ec7d071537ca/href</a></iframe><p>GenreController içerisinde Song’ları alacağımız fonksiyonu tanımlayalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cded811b1bb3525229d2da064bc3eea5/href">https://medium.com/media/cded811b1bb3525229d2da064bc3eea5/href</a></iframe><p>fonksiyonu boot kod bloğu içerisinde route işlemi için kullanalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9bd4c0fc3e113b9a0a0e1c036be9c4f0/href">https://medium.com/media/9bd4c0fc3e113b9a0a0e1c036be9c4f0/href</a></iframe><p>Şimdi bir Song’u bir Genre’ya ekleme işlevini implemente edelim. Bu fonksiyon geriye HTTPStatus dönecek.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4f12cffdf3f50843ee51710fe249bb67/href">https://medium.com/media/4f12cffdf3f50843ee51710fe249bb67/href</a></iframe><p>boot içerisinde fonksiyonu route için kullanalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bfc97eb4a990ec0a0581964a065edaae/href">https://medium.com/media/bfc97eb4a990ec0a0581964a065edaae/href</a></iframe><p>Son değişiklikleri uygulamamızı çalıştırıp deneyelim. Yeniden çalıştırdığım için önceki veriler elimde yok. User oluşturarak başlayalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rPq4_uQYe0Q7jzektfpvOg.png" /></figure><p>User id’yi kopyalayıp Song eklemek için parametre olarak kullanıyorum.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7ZBE4tywxs-GmN0Ix4f88g.png" /></figure><p>Genre oluşturalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OCk8bzjxx-B4955MGfuYaQ.png" /></figure><p>Id’si 1 olan Song’u id’si 1 olan Genre’ya ekleyelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qaxHBJb2k_KQE45LZNa_KA.png" /></figure><p>Response header içerisinde 200 OK’u gördük; işlem başarılı. Şimdi id’si 1 olan Song’un hangi Genre’da olduğunu test edelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5VG6S1VecuMZuWe8PurSNw.png" /></figure><p>Son olarak id’si 1 olan Genre’da bulunan Song’ları getirelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cHrGoX4tY4Mr78FkVVWYUA.png" /></figure><p>Böylelikle yazdığımız tüm fonksiyonları test etmiş olduk. Modeller arasındaki ilişkiler tamamlanmış oldu.</p><h3>Fluent Queries</h3><p>Şimdiye kadar yaptığımız işlemlerde bir Song’u kaydetme, tüm Genre’ları getirme gibi işlemleri yaptık. Bu bölümde Fluent ile filtreleme işlemlerine bakalım.</p><p>SongController içerisine searchSong() fonksiyonu ekleyeceğiz. Fluent query’lerini kullanacağımız için class içerisine Fluent’i import ediyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/82337a2a5ff7002d221feee19b486f7f/href">https://medium.com/media/82337a2a5ff7002d221feee19b486f7f/href</a></iframe><p>Fonksiyonu boot içerisinde kullanalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b0cadd6ce9c9fc1600e6ca84d8ccbe17/href">https://medium.com/media/b0cadd6ce9c9fc1600e6ca84d8ccbe17/href</a></iframe><p>Buraya kadar her şey güzel. Sadece artist üzerinden değil de title üzerinden de arama yapmak istiyorum. Bunun için <strong>filter group</strong> kullanacağız. Fluent ile iki parametre için de ayrı search işlemi tanımlamak çok kolay. Tekrar seachSong() fonksiyonuna geri dönüyorum.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b074bf2d9783fd4ae458dd05c90736a4/href">https://medium.com/media/b074bf2d9783fd4ae458dd05c90736a4/href</a></iframe><p>Fonksiyonumuzun son hali yukarıdaki gibi olacak. Syntax yeterince temiz olduğu için kolayca anlaşılabiliyor.</p><p>Şimdi uygulamayı çalıştırıp deneyelim;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WbhabPhSx63jhWqU1odF-Q.png" /><figcaption>Yeni bir user oluşturdum.</figcaption></figure><p>Song ekleyelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cbjbnjYLVkQExaAmnJWkGA.png" /></figure><p>Şimdi search işlemini title üzerinden deneyelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9WPSujbdEbzVkLtHXiMRMg.png" /></figure><p>URL’e dikkat edelim ve Response Body içerisinde bize dönen değeri kontrol edelim.</p><p>Şimdi artist üzerinden arama yapalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zNVWaS_hiShCAZ7pT5cp2A.png" /></figure><p>Görüldüğü gibi fonksiyon iki parametre için de arama sonuçlarını getirdi. Burada dikkat edilmesi gereken nokta, URL içerisinde space karakteri ile istek atamayız. Rested’ın space’leri ‘%20’ ile otomatik değiştirdiğini görüyoruz sağ üst tarafta. Bu yapı kullanılırken space karakterleri için kontrol yapmayı unutmamanız gerekir.</p><h3>MySQL ile Fluent Kullanımı</h3><p>İster Docker üzerinden ister kendi bilgisayarınız üzerindeki MySQL üzerinden bağlantı işlemini gerçekleştirebilirsiniz.</p><p><strong>Package.swift</strong> dosyasını açıyoruz ve içerisini aşağıdaki gibi değiştiriyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/09ac6dd1ec8ce6f2f2fd3381ef69cf14/href">https://medium.com/media/09ac6dd1ec8ce6f2f2fd3381ef69cf14/href</a></iframe><pre>vapor xcode -y</pre><p>Projeyi yeniden başlatalım.İlk önce <strong>configure.swift </strong>içerisinde birtakım değişiklikler yapmamız gerekiyor. Proje içerisinde <strong>FluentSQLite</strong> geçen her import’u <strong>FluentMySQL</strong> ile değiştiriyoruz. Aynı şekilde herhangi bir keyword SQLite içeriyorsa onları da ‘SQLite’ yerine ‘MySQL’ versiyonu ile değiştiriyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b063d380cac82ce3cd3f8ebaecb93954/href">https://medium.com/media/b063d380cac82ce3cd3f8ebaecb93954/href</a></iframe><p>MySQL database’i tanıttık. Ben localde “vapor” adında bir database yaratmıştım. Sonraki aşamada ,aynı class içerisinde, “configure migrations” bölümünde “.sqlite” olarak seçtiğimiz kısımları da “.mysql” olarak değiştirelim.</p><p>Ek olarak vapor projesini ilk oluşturduğumuzda default gelen Todo.swift ve TodoController.swift dosyalarını silelim. Onlara ihtiyacımız yok. <strong>routes.swift</strong> içerisinde de Todo ile ilgili kısmı tamamen silelim.</p><p>Şimdi projeyi çalıştırdığımızda oluşturulacak olan User, Song vb. yapılar MySQL üzerinde kaydolacak. Ben konfigurasyonu tamamlayıp bir adet User oluşturdum.</p><p>MySQL içerisinde Fluent bizim için table’ları oluşturuyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/330/1*gc8WhOa1hzRbmMk1YZ2nVQ.png" /></figure><p>User oluşturduktan sonra users table’ı içerisinde kayıtları görebiliyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dsTdejBVr5XKx3p_Y8l5yQ.png" /></figure><p>Not: Vapor hala beta aşamasında olduğu için MySQL bağlantı aşamasında “No such module FluentMySQL” hatası alıyorsanız Swift 4.1&#39;in en son snapshot’ını indirip Xcode üzerinden seçmeniz gerekiyor. Konu ile ilgili link: <a href="https://gist.github.com/tanner0101/cdb77c7f58d53af2ba2da5d39415389a">https://gist.github.com/tanner0101/cdb77c7f58d53af2ba2da5d39415389a</a></p><p>API oluşturma bölümünü tamamlamış olduk. 🤓 Sonraki bölümde Leaf ile Templating konusunu anlatmaya çalışacağım.</p><p>İletişim için: <strong>mehmetkoca@outlook.com</strong></p><p>Github reposuna ulaşmak için: <a href="https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial">https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial</a></p><p>🍻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f93923d6db45" width="1" height="1" alt=""><hr><p><a href="https://medium.com/nsistanbul/server-side-swift-vapor-3-api-olu%C5%9Fturma-part-2-2-f93923d6db45">Server Side Swift: Vapor 3 — Bölüm 2: API Oluşturma Part 2/2</a> was originally published in <a href="https://medium.com/nsistanbul">NSIstanbul</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Server Side Swift: Vapor 3 — Bölüm 2: API Oluşturma Part 1/2]]></title>
            <link>https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-2-api-olu%C5%9Fturma-part-1-2-809e7cf8485c?source=rss-c2f08b6241ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/809e7cf8485c</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[vapor]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[api-development]]></category>
            <dc:creator><![CDATA[Mehmet Koca]]></dc:creator>
            <pubDate>Fri, 09 Mar 2018 13:33:03 GMT</pubDate>
            <atom:updated>2018-03-27T14:41:11.864Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/947/1*ZPF7sNpwwrlYeiyzEBPipg.png" /></figure><p>Merhaba 🙋🏻‍♂️,</p><p>Bu bölümde API oluşturmaya başlıyoruz. ORM aracı olarak Fluent kullanacağım. Fluent Vapor’un yayınladığı bir araç; veritabanı işlemlerinde kolaylık sağlayacak. Fluent, PostgreSQL, MySQL, SQLite ve MongoDB ile beraber çalışabiliyor. Fluent 3&#39;ün getirdiği yenilikler için aşağıdaki linki inceleyebilirsiniz;</p><p><a href="https://geeks.brokenhands.io/blog/posts/whats-new-in-vapor-3/">https://geeks.brokenhands.io/blog/posts/whats-new-in-vapor-3/</a></p><h3>Model Oluşturma ve Fluent</h3><p>PlaylistApp adında yeni bir proje açarak başlıyorum.</p><pre>vapor new PlaylistApp --branch=beta</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EoH8rWkbw7ViCKl4E2PE2g.png" /></figure><p>Proje dizinine girip Sources/App altındaki Models klasöründe <strong>Song.swift</strong> dosyasını yaratalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pX4AIW-Fs-RfkE-fpaeH3A.png" /></figure><pre>vapor xcode -y</pre><p><strong>Song.swift </strong>sınıfını yarattıktan sonra yukarıdaki komut ile projeyi Xcode ile açalım. Song sınıfına id, artist ve title değişkenlerini tanımlıyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/736/1*T7iCy3HipMLABsJOES8ziQ.png" /></figure><p>Vapor’u ve SQLite’ı geliştirme ortamında kullanabilmek için 1. ve 2. satırda görüldüğü gibi import ediyoruz.</p><p>En altta görülen extensionlar Song sınıfını kullanabilmemiz için özellikler sunuyor.</p><p><strong>SQLiteModel</strong>, Fluent’in Song sınıfını veritabanı işlemlerinde model olarak tanımasını sağlayacak.</p><p><strong>Content</strong>, Song sınıfının HTTP mesajları için decode ve encode edilmesine izin vermesini sağlıyor.</p><p><strong>Migration</strong>, Song sınıfının veritabanı işlemlerinde dinamik geçiş ve taşıma işlemlerinin yapılmasını sağlayacak.</p><p>Song sınıfını hazırladıktan sonra <strong>configure.swift </strong>sınıfı içerisindeki Configure migrations altında default gelen Todo sınıfının kullanılmasını sağlayan kodu silip yerine Song sınıfını tanımlayalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*grBnmEDCIB2gxOqmUFeZpw.png" /><figcaption>configure.swift sınıfının son hali bu şekilde.</figcaption></figure><p>Command+B ile build edip hata olup olmadığını kontrol edin.</p><h3>Controller Oluşturma ve CRUD İşlemleri</h3><p>Fluent ile model entegrasyonunu tamamladıktan sonra create, retrieve, update ve delete fonksiyonlarını implemente edeceğiz.</p><p><strong>SongsController.swift</strong> dosyasını oluşturalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dE7B5rEgBHJn_WdfF6hRXQ.png" /></figure><p><strong><em>vapor xcode -y</em></strong> ile projeyi yeniden başlatıyoruz.</p><p>SongsController sınıfı aşağıdaki gibi olacak. Daha anlaşılır olması için yorum satırlarında neyin ne işe yaradığını anlatmaya çalıştım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5ILmGhS7YsbnFmy9EuS7gA.png" /><figcaption>Vapor, Future tipinde geri dönüş değeri sağlar. Future, provider ile receiver arasında duran bir varlıktır. Provider geri dönüşü Future ile yapar. Ayrıntılı bilgi için; <a href="https://docs.vapor.codes/3.0/async/futures/">https://docs.vapor.codes/3.0/async/futures/</a></figcaption></figure><p>SongsContoller’a Song ekleme ve var olan Song’ları geri döndürecek iki fonksiyon tanımladık. SongsController’ı <strong>routes.swift </strong>içerisinde de tanımlayıp kullanılabilir hale getireceğiz. <strong>routes.swift</strong> içerisinde default olarak gelen kodları siliyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eDNsIQ4PYdWeZxq7T4g5ZQ.png" /></figure><p><strong>routes.swift</strong> sınıfının son hali yukarıdaki gibi olacak. Oluşturduğumuz controller’ı register ettik ve şu an kullanılabilir durumda.</p><p>Uygulamayı çalıştıralım ve request atarak deneme yapalım. Ben Rested uygulamasını kullanacağım. Postman veya Imsomnia gibi rest client uygulamarını da kullanabilirsiniz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_yVZRzG6JwP_ZU04oRjXnw.png" /></figure><p><a href="http://localhost:8080/api/songs">http://localhost:8080/api/songs</a> adresine get isteği atıp HTTP 200&#39;ü response headers içerisinde gördük.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nLDqRqbwTvXam_vLTR0CDg.png" /></figure><p>Aynı URL’e post isteği atıyoruz. Bu sefer parametre değerlerini giriyoruz. Parametlerimiz Song sınıfını init ederken kullandığımız değişkenler olacak. Response body’de gördüğümüz gibi Fluent, id’yi otomatik olarak algılıyor ve post işlemini tamamlıyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WBBYdQfVFSeGDtlwgT3wng.png" /></figure><p>Tekrar get isteği atıyoruz ve array içerisinde biraz önce girdiğimiz Song’u geri döndürüyor.</p><h3><strong>CRUD İşlemlerini Tamamlayalım</strong></h3><p>Spesifik bir Song’u getirme, güncelleme ve silme işlemlerine bakalım.</p><p>Daha iyi anlaşılması için yeniden yorum satırları içerisinde açıklamalar bulunuyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dXC3AdsYsn--hQx-aSG0xQ.png" /></figure><p>Yazdığımız CRUD fonksiyonlarını daha önce yaptığımız gibi SongsController içerisindeki boot fonksiyonunda register edelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ufe7pB2mXDbE0Q0zwOjHBQ.png" /></figure><p>Artık tüm CRUD fonksiyonlarını kullanabilir durumdayız. Rested uygulaması ile her birini deniyorum. <em>Hatırlatma: Bu aşamada gördüğümüz veriler memory içerisinde saklandığı için uygulamayı her run ettiğimizde veriler sıfırlanacak. Bir sonraki yazıda MySQL yapılandırmasını anlatıp API uygulamasını tamamlayacağız.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H8zrpUZzgjf7oIYSzL1tHA.png" /></figure><p>Id’si 1 olan veriyi getirmek için get isteği attığımızda response body içerisinde sonucu görüyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j9rngWhnoZwjQOWXPy5Lkw.png" /></figure><p>Yine id’si 1 olan veriyi güncellemek istediğimizde, görmek istediğimiz yeni bilgileri parametre olarak ekliyoruz ve put isteği atıyoruz. Güncellenmiş veri response body içerisinde görünüyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YfcGq7q4Y8j_hcFqv50oLA.png" /></figure><p>Son olarak id’si 1 olan veriyi silmek istediğimizde, delete isteği atıyoruz. Kod içerisindeki yorum satırında bahsettiğimiz No Content uyarısı Response Headers içerisinde görülüyor.</p><p>Fazla uzun olmaması için bu bölümü iki parçaya ayırdım. Sonraki bölümde modeller arasındaki ilişkileri, Fluent querylerini ve MySQL ile bağlayıp çalıştırmayı anlatacağım.</p><p>Uygulamanın kodlarına github üzerinden erişmek isterseniz; <a href="https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial">https://github.com/mehmetkoca/PlaylistApp-Vapor3-Tutorial</a></p><p>İletişim için: <strong>mehmetkoca@outlook.com</strong></p><p>🍻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=809e7cf8485c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-2-api-olu%C5%9Fturma-part-1-2-809e7cf8485c">Server Side Swift: Vapor 3 — Bölüm 2: API Oluşturma Part 1/2</a> was originally published in <a href="https://medium.com/nsistanbul">NSIstanbul</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Server Side Swift: Vapor 3 — Bölüm 1: Başlangıç]]></title>
            <link>https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-1-ba%C5%9Flang%C4%B1%C3%A7-3f38ccfd3ab1?source=rss-c2f08b6241ed------2</link>
            <guid isPermaLink="false">https://medium.com/p/3f38ccfd3ab1</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[api-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[vapor]]></category>
            <dc:creator><![CDATA[Mehmet Koca]]></dc:creator>
            <pubDate>Tue, 27 Feb 2018 11:49:46 GMT</pubDate>
            <atom:updated>2019-01-03T11:19:05.901Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AnprRRx9EpqSEo72f23H5g.png" /></figure><p><a href="https://github.com/vapor/vapor">Vapor</a>, -şu an için- Github’da en çok star toplayan server side swift framework’ü. MacOS ve Ubuntu üzerinde çalışabiliyor. Henüz beta aşamasında ve 2018 Mart ortasında release olması bekleniyor. Başlangıç aşamasında ve devam eden API örneğinde Vapor 3 ile <a href="https://swift.org/download/#snapshots">Swift 4.1</a> versiyonları kullanılacak.</p><p>İlk Vapor uygulamasını oluşturmak için gerekli araçlar:</p><ul><li>Vapor Toolbox</li><li>Swift 4.1</li><li>Xcode 9</li></ul><p>Vapor Toolbox kurulumunu <a href="https://brew.sh">Homebrew</a> ile yapılacak. Homebrew bilgisayarınızda yüklü değilse aşağıdaki kod parçacığını Terminal’de çalıştırarak yükleyebilirsiniz.</p><pre>/usr/bin/ruby -e &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&quot;</pre><p>Daha sonra Vapor Toolbox kurulumu için Terminal ekranında</p><pre>brew install vapor/tap/vapor</pre><p>komutu ile vapor toolbox kurulumunu yapıyoruz. Son versiyona ulaşmak için</p><pre>brew upgrade vapor/tap/vapor</pre><p>komutu ile kontrol edebilirsiniz.</p><p>Yeni proje oluşturmak için istediğiniz path’e terminal üzerinden erişip aşağıdaki kodu kullanmanız gerekir. HelloVapor adında bir proje oluşturuyorum.</p><pre>vapor new HelloVapor --branch=beta</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fMfqT-JP08XaXRQlmlXZ-g.png" /></figure><p>İşlem başarıyla tamamlandığında ekran görüntüsündeki Vapor’un karşılama mesajını göreceksiniz. Vapor <a href="https://swift.org/download/#snapshots">Swift 4.1</a> ile kullanıldığı için Xcode üzerinde 4.1 ile çalışmanız gerekiyor. (Xcode &gt; Toolchains &gt; Swift 4.1 Snapshot)</p><p>Proje oluşturma aşamasını geçtikten sonra, Xcode ile projeyi açalım.</p><pre>vapor xcode -y</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*M1Wg4N-sG1WFO6hOACQc-w.png" /></figure><p>Projeyi açtıktan sonra Vapor’un dosya sistemini görüyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y55M4rBn2OyDA9k1G8_iJA.png" /></figure><p>Projeyi başarılı bir şekilde çalıştırmak veya build etmek için Run &gt; My Mac şeklinde seçili olması gerekli.</p><p>Run ettikten sonra konsolda, <strong>Server starting on </strong><a href="http://localhost:8080"><strong>http://localhost:8080</strong></a><strong> </strong>mesajını görüyoruz.</p><p>Tarayıcıdan <a href="http://localhost:8080/hello">http://localhost:8080/hello</a> adresine girildiğinde default gelen Hello World! görünür. Bu routing işlemi routes.swift içerisinde yapılmış. Başlangıç için routes.swift içerisinde iki örnek oluşturacağım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/746/1*ayDMNQL6XMmgr3hK3iXgGQ.png" /></figure><p>Bu kod http://localhost:8080/hello/mehmet üzerinden erişmemizi sağlayacak. Tarayıcıdan girildiğinde Hello Mehmet! görünecek.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/702/1*ZQXJpAIrMGrtxGcq40tKTQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qpRcNqKM632MYKoU5iix3w.png" /></figure><p>Son örnek parametre alarak geriye String bir mesaj dönmeyi sağlayan router işlemi. <a href="http:///localhost:8080/user/YourFavoriteUserName">http:///localhost:8080/user/YourFavoriteUserName</a> adresinde istediğiniz kullanıcı adı ile denediğinizde <em>User YourFavoriteUserName</em> mesajı ile karşılacaksınız.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/758/1*MJQSquANxocC4ss5gGUEMw.png" /></figure><p>🔜</p><p>İletişim için; mehmetkoca@outlook.com</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3f38ccfd3ab1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/nsistanbul/server-side-swift-vapor-3-b%C3%B6l%C3%BCm-1-ba%C5%9Flang%C4%B1%C3%A7-3f38ccfd3ab1">Server Side Swift: Vapor 3 — Bölüm 1: Başlangıç</a> was originally published in <a href="https://medium.com/nsistanbul">NSIstanbul</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>