SequelPro: MacOSX kullanıcıları için PHPMyAdmin alternatifi

MacOSX’de php geliştirme ortamı kurmak, diğer işletim sistemlerine göre çok daha kolay. MAMP ile neredeyse tek drag & drop ile apache, php, mysql üçlüsünü çalışır hale getirmek mümkün.

Eğer *AMP kullanan bir web geliştiricisi iseniz muhtemelen tüm veritabanı yönetiminizi phpmyadmin ile yapıyorsunuzdur. PHPMyAdmin kuşkusuz taşınabilir ve esnek yapısıyla istediğiniz gibi özelleştirebileceğiniz bir yönetimsel araç. Fakat bazı noktalarda bazen bir masaüstü aracının sunacağı özellikleri sunamayabiliyor.

Sequel Pro, adından paralı bir yazılım gibi bir çağrışım yapsa da ücretsiz bir yazılım. Basit ve minimalist bir arayüze sahip Sequel Pro’nun kullanımı oldukça kolay.

Okumaya devam et “SequelPro: MacOSX kullanıcıları için PHPMyAdmin alternatifi”

PHPStorm, PyCharm veya RubyMine kullanıcıları, projenizi veritabanı entegrasyonu ile geliştirin

PyCharm, PhpStorm, and RubyMine kullanıcıları, jetbrains son güncellemelerden biriyle saydığım IDE’lere gelişmiş veritabanı desteği ekledi. Daha önce de vardı fakat hiç veritabanı bağlantısını PHPStorm’da kullanmamıştım fakat bu videodan sonra denemeye karar verdim ve oldukça efektif buldum.

Java bağlayıcılarını yükledikten sonra birçok veritabanı motorunu projenize bağlayabiliyorsunuz. Projenize veritabanı bağlantınızı kurduktan sonra veritabanı yapısını gözden geçirebilir, yapıyla oynayabilirsiniz. Teknik olarak phpmyadmin yerine bu kısımları kullanabilirsiniz. Bu kısmı ilgimi çok çekmedi, fakat spesifik olarak SQL geliştirirken veritabanı konsolunu kullanabilir ve kod yazım zekasını kullanabilirsiniz. Buraya kadar IDE’den bağımsız bir veritabanı yönetim aracı gibi geldi.

Asıl işe yarayan kısmı ise, kodunuzdaki SQL’leri doğrudan çalıştırabilir veya php kodunuzda SQL yazarken kod yazım zekasını kullanabiliyorsunuz. Videoda örnek kullanımda görebilirsiniz.

Kaynak: http://blog.jetbrains.com/webide/2012/11/sql-support-and-database-tools/

PHP’de tarih karşılaştırma

Bir web uygulaması/sitesi geliştiriyorsanız verilerinizin eklenme, güncellenme tarihleri genelde uygulamanın işleyişinde büyük rol oynar.

Örnek bir senaryo olarak, bir günlük sitesi hazırladınız ve günlükte görünen yazılarınızın son güncellenme tarihlerine göre son güncellenen yazıları listelemek isteyebilirsiniz. Veya bir e-ticaret sitesinde ürünleri belirli günlerde yayına çıkarmak istiyorsunuz ama bütün ürünleri her gün tek tek ekleyememeceğinize göre her ürünün yayına çıkış tarihini ayarlamak isteyebilirsiniz. Bunun gibi bir çok örnek bulabilirsiniz verilerin tarihleri üzerinden işlem yapmak isteyeceğiniz.

Yani aslında tarihlerle çalışmak bu ısın her noktasında. Dolayısıyla tarih eşleştirmeleri yapmak veya iki tarih/zaman arasındaki farkı bulmak gibi birçok is yapıyor olacaksınız yukarıdaki veya benzer senaryoları kodlarken. Size bu dökümanda php ile tarih eşlestirmesi yapmayı göstereceğim.

Benzer şekilde tarih karşılaştırmasını mysql’de yapmak için yakında başka bir yazı yayınlayacağım.

