Kategori arşivi: Yazılım & İnternet

Yazılımla ilgili bilgiler falanlar filanlar

Mysql ile iki konum arasındaki uzaklığı ölçmek

Mysql 5.7 ile gelen native bir method ile, verilen 2 konum (latitude, longitude noktası) arasındaki uzaklığı metre cinsinden ölçebilirsiniz. Tanıştırayım: ST_Distance_Sphere

Örneğin, üyelerinizin 41.0049823,28.7319855 konumuna uzaklığını ölçmek istiyorsunuz. Hızlıca bir sorgu yazalım:

<?php
$latitude = 41.0049823;
$longitude = 28.7319855;
$sql =  "SELECT users.id, users.username, ST_Distance_Sphere(point(users.longitude, users.latitude),point({$longitude}, {$latitude})) as distance FROM users"

Sorgu çıktısına, verilen konumdan uzaklığı metre olarak eklenecektir. Dikkat etmeniz gereken, longitude-latitude ikilisi olarak sorgu yapılıyor.

Verilen noktaya 100 metre çapındaki uzaklıkta olan kullanıcıları da listeleyebilirsiniz, neden olmasın?

<?php
$latitude = 41.0049823;
$longitude = 28.7319855;
$sql = "SELECT users.id, users.username, ST_Distance_Sphere(point(users.longitude, users.latitude),point({$longitude}, {$latitude})) as distance FROM users WHERE distance < 100"

Bu methodu bilmeden önce sinüsler, kosinüler, tanjantlar filan havada uçuşuyordu. Hem yavaş çalışıyordu, hem de doğru sonuç vermiyordu. Bu methodu öğrenince dünyam aydınlandı. Teşekkürler ST_Distance_Sphere

Bağlantı

Kısa bir süre önce Symfony ekibi, composer ile kullandığımız PHP paketlerine teşekkür edebileceğimiz bir kütüphane geliştirdi. https://github.com/symfony/thanks adresinden ulaşabileceğiniz kütüphaneyi bağımlılıklarınız arasına ekledikten sonra, composer thanks diyerek composer.json dosyanızda dahil ettiğiniz tüm paketleri Github üzerinde beğenmiş oluyorsunuz. Paketinin beğenilmesi de bir geliştirici için oldukça iyi bir teşekkür olsa gerek. Daha iyisi için: teşekkür amaçlı bir e-posta gönderin veya bağış yapın.