Tarih karşılaştırması denince akla çok basit örnekler gelebilir, örneğin X tarihi Y’den önce mi sonra mi? gibi, bunu string karşılaştırması yaparak da yapabilirsiniz. MySQL’de sürekli gördüğünüz “Y-m-d H:i:s” formatı aslında tam olarak bu ihtiyacı karşılayabılır, Yani o tarih formatları string’e de çevrilse string karşılaştırmasında tarihsel sırayı doğru yansıtacaktır.

Ama tarih karşılaştırmaları her zaman böyle once/sonra karşılaştırması değil, 1 haftadan önce mi? veya son 1 aylık veriler… gibi daha karışık örneklere dönebilir. Böyle karışık tarih karşılaştırmaları eğer sihirli fonksiyonlar kullanılmazsa baş ağrısı olabilecek bir konu, çünkü tarihler arasındaki farklar sadece saat dakika saniye gibi matematiksel hesaplarla hesaplanması kısa kodlarla yapılacak bir şey değil. Tabi ki yapılabilir fakat tek satırda ya da tek fonksiyon ile bunu yapmak varken anlamsız. 1 ay öncesi demek her zaman son 30 gün demek değildir mesela. Veya Geçen hafta Pazartesi’yi hesaplamak kolay değildir.

Bu tarz karışık karşılaştırmalar için php’de her zaman kullandığım bir fonksiyon olan strtotime() fonksiyonunu tarih karşılaştırması yapmak için de kullanırım. Örnegin X tarihinin 3 günden önce olup olmadigini:

veya “3 days ago” stringini matematiksel tarih değeri yani timestamp’e çevirerek karşılastırabiliriz. Farkettiyseniz $X değişkenini de strtotime fonksiyonundan geçiriyorum çünkü o da string değeri olduğunu varsayıyorum. Strtotime fonksiyonunun güzel yanı, herhangi bir tarih formatını timestamp’e çevirebiliyor olması. Yani amerikan tarih formatı da yazsanız, bizim kullandığımız formatta da yazsanız php’nin bunu çeviriyor olması. Bundan daha değerli olarak gördüğüm, söylem olarak kullandığımız tarihleri de (2 gün önce, 1 saat sonra, geçen cumartesi, önümüzdeki pazar saat 2) gibi stringleri de doğru olarak timestamp’e çevirebiliyor olması. Bunu kullanarak istediğiniz tarih karşılaştırmasını yapabilirsiniz.

Mesela daha karışık bir örnek olarak:

Bu ufak kontrolle, bütün hafta yazdığınız yazıları bir sonraki hafta pazartesi öğlen 1’de herkese görünür hale getirir. Kontrol’de su anki tarihe göre bir önceki haftanın pazartesi saat öğlen 1’in zaman değeri ile yazıların tarihlerini kıyaslıyoruz. Örnek veriyorum Bugün salı ve siz bi yazı yazdınız, o tarih değeri o haftanın pazartesisinden küçük olmadığı için yukarıdaki kodda if’in içindeki ilk tarih bir sonraki pazartesiye kadar değişmeyecektir. Bir sonraki pazartesi saat 1’de o anın tarihine dönüşeceği için bu salı günü yazdığınız yazı görünür hale gelecektir.

MySQL’de optimizasyon analizi

MySQL’de Procedure Analyse fonksiyonu ile tablo yapınıza ait betimsel istatistikler ve alanlara ait veri türü önerisi elde edebilirsiniz. Bu sayede içi dolu olan bir tablonuzun yapısını optimize ederken kaydedilen veri hakkında fikir sahibi olabilirsiniz.

Procedure Analyse, çıktı olarak tablonuzdaki her alana ait minimum, maksimum, içindeki veri boyutlarının alt ve üst sınırlarını, ortalama standart sapma ve en önemlisi, o ana kadar kaydedilmiş verilerin profiline göre o alanın en ideal hangi türde olması gerektiğine dair öneri veriyor.

Sonuçta nümerik alanlarda ortalama, standart sapma, minimum maksimim değerleri düşünerek veri boyutunuzu saptayabilirsiniz. Aynı durum varchar alanlarda da geçerli. Çoğu zaman select sorguları gereksiz yere büyük açılmış alan türlerinden ve indeks oluşturulmamış basit alanlardan dolayı oldukça uzun sürelerde sonuç veriyor. Hatta bazen zaman aşımına uğruyor.

MySQL’de Procedure Analyse hakkında bilgi almak için
taze yazdığım şu dökümanı inceleyebilirsiniz :

MySQL’de Procedure Analyse ile optimizasyon analizi

MySQL’de Procedure Analyse ile optimizasyon analizi

MySQL’de büyük veri taşıyacak tablolar ürettiğinizde bazen indeksleri doğru seçemeyebiliyor, alan türlerini iyi belirleyemiyoruz. Gözden kaçan şeyler olabiliyor veya bilmediğimiz alan türleri ile çalışıyor olabiliriz.

Veri boyutu büyüdükçe sistemdeki sorgu süreleri büyüyebiliyor. Hatta bu optimizasyonu iyi yapmazsanız aslında 1 saniyeyi geçmeyecek sorgular için dakikalar harcayabilir, kodunuz zaman aşımına uğrayabilir (timeout).

Optimizasyon konusunda çeşitli teknikler var tabiki. Bu dökümanda basitçe tek sorgu ile mysql’in yapı analizi çıktısı almayı ve oradaki önerileri değerlendirmeyi anlatacağım.

Bir tablonun yapısını öğrenmek için

sql kodunu kullanarak tablo yapısını öğrenebiliriz. Çıktı olarak her alanın adını, türünü, null olup olmadığı, indeks türü gibi değerler döner. Kaç alanınız var ise o kadar satır çıktı alırsınız.

MySQL’deki Procedure Anlayse fonksiyonu ile bu alanların bazı betimsel istatistiklerini ve önerilen türünü öğrenebilirsiniz. Bunun için de

kodunu çalıştırmanız yeterlidir. Bu kod çıktı olarak kaç tane alanınız var ise o kadar kayıt dönecektir. Bu kayıtlar şu bilgilere sahip olur :

Burada dikkat edeceğiniz şey, alan boyutlarının alt ve üst değerleri. Yani mesela siz varchar(200) lük bir alan ürettiniz. Ve tablonuz verilerle doldu, bu analize bakınca o alan için Min_length 10 Max da 50 diyorsa sizin alan boyutunuzu 70-80 gibi bir boyuta düşürmeniz daha az bellek harcamasını sağlar. Yani 200 olarak düşündüğünüz alan uygulamada, yani gerçekte o boyuta ulaşmamış ve daha ufak kalmış.

Benzer konu nümerik alanlar için de geçerli. Yani sizin teorik/ideal olarak düşündüğünüz veri boyutu bazen büyük gelebilir. Bu noktada alan türü ve boyutunu değiştirerek select gibi sorguları daha hızlı hale getirebilirsiniz.

Index atama konusunda da bu geçerli, eğer select’lerde çok kullandığınız ve where kalıplarına sürekli soktuğunuz bir alanınızın standart sapması ufak ise (yani birbirinden çok farklı değerler almıyorsa – ama tekil ise) o alana bir indeks atayarak sorgu işletim zamanını oldukça kısaltabilirisiniz.

Burada bir güzel şey de, mesela sadece gruplama amacı ile bir alanı varchar(30) yapıp içine "anket", "forum", "dokuman" gibi 3 değer atıyorsunuz. Tabiki projeyi tasarlarken bunun farkında olmazsınız ve "Ya burada her türlü şeyi tanımlarım" diye düşünürken projeye bu üçü dışında başka şey gelmediğini farkettiğinizde bu analiz çıktısında zaten mysql size veri türünü ENUM("anket", "forum", "dokuman") olarak ayarlamanızı önerecektir.