Yazılım alanında ilerlemek isteyen öğrencilere tavsiyeler

  • Not alma alışkanlığı edinin
    Yaptıklarınızla, öğrendiklerinizle ilgili küçük/büyük notlar almak çok işinize yarayacaktır. Aynı şey diğer dersleriniz için de geçerli. Not almak için geleneksel yöntemleri tercih edebilirsiniz.
  • Öğrendiklerinizi öğretin
    Bildiğiniz şeyleri çevrenizdekilere öğretin. Öğrettiğiniz şeyleri çok basit şeyler diye düşünmeyin. Arkadaşlarınızı sınavlara çalıştırın. Öğreterek daha fazla öğrenirsiniz.
  • Pair Programming Yapın!
    Pair programming, tek bir bilgisayarda iki kişinin kod yazmasıdır. Bir kişi yazarken diğeri izler ve yorumlarıyla katkı yapar. Zaman zaman kod yazıcı ve yorumcu yer değiştirir. Bir dil öğrenirken de yapabilirsiniz, bir soru çözerken, bir proje geliştirirken de. 2 kişi çok daha hızlı ilerleyeceksiniz. Sonuçta 2 işlemci kullanıyorsunuz :)
  • Matematiksel soruları çözmeye çalışın
    Bilgisayarın temeli matematiktir. Matematik, yazılım öğrenmek için bir ön koşul değil ama matematik bilerek yazılım daha iyi öğrenilebilir. Programlama derslerinde sürekli matematik soruları çözdük ve “yav bunlar ne işe yarıyor” diyordum ama daha sonra o derslerin bana temel kazandırdığını ve öğrenme hızımı arttırdığını farkettim.
  • WordPress gibi hazır sistemleri kurun, kullanın
    Bu tarz (WordPress, Joomla, Jekyll, OsCommerce, Forum yazılımları vs) kompleks ve büyük yapıları görmek, kullanmak, öğrenmek ufkunuzu genişletecektir. Kullanmanın yanı sıra, kurulum işlemini de yapın. Cpanel, Plesk gibi hosting yönetim panelleri ile haşır neşir olun. Firmalardan, insanlardan size hosting sponsoru olmasını isteyin. (Düzgün bir Türkçe ile talep edin)
  • Çeşitli programlama dilleri hakkında temel bilgi sahibi olun
    Okulunuzda gösterilen diller ile sınırlı kalmayın. (Hele hele bu diller windows tabanlıysa) Python, Ruby, Go vd. dilleri bilgisayarınıza kurun. Çok zor değil, hepsinin sitesinde 3-5 adımda nasıl kurulacağına dair dökümanlar mevcut. Dilleri kurun, demo uygulamalarını çalıştırın. Bazı diller seçerek kendinizi o dilde geliştirin. Tamamen öğrenmek ve her şeyi yapmak zorunda değilsiniz. Önemli olan belli başlı şeyleri öğrenmek ve yine yeniden ufkunuzun genişlemesi.
  • Linux kullanın
    Dual boot olur, virtualbox olur, hiç farketmez. Bir kaç defa linux kurulumu yapın. Farklı farklı Linux dağıtımlarını kurun. Ubuntu ile başlayabilirsiniz, kolay kuruluyor.
  • Github hesabı açın
    Sektörde Github hesabı olmayana iş vermiyorlar. (Gerçi veren çok yer var. Ama siz yine de Github kullanın). Github hesabınızda yazdığınız kodları paylaşın. Küçük/büyük, eksik/yanlış düşünmeyin, sadece paylaşın. İnsanların kodlarını okumaya gayret edin. Başkalarının kodlarını bilgisayarınıza indirip kurmaya çalışın. Hata bulursanız bir issue açın. Hatta kodda düzenleme yapıp pull request (düzenleme isteği) açarsanız tadından yenmez. Github’ı ne kadar aktif kullanırsanız o kadar iyi. Aynı zamanda aynı işi yapan Gitlab, Bitbucket gibi sitelere de üye olun ve bu 3 siteyi özümseyin.
  • Teknik makale okuyabilecek kadar ingilizce öğrenin
    Kimse sizden süper ingilizce konuşmanızı istemiyor. İlk etapta önemli olan teknik makaleleri göz ucuyla da olsa takip edebilecek kadar ingilizce bilmek. Bunun için kurslara gitmeye gerek yok. Basit telefon uygulamaları var. Duolingo mesela. Konuşma pratikleri yapabileceğiniz ücretli Engoo var. Sahaflarda ingilizce hikaye kitapları var seviye seviye. Onları okuyun. Teknik makaleleri bol bol okuyun, uygulayın. İlla translate kullanmanıza gerek yok, bazı çeviriler deneyimleyerek yapılabilir. Sadece kendinize güvenin ve bol bol okuma yapın.
  • Öğrenci kulüplerine dahil olun, çalışın
    Öğrenci kulüpleri, etkinliklere ve insanlara ulaşmak için, okulunuzda etkinlik düzenleyebilmek için önemli birer araçtır. Bilgisayar ile ilgili tüm kulüplere üye olun, aktif görev alın. (Bilgisayar ile ilgili olmayan diğer kulüplere de üye olun bence.) Etkinlik düzenlemek için arkadaşlarınızı zorlayın. İnternetten insanlara ulaşıp şehrinize konferans vermesi için davet edin.
  • Sektördeki insanları tanıyın, çevrenizi tanıyın
    Diğer bir deyişle, networking yapın. Sosyal medyadan insanlarla etkileşime geçin, şehrinizdeki yazılımcılarla aynı ortamda bulunmaya çalışın.
  • Bol bol soru sorun
    Bizim yazılım öğrendiğimiz dönemde ciddi bir paylaşım ve yardımlaşma ağı vardı. Hala da var ama paylaşım alanları farklılaştı ve çeşitlendi. Bizim dönemimizde forumlar vardı, kategori kategori ayrılmış. Soru sormak biraz daha kolaydı. Şimdi soru sormak için sosyal medyadan ilgili kişiyi bulmak lazım. Çok güzel işler yapan kişiler var ama bu kişileri bulmak zor olabiliyor. Bulduğunuzda da çekinmeden soru sorun. Facebook grupları da var. Ama sosyal medyanın ego arttırıcı gücüyle insanlar genelde tepeden bakabiliyorlar. Bu tarz tiplere aldırış etmeyin. Eğer bilmiyorsanız, sorunun iyisi kötüsü olmaz. Sadece soruları biraz kaliteli sormaya özen gösterin:  Doğru düzgün soru sormanın yolları

Aklıma geldikçe ekleyeceğim :)

Laravel’de Middleware kullanımı ve yanıt süresini loglama

Aslında sadece yanıt süresini loglamayı anlatıcaktım ama burada işimiz Middleware ile olacağı için onun da ne olduğunu anlatayım istedim. Middleware, kelime anlamıyla, “ara katman – orta katman” anlamına gelir. Kelime anlamıyla çok uyumlu bir programlama terimi. Bu sefer Laravel’in bir uydurması değil, zaten olan birşey. Bu yazımda “Laravel süper isimlendiriyor yawww” diye övmeyeceğim.