Bu çıktıyı sadece optimizasyon değil, log tuttuğunuz bazı tablolardaki basit istatistiksel çıkarımlarla veri hakkında fikir edinmek için de kullanabilirsiniz. Zira ortalama, standart sapmaya veriyor olması o verinin dağılımı konusunda size oldukça fazla fikir verebilir.

PHP’de Pratikçe Sorgu Cümlesi Oluşturmak

Daha önce SQL injection ve MDB2 hakkında birşeyler yazmıştım.

Bu döküman birkaç konuda size yardımcı olacak, pratikleştirecek sorunlar :

  • Çok alan (4-5+) kullanırken sorgu cümlesi oluşturmak zor
  • Gözden kaçırıp alanları kontrol etmek bazen mümkün olmuyor.
  • Yukarıdaki 2 maddeyi yapmak için satırlarca duplicate kod yazmak gerekebiliyor

Kısaca 3-4 adımda kocaman bir sorgu cümlesini oluşturacağız. Genel olarak bu dökümandaki sorun insert ve update türü sorgularda çıkan kargaşayı kolaylaştıracaktır. Zira select sorguları hem çok veri içermiyor hem de özel cümleler olabiliyor.

Bu methodolojide doğal olarak bir otomatizasyon var. Bunun için verinin düzenli olması gerekiyor. Bu noktada genelde bir dizi içinde verilerin tutulduğunu düşünelim.

Verinin anahtarları veritabanındaki alan adları ile aynı olmalı. Zaten bu veri dizisini oluştururken gerekli sql injection kontrolleri yapılıp kolayca kurtulabilinir fakat her değerde bir ton fonksiyon çağırmaya gerek yok. Kısaca :

kullanımıyla tüm diziye mysql_real_escape_string() uygulayabiliriz.

Sonra zaten cümleyi oluşturmak için genel method olan sprintf ile alanları ve değerleri basacağız. Ancak işin güzelliği burada bu alanlar ve değerler kısımlarını bir sürü döngü ile çözmeyeceğiz.

Gördüğünüz gibi array_keys ve array_values ile hızlıca alanlar ve değerleri alıp implode ile aralarına virgül ve tırnak ekleyebiliriz. Burada dikkat edeceğimiz şey implode sadece değerlerin aralarına tırnak ve virgül ekleyecektir. En dışda kalan tırnakları sprintf içinde tanımlayacağız.

Sonuç olarak bu noktada $sql değişkeninde, değerler ve alanlar giydirilmiş, aşağıdaki gibi bir sql cümlesi elde etmiş olacağız.

Bu cümleyi de mysql_query($sql) ile çalıştırıp sonucu işlemede bitiyor olay.

MDB2 Kullanımı ve SQL Injection

MDB2 Nedir?

MDB2 ilk başta DB olarak başlayan sonra MDB olan ve en son MDB2 ismine dönüşen PEAR’ın veritabanı yönetim paketlerinden birisidir. Oldukça fazla türde veritabanı sürücüsü (driver) bulunduğu için, projenizde bu kütüphaneyi kullanıp fakrlı veritabanı yapılarını aynı kodda rahatça kullanabilmenizi sağlar. Ayrıca “prepare & execute” gibi yapılarla hem sql sorgularınızı daha anlaşılır yapar, hem de injection gibi saldırılar için veri türü kontrollerini otomatik yapar.

Sonuç olarak güvenlik, daha taşınabilir kod, kolaylık gibi özelliklerinden dolayı tercih edilmesi gereklidir diye düşünüyorum. Genel olarak PHP’nin PDO’suna benzeyen bir yapısı var (özellikler bakımından).

Örneklerle Genel Kullanımı

PEAR’ı sisteminize kurmanız gerekiyor. Ya da PEAR’ı kendi projenize gömerek de kullanabilirsiniz. http://pear.php.net/package/MDB2 adresinden MDB2’yi indirebilirsiniz. PEAR dizininizi include_path’a tanıtırsanız şu şekilde sayfa başında MDB2’yi çalıştırabilirsiniz :

Bağlantı

MDB2’yi bağlamak çok kolay. Bağlantı fonksiyonunda DSN (Data Source Name) denilen bir cümle ile veritabanı türü, kullanıcı, şifresi, sunucu, port, veritabanı adını bir url olarak veriyorsunuz. Yani fonksiyona 100 tane parametre girmek zorunda kalmıyorsunuz.

Aşağıdaki örnekten rahatça anlayacaksınız zaten DSN’nin nasıl birşey olduğunu :

gördüğünüz gibi bir web sitesi url’si tanımlamak gibi. Daha doğrusu ftp erişimi yapmak gibi.
protokol türü + “://” + kullanıcı + “:” + şifre + “@” + sunucu (+”:port”) + “/” veritabanı

Yani siz aynı veritabanı yapısını oluşturduğunuz sürece projenizi ileride mysql:// yerine pgsql:// yazarak kolayca çevirebileceksiniz.

Neyse, bağlantı kısmı işin başlangıcı. Asıl sık sık kullanacağımız olan şey sorgu işletmek, sonuçları işlemek vs.

Sorgu işletmek

Örnekte tüm detayları açıkladım 🙂 Eğer çok boyutlu sonuçlarla çalışıyorsanız fetchAll ile halletmenizi öneririm işlerinizi. Eğer tek boyutlu sonuç bekliyorsanız fetchRow işinizi görecektir.

Injection için güzellikler

En sevdiğim kısmı ise sizi verilerinizin türünü kontrol etme işini üstünüzden alması. Bunun için iki yol var. Birincisi query kullanarak quote yapmak. Yani Türkçesi, yukarıdaki methodu kullanarak sorgu işletmek, ama işletirken de değişkenleri tek tek bir fonksiyondan geçirmek. Örnekle anlatırsam :

görüldüğü gibi sql içinde herhangi bir tırnak kullanmadan doğrudan quote() fonksiyonunu kullandım. ilk parametrede veri ikinci parametrede de veri türünü belirtiyorsunuz. Eğer text ise sql injection önlemlerini alıyor. integer ise zaten sayısallaştırıp kaydediyor.

Ancak yine de sqliniz oldukça karışık görünüyor. Yani baksanıza bir sürü tırnak ile SQL cümlesini oluşturan string’den kaçmak için uğraştık. Ayrıca sürekli $db->quote(…) gibi bir fonksiyon çağırmak, elinizde 20 tane alan varsa sıkıcı bir işe dönüşecektir. Bunun için prepare & execute yapısını kullanacağız.

Prepare & Execute

quote kullanımından biraz daha uzun. Ancak eğer sorgunuzda kullanıcıdan gelebilecek bir veri kullanıyorsanız KESİNLİKLE bu yapıyı kullanmanızı öneririm. Yani sonuçta gözünüzden kaçabiliyor bazen değişkenlerinizi izlemek ve kontrol etmek. Bu kullanıma alışırsanız farkında olmadan vereceğiniz açık sayısı en az inecektir.

Gelelim kullanıma, bunu da örnekleyerek anlatacağım :

Bu örnekte tek değişken gösterdiğim için pek anlaşılmamış olabilir. Ancak alttaki örnekte prepare & execute yapısının önemini kavrayacaksınız.

Son kısımda bahsettiğim detayı umarım anlayabilmişsinizdir. Çünkü bu şekilde uygulama geliştirdiğiniz zaman, uygulamanız daha esnek, daha rahat müdahale edilebilir ve daha rahat geliştirilebilir hale gelecektir. Siz üye kayıt sayfasını daha sadeleştirmiş olacak, eğer gerekirse üye veritabanında yapacağınız bir değişiklik için gidip üye kayıt sayfasının içinde HTML, PHP karışık kodun içinde aramak yerine doğrudan fonksiyonunuzdaki sql’i güncelleyerek daha hızlı çalışacaksınız.

Bu noktada iş gruplarına ait fonksiyonları sınıflandırırsanız zaten Nesne Tabanlı Programlama (OOP)’ya adım atmış olacaksınız 🙂