Laravel’de middleware, HTTP istekleri ile isteğin gerçekleşmesi arasında ya da http isteği gerçekleştikten sonra çalışacak şekilde durur. Şöyle ki, Laravel ile yazılmış site.com/hakkimizda sayfasını açmak istediğinizde, Laravel önce router dosyasına bakar, işler ve ilgili controller methodunu çalıştırır. Hah, işte tam bu noktada; router isteği işledikten sonra, controller’a yönlendirmeden önce -eğer tanımlandıysa- middleware sınıfımıza yönlendirir. Middleware çalışır, istenilen kontroller/güncellemeler yapılır, eğer middleware izin verirse controller’a yönlendirilir. (controller’a ne kadar acayip bi kelime ya)

Yani middleware, route ile controller arasında bir ARA KATMANdır. Ara katman’ı büyük yazdım çünkü, sadece Laravel’deki kullanımına bakarsak, controller&route arasındaki katman olduğunu zannedebiliriz. Oysa araya girme niyetindeki herşey bir middleware olabilir. Google Translate’teki tanımına bakalım:

“`software that acts as a bridge between an operating system or database and applications, especially on a network.“`

Yani diyor ki, “bir işletim sistemi/veritabanı ve uygulamalar arasında köprü görevi gören yazılımlardır.” Özellikle bir networkte diye belirtmiş. “Bir network”ü ben şu şekilde yorumluyorum: bir sistemde/yapıda. Dahili bir biçimde. Neyse çok detaya girip kafa karıştırmayayım, benim kafam karıştı bile. Yine de girmek isteyen olursa katkılarını eklerim.

Laravel’de Middleware

Middleware ile ilgili dökümantasyon şurada bulunuyor: https://laravel.com/docs/master/middleware Laravel 2 tip middleware oluşturmuş. Birincisi, aşina olduğumuz request-controller arası çalışan middleware. Diğeri de response verildikten sonra çalışan “terminable” middleware.

Aşina olduğumuz middleware için şu örneği verebiliriz: Girilen sayfaya, bir kullanıcının yetkisinin olup olmadığını kontrol eden middleware. Kodu ise şu şekildedir:

<?php

    public function handle($request, Closure $next)
    {
       //burada gerekli işlemleri yapıyoruz. örneğin üyenin yetkisi var mı yok mu kontrol edebiliriz.
       //ya da buna benzer şeyler. 

        return $next($request);
    }

$request değişkenimiz, IlluminateHttpRequest sınıfının ta kendisi. Yani bizim o anki isteğimiz ile ilgili herşeyi bilen sınıf. (Bence birisi bu sınıf üzerine bir yazı yazmalı.) O an hangi route çalışıyor, hangi parametreler almış, sessionda neler var, cookiede neler var vs vs gibi onlarca sorunun cevabı bu sınıf içerisinde. Bu bilgiler ışığında istediğiniz kontrolü yapabilirsiniz. Tabi middleware sadece “kontrol etmek” için kullanılmıyor. Aynı zamanda sisteme yeni parçalar da dahil edebilirsiniz. Herşey sizin elinizde.

Terminable Middleware

Bu middleware sınıfı, HTTP sonucu, yani Response, tarayıcıya (istemciye) gönderildikten sonra çalışır. Bitiş middlewarelerinde handle methodundan farklı olarak bir de terminate methodu çalışır. Ve bu method $request sınıfına sahip olmakla birlikte, bir de $response sınıfına sahiptir. Response sınıfı sayesinde, istemciye ne sonuç gönderildiğini biliriz ve buna göre istediğimiz işlemi yaparız.

<?php

    public function terminate($request, $response)
    {
        // burada bişeyler yapabiliriz.
        // artık response tarayıcıya gönderildi. 
        // örneğin, responsu kontrol ederiz. diyelim ki 422 sonuç kodu dönüyor.
        // o zaman bunu loglatalım, gibi fantazi işler yapılabilir. 
    }

Laravel’de derleme süresini öğrenme

Laravel’deki  public/index.php dosyasına baktığımızda, LARAVEL_START adında bir sabit değişken tanımlandığını görürüz. Bu, Laravel’e ilk istek geldiği anda tanımlanır. Yani ilk çalışan kodumuzdur. Şimdi bir de yapmamız gereken, en son çalışma anında süreyi tespit etmek ve aradaki farkı loglara göndermek.

Bunun için standart bir middleware oluşturalım. php artisan make:middleware ResponseTimeMiddleware güzel bir başlangıç olacaktır. Daha sonra bu middleware’i AppHttpKernel dosyamızdaki $middleware dizisi içerisine ekleyelim. Böylece tüm requestlerde bu eklediğimiz middleware çalışmış olacak. Yeni oluşturduğumuz middleware’e aşağıdaki terminate fonksiyonunu ekleyelim:

<?php

    ....

    public function terminate(Request $request, Response $response)
    {
        \Log::debug($request->getPathInfo().' =>  '.(microtime(true) - LARAVEL_START));
    }

Böylece uygulama başlangıcından itibarek geçen süreyi loglarımıza yazdırmış olduk. Response süresini loglara yazdırıp debug yapmak çok etkili bir yöntem gibi gözükmese de bazen çok hızlı biçimde sorunlu sayfaları bulmanıza yardımcı olabiliyor. Ama ben genelde production ortamında, daha detaylı bilgi veren NewRelic hizmetini kullanıyorum. Hem sayfaların ortalama response sürelerini kolayca öğrenebiliyorum hem de veritabanı sorgularını detaylıca inceleyebiliyorum. Hangi query ne kadar sürmüş vs diye. Tavsiye ederim.

Trait Nedir?

Bir önceki yazımda, yazdığım kodda sürekli tekrar eden kod parçasını Trait içine alıp, güzelleştirdiğimi iddia etmiştim. Peki kodu güzelleştirdiğimi iddia ettiğim bu trait tam olarak nedir?

Kelime anlamına baktığımızda, trait; bir kişinin karakteristik özelliği anlamına gelir. Birebir çevirdiğimizde ise özellik, kişisel özellik diyebiliriz. Programlama özelinde baktığımızda ise, bir sınıfa özellik/yetenek yüklemek için kullanılan kod diyebiliriz.

PHP’de bir sınıf, yalnızca bir üst sınıfa sahip olabilir. Daha anlaşılır bir deyişle, “bir sınıf yalnızca tek bir sınıftan türetilebilir(extend edilebilir)”. Sınıftan türetme işlemini, genellikle türetilen sınıfın özelliklerini(fonksiyonların/methodlarını/değişkenlerini) kullanabilmek için yaparız.

<?php

class Admin extends User {}

class Admin extends User, Human {} //böyle bir kullanım yok

Fakat zaman zaman yazdığımız sınıfın, birden fazla sınıfın özelliklerine sahip olması gerektiğini görürüz. Yukarıdaki örnekte gördüğümüz üzre, Admin sınıfımız User sınıfından türetilmiş. User’ın tüm özelliklerini kullanabileceğiz demektir. Fakat aynı zamanda Human sınıfının da özelliklerine sahip olmasını istiyoruz. İkinci satırdaki kullanım mümkün değil.

PHP 5.4 ile hayatımıza dahil olan traitler, bu duruma bir nebze çözüm olabilmektedir. Tabi tek amacı buna çözüm olmak değildir. Aynı zamanda kod tekrarının önüne geçmek konusunda bize oldukça yardımcı olur ki, bir önceki yazımda Trait kullanarak tam olarak bunu hedeflemiştim.

Traitlere bir bakış atalım:

<?php

trait ValidatesRequests {
   
    public function validate($data)
    {
        //parametre olarak gönderilen veriyi burada validate edelim.
    }

}

Bir trait, abstract class gibi işlem görür. Yani bir traitten yeni bir obje oluşturamazsınız. new ValidatesRequests() işe yaramaz. Traitleri bir sınıfı içerisinde ise, Use keywordu ile kullanırız.

<?php 

class BilmemneController {
 
    use ValidatesRequests;

    public function deneme()
    {
         $data = ['test']
         $this->validate($data);
    }

}

Yukarıdaki örnekte açıkça görüleceği gibi, ValidatesRequests traitini use ile dahil ettik. Ve deneme fonksiyonumuz içinde, traitte tanımladığımız validate methodunu kullanabilir duruma geldik.

Çalışma mantığını ise kopyala yapıştır gibi düşünebiliriz. Traiti sınıfa dahil ettiğimiz anda, içerisindeki methodları sanki dahil ettiğimiz sınıfa kopyalayıp yapıştırıyormuş gibi düşünün. Örneğin bu validate methodunu 5 controller dosyasında kullanacağımızı varsayalım.

Her bir dosyaya aynı methodu kopyalamak yerine, bu 5 sınıfa traiti dahil ediyoruz. Böylece kod tekrarının önüne geçiyoruz. Ve tabii ki yazdığımız kodun bakımı/tekrar çok daha kolay oluyor.

Traitlerin isimlendirilmesi

Genelde bu tarz bir paragraf göremezsiniz fakat ben oldukça önemsiyorum. Trait kullanımı Laravel’de yoğun ve bence Laravel isimlendirme konusunda oldukça başarılı. Traitlerin karakteristik/kişisel özellik anlamında geldiğini söylemiştik. Trait, kullanılan sınıfa yeni özellikler katar. Laravel’in Controller örneğine bakalım. 2 trait kullanılıyor:
use AuthorizesRequests, ValidatesRequests;
Bir controllera bu 2 traiti dahil ettiğimizde insan dilinde(ama türkçe değil) şu cümleleri kurabiliyoruz:

“Bu controller, requestleri(istekleri) authorize eder(yetkilerini onaylar).”
“Bu controller, requestleri(isteklerin) validate eder(geçerliliğini kontrol eder).”

Bu iki traiti detaylıca incelediğimizde birisinde authorization ile ilgili methodların, diğerinde ise validation ile ilgili methodların bulunduğunu görürsünüz. Yazılımda en zor şeylerden birisi isimlendirmedir, malumunuz. Ne kadar insan diline yakın isimler verebilirseniz, o kadar başarılı olursunuz (bence).

Sevgiyle kalın.

<?php
trait Love()
{
    public function love(Human $human) {

    }
}

trait Hate()
{
    public function hate(Human $human) {

    }
}

class Human()
{
    use Love;
}

 

Laravel’de UUID kullanımı

Buraya kadar geldiğinize göre muhtemelen ne olduğunu biliyorsunuzdur ama yine de Laravel’de UUID’nin nasıl kullanıldığını anlatmaya başlamadan önce kısaca bir UUID tanımını yapalım ve ne olduğunu anlatmaya çalışalım.

UUID, “Universally unique identifier” nin kısaltılmışıdır. Kabaca çevirirsek, evrensel(?) benzersiz tanımlayıcı diyebiliriz. Normalde veritabanında satırları tanımlayıcı olarak integer kullanırız. UUID ise, 36 karakterlik, sayılar ve harflerden oluşan, bir settir. Ve en önemli özelliği, yüksek derecede benzersiz olmasıdır. (Bilgisayarda rastgele üretilen hiçbir şey aslında tam olarak rastgele değildir. Rastgeleliği arttırabiliriz. Değişik bi konu.)

Örnek olarak şöyle bir kaç tane gösterebilirim:

UUID genellikle büyük projelerde işe yarayabiliyor. Biliyorsunuz, veritabanında integer alanının maximum değeri var. Mysql’deki değeleri şuradan görebilirsiniz: https://dev.mysql.com/doc/refman/5.7/en/integer-types.html

Burada minimum-maximum değerlere bir paragraf açıyorum. Veritabanında id alanı, Primary Key olarak tanımlanır. PrimaryKey alanı doğası gereği unsigned olarak tanımlanır. Bu yüzden ilgilendiğiniz alan unsigned olmalı. Peki unsigned değer ne demek? Negatif olmayan sayılar demek. Linkteki tabloya baktığımızda, TinyInt türü için signed [-127, 127] aralığındayken, unsigned [0, 255] aralığında değer alabiliyor.

Primary key, varsayılan olarak INT, unsigned tanımlanır. Bu da demektir ki, o tabloya maksimum 4294967295 kayıt eklenebilir. Sanırsam, 4 milyar 294 milyon 967 bin 295 kayıt. Her ne kadar çok büyük bir sayı olsa da, sonsuz değil. Eğer uuid olarak tanımlarsanız, sonsuz kayıt ekleyebilirsiniz. (Acaba öyle mi? Keşke birisi bunun doğrulamasını yapsa) Maksimum kaç kayıt eklenebileceği ile ilgili yanıt: https://twitter.com/hkanaktas/status/906891710155849730

Bunun haricinde, çok olası değil ama, bir tablonuz dağıtık biçimde çalışıyorsa, primary key alanınızın çakışmasını önler. Farazi bir örnek verelim. Diyelim ki kullanıcının gezdiği sayfaları kayıt altına alıyorsunuz. Öyle ki, çok yoğun bir sistem ve kayıtları %50 A sunucusundaki logs tablosuna, %50 B sunucusundaki logs tablosuna kaydediyorsunuz. Günün sonunda verileri C sunucusunda birleştirmek istediğinizde, id alanı çakışacaktır. Bunun için idleri yeniden vermeniz gerekmektedir. Fakat uuid kullanırsanız, herhangi bir yenileme yapmadan doğrudan verileri birleştirebilirsiniz.

Son olarak şunu söyleyeyim, tahmin edilmesi oldukça zordur. Örneğin kullanıcılar tablomuzda int kullansaydık, üye kayıtları 1,2,3,4,5 diye düzenli olarak gidecekti. Ve emin olun saldırganlar ilk olarak url’deki idleri değiştirerek erişim sağlamaya çalışır. Gerekli kontrolleri aldıysanız sıkıntı olmaz. Fakat uuid ile bu sıkıntı daha da az yaşanır. Çünkü bir sonraki kullanıcının id’si tahmin edilemez hale gelir. Siz yine de arka tarafta gerekli kontrolleri yapmayı unutmayın.

Gelelim Laravel Kulanımına

UUID’leri üretmek için ek paket kullanmamız gerekiyor. Ben ramsey/uuid paketini kullanıyorum.

$ composer require ramsey/uuid

Bu paket sayesinde artık UUID üretebiliriz. README dosyasında kullanımı var, ama kısaca ben de buradan tekrar edeyim:

<?php
 // Generate a version 1 (time-based) UUID object
    $uuid1 = Uuid::uuid1();
    echo $uuid1->toString() . "n"; // i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd

    // Generate a version 3 (name-based and hashed with MD5) UUID object
    $uuid3 = Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net');
    echo $uuid3->toString() . "n"; // i.e. 11a38b9a-b3da-360f-9353-a5a725514269

    // Generate a version 4 (random) UUID object
    $uuid4 = Uuid::uuid4();
    echo $uuid4->toString() . "n"; // i.e. 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a

    // Generate a version 5 (name-based and hashed with SHA1) UUID object
    $uuid5 = Uuid::uuid5(Uuid::NAMESPACE_DNS, 'php.net');
    echo $uuid5->toString() . "n"; // i.e. c4a760a8-dbcf-5254-a0d9-6a4474bd1b62

Bu pakette toplam 4 çeşit üretme yöntemi var. Hangisini kullanacağınız konusunda tercih size kalmış. Ben farklarını bilmiyorum, araştırmadım.

Göç yolları, göründü bize

Paketi yükledikten sonra, ilk değişikliğimiz migration yazımında karşımıza çıkıyor.

Normalde bir migration oluşturduğunuzda şu şekilde oluyor:

$table->increments('id');

Bu fonksiyonun detayına baktığımızda, unsignedInteger tipinde oluşturduğunu göreceksiniz. Bunun yerine şunu yazmamız daha manidar:

$table->uuid('id')->primary();

ID alanımızın uuid türünde olduğunu, ve bu alanın tablomuzun birincil alanı(reyizi) olduğunu söyleyerek tablomuu oluşturuyoruz. Bu da aslında özel bir kolon türü değil, 36 karakterlik char alanı oluşturuyor tablomuzda.

Model dosyalarında değişiklik

İlk önce modelin primary key’in otomatik artma özelliğini kapatalım. Eloquent’te primary key, varsayılan olarak int, auto increment olarak kabul edilir. Bunu değiştirelim.

<?php

class Bilmemne extends \Illuminate\Database\Eloquent\Model {
 
    public $incrementing = false;

}

Otomatik arttırmayı kapattık ama, şimdi de bir modeli kaydetmek istediğimizde, otomatik olarak sayı yazmaya çalışacak eloquent. Bunun için Eloquent event’lerinden yararlanıyoruz:

<?php

class Bilmemne extends \Illuminate\Database\Eloquent\Model {
 
    public $incrementing = false;

    protected static function boot()
    {
        parent::boot();
 
        static::creating(function ($model) {
            $model->{$model->getKeyName()} = \Ramsey\Uuid\Uuid::uuid1()->toString();
        });
    }

}

Peki bu kod ne yapıyor? $model->save() komutunu çalıştırdığınızda, model verileri, veritabanına kaydedilmek üzere hazırlanıyor. Bu kod sayesinde, modelimiz veritabanına kaydedilmeden önce ‘id’ alanının değerini uuid ile değiştiriyoruz.

Hepsi bu! Artık id alanımız integer yerine uuid olarak kaydediliyor. Fakat burada göze güzel görünmeyen birşey var. Bu kodu tüm modellere tek tek kopyalayıp yapıştıracağız. Bunun önüne geçmek için yapabileceğimiz 2 şey var. Birincisi, extend edilen sınıfı değiştirmek. İkincisi ise Trait kullanmak.

1. Yöntem: Extend edilen sınıfı değiştirmek

Öncelikle yeni bir model sınıfı üretelim.

<?php

class MyModel extends \Illuminate\Database\Eloquent\Model
{
    public $incrementing = false;

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->{$model->getKeyName()} = \Ramsey\Uuid\Uuid::uuid1()->toString();
        });
    }
}

Daha sonra kendi sınıfımızın ayarlarıyla oynayalım:

<?php 

class Bilmemne extends MyModel { 

}

Bilmemne modelimiz artık integer yerine uuid üretiyor!

2. Yöntem: Trait kullanmak

Bildiğiniz gibi bir sınıf birden fazla sınıftan türetilemiyor(extend edilemiyor). Siz birden fazla sınıfın özelliğini kullanmak isterseniz ya hepsini birbirinden extend edeceksiniz -ki etmeyin- ya da trait kullanarak istediğiniz methodları kullanacaksanız. Laravel’e baktığımızda trait kullanımının yoğun olduğunu görürüz. Traitler bize kodların yeniden kullanımı konusunda yardımcı olur. Tekrar yazımların önüne geçer. Kodumuzu parçalara bölebilmemizi sağlar ve kodun kolay takibini sağlar. Örnek olarak Laravel’in model sınıfının neler kullandığına bakalım:

<?php

abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
{
    use ConcernsHasAttributes,
        ConcernsHasEvents,
        ConcernsHasGlobalScopes,
        ConcernsHasRelationships,
        ConcernsHasTimestamps,
        ConcernsHidesAttributes,
        ConcernsGuardsAttributes;
}

Model sınıfı yorumlar da dahil 1460 satır. Traitlerin içindeki methodları da bu sınıfa dahil etseydik kim bilir kaç satır olacaktı. Kodun birbiriyle ilgili bölümlerini alıp trait içerisine koyup, traiti de model içerisinde sadece use ile çağırmak oldukça güzel bir fikir. Daha övülecek çok yanı vardır da, hem şimdi aklıma gelmiyor(hepsini bilmiyor da olabilirim) hem de artık kendi trait kodumuza geçelim.

<?php

trait UuidsTrait
{
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->{$model->getKeyName()} = \Ramsey\Uuid\Uuid::uuid1()->toString();
        });
    }
}

Tek yapmamız gereken, bunu modelimiz içerisinde kullanmak:

<?php

class Bilmemne extends \Illuminate\Eloquent\Database\Model { 
    
    use UuidsTrait;
}

Bu da tam olarak istediğimiz gibi sonuç verecek ve integer yerine uuid kullanmamızı sağlayacak.

Trait olarak kullanmak ve extend etmek arasında belli farklar var fakat onları başka bir yazı konusu yapabiliriz. Şimdilik ben size bu iş için trait kullanmanızı öneririm.

Esenlikle kalın.

 

Laravel için örnek gitlab-ci dosyası

Uzun süre Gitlab’deki projelerimde unit testleri otomatik çalıştırmayı beceremedim. Gitlab’de bununla ilgili bir örnek bulamadım. Çeşitli forumlarda örnek konfigürasyonlar paylaşılmış ama google’da ilk sırada çıkan konfigürasyonda testin tamamlanması 10 dakikayı buluyordu. (https://laracasts.com/discuss/channels/testing/laravel-ci-testing-with-gitlab)

En sonunda daha derli toplu güzel bir repo buldum. https://laracasts.com/discuss/channels/testing/laravel-ci-testing-with-gitlab/replies/307623

Laravel’e özel bir docker image kullanıyor. Ve bende testin tamamlanması 2 dakika filan sürüyor.

Gitlab ve Laravel için CI(Pipeline) konfigürasyonu arayanlara sevgilerimle. Umarım yardımcı olur.

Benim konfigürasyonum:

before_script:
  - mv /root/composer.phar .
  - php -v
  - git --version
  - ls -lah
  - php composer.phar self-update
  - php composer.phar install --no-interaction --prefer-dist --optimize-autoloader
  - cp .env.gitlab .env
  - php artisan key:generate
  - php artisan config:cache
  - php artisan migrate --force
  - php artisan db:seed

variables:
  MYSQL_DATABASE: laravel
  MYSQL_ROOT_PASSWORD: secret

phpunit:php-laravel-env:mysql5.7:
  image: woohuiren/php-laravel-env:latest
  services:
    - mysql:5.7
  script:
    - php vendor/bin/phpunit --coverage-text --colors=never

 

Laravel 5.3 change mail configuration dynamically

If you are developing CMS software or a SaaS product, your customers needs to set their mail sending credentials for sending mails from their system. By default, you can set mail configuration to .env file.

But if your customer don’t have access to .env file and command line to execute artisan config:clear command, they need to change credentials from their panel. Here is an example:

I store these values at database. So, i need to change mail config before sending email. But, Laravel’s

config()->set('mail',$values);

doesn’t work. Because, SwiftMailer instance registers when compiling Service Providers with default parameters which are coming from .env file. So, there is two option for override this instance.

1- Create new Swift_Mailer instance and set it before sending email.

<?php
$swiftMailer = new Swift_Mailer();
//do your configuration with swift mailer
Mail::setSwiftMailer($swiftMailer);
Mail::to('mail')
->send();

But, i do not use this metod. I don’t want to fight with SwiftMailer’s configuration. And also, it’s bad architect. It stand againts Dependency Injection.

2- Override MailService Provider

It has 3 step to set-up.

a) Create AppManagerMailTransportManager. (You can use your namespace.) In this file, we will get mail configuration from database (or wherever you save) and will set to laravel’s config.

<?php
/**
 * @author Guven Atbakan
 */

namespace AppManager;

use AppModulesSettingServiceSettingService;
use IlluminateMailTransportManager;

class MailTransportManager extends TransportManager
{
    public function __construct(IlluminateFoundationApplication $app)
    {
        $settings = []; //get your settings from somewhere

        /
            $this->setDefaultDriver('smtp');
            $this->app['config']['mail'] = [
                'driver' => 'smtp',
                'host' => $settings['mailHost'] ?? 'smtp.yandex.net',
                'port' => $settings['mailPort'] ?? 465,
                'from' => [
                    'address' => $settings['mailFromAddress'] ?? '',
                    'name' => $settings['mailFromName'] ?? '',
                ],
                'encryption' => 'tls',
                'username' => $settings['mailUsername'] ?? '-',
                'password' => $settings['mailPassword'] ?? '-',
                'sendmail' => $settings['mailSendmailPath'] ?? '/usr/sbin/sendmail -bs',
                'pretend' => false,
            ];

            config()->set('mail', $this->app['config']['mail']);
            //i'm not sure if its necessary.
    }
}

b) Create AppProvidersCustomMailServiceProvider. In this file, we will tell  to swift mailer, use our MailTransportManager.

<?php

namespace AppProviders;

use AppManagerMailTransportManager;
use IlluminateMailMailServiceProvider;

class CustomMailServiceProvider extends MailServiceProvider
{
    protected function registerSwiftTransport()
    {
        $this->app['swift.transport'] = $this->app->share(function ($app) {
            return new MailTransportManager($app);
        });
    }
}

 

c) By using config/app.php, we will disable default MailServiceProvider and register our CustomMailServiceProvider. It’s easy.

<?php
//IlluminateMailMailServiceProvider::class,
AppProvidersCustomMailServiceProvider::class,

PDF dosyaları PHP ile resim dosyasına çevirme

Imagick kütüphanesi, pdf dosyaları convert etmemize yardımcı oluyor.

<?php

$imagick = new Imagick('file.pdf[0]');
$imagick->setImageFormat('jpg');
file_put_contents($pathToImage, $imagick);

Imagick kullanmak için yapmanız gereken şey imagick paketini kurmanız. (apt: php5-imagick ya da php7.0-imagick)

Bu işlem için daha iyi bir kullanım deneyimi sunan bir paket te mevcut. Arka planda imagick kullanıyor.

https://github.com/spatie/pdf-to-image

Dönüştürme işlemi ise oldukça basit. jpg, jpeg, png formatlarında kayıt yapabiliyor.

<?php

$pdf = new SpatiePdfToImagePdf($pathToPdf);
$pdf->saveImage($pathToWhereImageShouldBeStored);

Running Laravel4 with PHP7

I will not argue about Laravel’s shitty versioning system and dropping support for older versions. They are so excited, everyday adding a new feature to framework’s core. Yeah, thats really good thing but who cares fucking backward compability?

Anyway, if you are using Laravel4 and want to run it with PHP7, you have make some changes on framework’s core. So, you need to fork L4 and publish it as a new package OR (preferred) you need to use it as custom repository.

So, what do you need to change?

Here is a pull request, that contains full change for support PHP7: https://github.com/laravel/framework/pull/13338

changed Exception object references to Throwable because PHP7 uses Error instead of Exception. So, referencing as Throwable is a good idea.

So what i did? Here: https://github.com/shibby/laravel-framework/commit/1ab51571fde84b31d7328e9b9c86033d390187bf

Just deleted Exception references on functions. I’m using my repository for projects that runs with PHP7. So, you can use it if you want with your own responsibility. And you have to watch security/critical fixes on Laravel’s 4.2 branch.

If you want to use this repository, you need to make some changes on your composer.json file.

First, i added "php":">="7.0", to my require section.

And, second, i added my repository as custom repository above require section:

"repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/shibby/laravel-framework.git"
    }
  ],

But i think i need to delete other branches on my fork for make composer’s resolution faster. I’m waiting for your ideas. Maybe we can move as a group? At last, i will upgrade my 4.2 project to latest(or lts) version. I want to do it with less pain. It hurts now :(

Thanks!