{"id":2010,"date":"2017-09-10T12:40:12","date_gmt":"2017-09-10T10:40:12","guid":{"rendered":"https:\/\/guven.atbakan.com\/blog\/?p=2010"},"modified":"2022-11-09T09:53:36","modified_gmt":"2022-11-09T06:53:36","slug":"laravelde-uuid-kullanimi","status":"publish","type":"post","link":"https:\/\/guven.atbakan.com\/blog\/tr\/laravelde-uuid-kullanimi\/","title":{"rendered":"Laravel&#8217;de UUID kullan\u0131m\u0131"},"content":{"rendered":"<p>G\u00fcncelleme: Laravel v9.30 s\u00fcr\u00fcm\u00fc ile birlikte modellerdeki primary keylerde UUID kullan\u0131m\u0131 i\u00e7in dahili bir trait geliyor. Detaylar: <a href=\"https:\/\/twitter.com\/enunomaduro\/status\/1589598736715370496\">https:\/\/twitter.com\/enunomaduro\/status\/1589598736715370496<\/a><\/p>\n<hr \/>\n<p>Buraya kadar geldi\u011finize g\u00f6re muhtemelen ne oldu\u011funu biliyorsunuzdur ama yine de Laravel&#8217;de UUID&#8217;nin nas\u0131l kullan\u0131ld\u0131\u011f\u0131n\u0131 anlatmaya ba\u015flamadan \u00f6nce k\u0131saca bir UUID tan\u0131m\u0131n\u0131 yapal\u0131m ve ne oldu\u011funu anlatmaya \u00e7al\u0131\u015fal\u0131m.<\/p>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Universally_unique_identifier\">UUID<\/a>, &quot;Universally unique identifier&quot; nin k\u0131salt\u0131lm\u0131\u015f\u0131d\u0131r. Kabaca \u00e7evirirsek, evrensel(?) benzersiz tan\u0131mlay\u0131c\u0131 diyebiliriz. Normalde veritaban\u0131nda sat\u0131rlar\u0131 tan\u0131mlay\u0131c\u0131 olarak integer kullan\u0131r\u0131z. UUID ise, 36 karakterlik, say\u0131lar ve harflerden olu\u015fan, bir settir. Ve en \u00f6nemli \u00f6zelli\u011fi, y\u00fcksek derecede benzersiz olmas\u0131d\u0131r. (Bilgisayarda rastgele \u00fcretilen hi\u00e7bir \u015fey asl\u0131nda tam olarak rastgele de\u011fildir. Rastgeleli\u011fi artt\u0131rabiliriz. De\u011fi\u015fik bi konu.)<\/p>\n<p>\u00d6rnek olarak \u015f\u00f6yle bir ka\u00e7 tane g\u00f6sterebilirim:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2011\" src=\"https:\/\/guven.atbakan.com\/blog\/wp-content\/uploads\/2017\/09\/Screenshot-from-2017-09-10-02-37-49.png\" alt=\"\" width=\"220\" height=\"294\" \/><\/p>\n<p>UUID genellikle b\u00fcy\u00fck projelerde i\u015fe yarayabiliyor. Biliyorsunuz, veritaban\u0131nda integer alan\u0131n\u0131n maximum de\u011feri var. Mysql&#8217;deki de\u011feleri \u015furadan g\u00f6rebilirsiniz: <a href=\"https:\/\/dev.mysql.com\/doc\/refman\/5.7\/en\/integer-types.html\"><a href=\"https:\/\/dev.mysql.com\/doc\/refman\/5.7\/en\/integer-types.html\">https:\/\/dev.mysql.com\/doc\/refman\/5.7\/en\/integer-types.html<\/a><\/a><\/p>\n<p>Burada minimum-maximum de\u011ferlere bir paragraf a\u00e7\u0131yorum. Veritaban\u0131nda id alan\u0131, Primary Key olarak tan\u0131mlan\u0131r. PrimaryKey alan\u0131 do\u011fas\u0131 gere\u011fi unsigned olarak tan\u0131mlan\u0131r. Bu y\u00fczden ilgilendi\u011finiz alan unsigned olmal\u0131. Peki unsigned de\u011fer ne demek? Negatif olmayan say\u0131lar demek. Linkteki tabloya bakt\u0131\u011f\u0131m\u0131zda, TinyInt t\u00fcr\u00fc i\u00e7in signed [-127, 127] aral\u0131\u011f\u0131ndayken, unsigned [0, 255] aral\u0131\u011f\u0131nda de\u011fer alabiliyor.<\/p>\n<p>Primary key, varsay\u0131lan olarak INT, unsigned tan\u0131mlan\u0131r. Bu da demektir ki, o tabloya maksimum <code class=\"literal\">4294967295<\/code> kay\u0131t eklenebilir. San\u0131rsam, 4 milyar 294 milyon 967 bin 295 kay\u0131t. Her ne kadar \u00e7ok b\u00fcy\u00fck bir say\u0131 olsa da, sonsuz de\u011fil. <del datetime=\"2017-09-11T08:18:39+00:00\">E\u011fer uuid olarak tan\u0131mlarsan\u0131z, sonsuz kay\u0131t ekleyebilirsiniz. (Acaba \u00f6yle mi? Ke\u015fke birisi bunun do\u011frulamas\u0131n\u0131 yapsa)<\/del> Maksimum ka\u00e7 kay\u0131t eklenebilece\u011fi ile ilgili yan\u0131t: <a href=\"https:\/\/twitter.com\/hkanaktas\/status\/906891710155849730\"><a href=\"https:\/\/twitter.com\/hkanaktas\/status\/906891710155849730\">https:\/\/twitter.com\/hkanaktas\/status\/906891710155849730<\/a><\/a><\/p>\n<p>Bunun haricinde, \u00e7ok olas\u0131 de\u011fil ama, bir tablonuz da\u011f\u0131t\u0131k bi\u00e7imde \u00e7al\u0131\u015f\u0131yorsa, primary key alan\u0131n\u0131z\u0131n \u00e7ak\u0131\u015fmas\u0131n\u0131 \u00f6nler. Farazi bir \u00f6rnek verelim. Diyelim ki kullan\u0131c\u0131n\u0131n gezdi\u011fi sayfalar\u0131 kay\u0131t alt\u0131na al\u0131yorsunuz. \u00d6yle ki, \u00e7ok yo\u011fun bir sistem ve kay\u0131tlar\u0131 %50 A sunucusundaki logs tablosuna, %50 B sunucusundaki logs tablosuna kaydediyorsunuz. G\u00fcn\u00fcn sonunda verileri C sunucusunda birle\u015ftirmek istedi\u011finizde, id alan\u0131 \u00e7ak\u0131\u015facakt\u0131r. Bunun i\u00e7in idleri yeniden vermeniz gerekmektedir. Fakat uuid kullan\u0131rsan\u0131z, herhangi bir yenileme yapmadan do\u011frudan verileri birle\u015ftirebilirsiniz.<\/p>\n<p>Son olarak \u015funu s\u00f6yleyeyim, tahmin edilmesi olduk\u00e7a zordur. \u00d6rne\u011fin kullan\u0131c\u0131lar tablomuzda int kullansayd\u0131k, \u00fcye kay\u0131tlar\u0131 1,2,3,4,5 diye d\u00fczenli olarak gidecekti. Ve emin olun sald\u0131rganlar ilk olarak url&#8217;deki idleri de\u011fi\u015ftirerek eri\u015fim sa\u011flamaya \u00e7al\u0131\u015f\u0131r. Gerekli kontrolleri ald\u0131ysan\u0131z s\u0131k\u0131nt\u0131 olmaz. Fakat uuid ile bu s\u0131k\u0131nt\u0131 daha da az ya\u015fan\u0131r. \u00c7\u00fcnk\u00fc bir sonraki kullan\u0131c\u0131n\u0131n id&#8217;si tahmin edilemez hale gelir. Siz yine de arka tarafta gerekli kontrolleri yapmay\u0131 unutmay\u0131n.<\/p>\n<h2>Gelelim Laravel Kulan\u0131m\u0131na<\/h2>\n<p>UUID&#8217;leri \u00fcretmek i\u00e7in ek paket kullanmam\u0131z gerekiyor. Ben <a href=\"https:\/\/github.com\/ramsey\/uuid\">ramsey\/uuid<\/a> paketini kullan\u0131yorum.<\/p>\n<pre class=\"lang:sh decode:true\">$ composer require ramsey\/uuid<\/pre>\n<p>Bu paket sayesinde art\u0131k UUID \u00fcretebiliriz. README dosyas\u0131nda kullan\u0131m\u0131 var, ama k\u0131saca ben de buradan tekrar edeyim:<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\n \/\/ Generate a version 1 (time-based) UUID object\n    $uuid1 = Uuid::uuid1();\n    echo $uuid1-&gt;toString() . \"n\"; \/\/ i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd\n\n    \/\/ Generate a version 3 (name-based and hashed with MD5) UUID object\n    $uuid3 = Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net');\n    echo $uuid3-&gt;toString() . \"n\"; \/\/ i.e. 11a38b9a-b3da-360f-9353-a5a725514269\n\n    \/\/ Generate a version 4 (random) UUID object\n    $uuid4 = Uuid::uuid4();\n    echo $uuid4-&gt;toString() . \"n\"; \/\/ i.e. 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a\n\n    \/\/ Generate a version 5 (name-based and hashed with SHA1) UUID object\n    $uuid5 = Uuid::uuid5(Uuid::NAMESPACE_DNS, 'php.net');\n    echo $uuid5-&gt;toString() . \"n\"; \/\/ i.e. c4a760a8-dbcf-5254-a0d9-6a4474bd1b62<\/pre>\n<p>Bu pakette toplam 4 \u00e7e\u015fit \u00fcretme y\u00f6ntemi var. Hangisini kullanaca\u011f\u0131n\u0131z konusunda tercih size kalm\u0131\u015f. Ben farklar\u0131n\u0131 bilmiyorum, ara\u015ft\u0131rmad\u0131m.<\/p>\n<h2>G\u00f6\u00e7 yollar\u0131, g\u00f6r\u00fcnd\u00fc bize<\/h2>\n<p>Paketi y\u00fckledikten sonra, ilk de\u011fi\u015fikli\u011fimiz migration yaz\u0131m\u0131nda kar\u015f\u0131m\u0131za \u00e7\u0131k\u0131yor.<\/p>\n<p>Normalde bir migration olu\u015fturdu\u011funuzda \u015fu \u015fekilde oluyor:<\/p>\n<pre class=\"lang:default decode:true \">$table-&gt;increments('id');<\/pre>\n<p>Bu fonksiyonun detay\u0131na bakt\u0131\u011f\u0131m\u0131zda, unsignedInteger tipinde olu\u015fturdu\u011funu g\u00f6receksiniz. Bunun yerine \u015funu yazmam\u0131z daha manidar:<\/p>\n<pre class=\"lang:default decode:true \">$table-&gt;uuid('id')-&gt;primary();<\/pre>\n<p>ID alan\u0131m\u0131z\u0131n uuid t\u00fcr\u00fcnde oldu\u011funu, ve bu alan\u0131n tablomuzun birincil alan\u0131(reyizi) oldu\u011funu s\u00f6yleyerek tablomuu olu\u015fturuyoruz. Bu da asl\u0131nda \u00f6zel bir kolon t\u00fcr\u00fc de\u011fil, 36 karakterlik char alan\u0131 olu\u015fturuyor tablomuzda.<\/p>\n<h2>Model dosyalar\u0131nda de\u011fi\u015fiklik<\/h2>\n<p>\u0130lk \u00f6nce modelin primary key&#8217;in otomatik artma \u00f6zelli\u011fini kapatal\u0131m. Eloquent&#8217;te primary key, varsay\u0131lan olarak int, auto increment olarak kabul edilir. Bunu de\u011fi\u015ftirelim.<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\n\nclass Bilmemne extends \\Illuminate\\Database\\Eloquent\\Model {\n\n    public $incrementing = false;\n\n}\n<\/pre>\n<p>Otomatik artt\u0131rmay\u0131 kapatt\u0131k ama, \u015fimdi de bir modeli kaydetmek istedi\u011fimizde, otomatik olarak say\u0131 yazmaya \u00e7al\u0131\u015facak eloquent. Bunun i\u00e7in Eloquent event&#8217;lerinden yararlan\u0131yoruz:<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\n\nclass Bilmemne extends \\Illuminate\\Database\\Eloquent\\Model {\n\n    public $incrementing = false;\n\n    protected static function boot()\n    {\n        parent::boot();\n\n        static::creating(function ($model) {\n            $model-&gt;{$model-&gt;getKeyName()} = \\Ramsey\\Uuid\\Uuid::uuid1()-&gt;toString();\n        });\n    }\n\n}\n<\/pre>\n<p>Peki bu kod ne yap\u0131yor? $model-&gt;save() komutunu \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131n\u0131zda, model verileri, veritaban\u0131na kaydedilmek \u00fczere haz\u0131rlan\u0131yor. Bu kod sayesinde, modelimiz veritaban\u0131na kaydedilmeden \u00f6nce &#8216;id&#8217; alan\u0131n\u0131n de\u011ferini uuid ile de\u011fi\u015ftiriyoruz.<\/p>\n<p><strong>Hepsi bu!<\/strong> Art\u0131k id alan\u0131m\u0131z integer yerine uuid olarak kaydediliyor. Fakat burada g\u00f6ze g\u00fczel g\u00f6r\u00fcnmeyen bir\u015fey var. Bu kodu t\u00fcm modellere tek tek kopyalay\u0131p yap\u0131\u015ft\u0131raca\u011f\u0131z. Bunun \u00f6n\u00fcne ge\u00e7mek i\u00e7in yapabilece\u011fimiz 2 \u015fey var. Birincisi, extend edilen s\u0131n\u0131f\u0131 de\u011fi\u015ftirmek. \u0130kincisi ise Trait kullanmak.<\/p>\n<p><strong>1. Y\u00f6ntem: Extend edilen s\u0131n\u0131f\u0131 de\u011fi\u015ftirmek<\/strong><\/p>\n<p>\u00d6ncelikle yeni bir model s\u0131n\u0131f\u0131 \u00fcretelim.<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\n\nclass MyModel extends \\Illuminate\\Database\\Eloquent\\Model\n{\n    public $incrementing = false;\n\n    protected static function boot()\n    {\n        parent::boot();\n\n        static::creating(function ($model) {\n            $model-&gt;{$model-&gt;getKeyName()} = \\Ramsey\\Uuid\\Uuid::uuid1()-&gt;toString();\n        });\n    }\n}\n<\/pre>\n<p>Daha sonra kendi s\u0131n\u0131f\u0131m\u0131z\u0131n ayarlar\u0131yla oynayal\u0131m:<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php \n\nclass Bilmemne extends MyModel { \n\n}\n<\/pre>\n<p>Bilmemne modelimiz art\u0131k integer yerine uuid \u00fcretiyor!<\/p>\n<p><strong>2. Y\u00f6ntem: Trait kullanmak<\/strong><\/p>\n<p>Bildi\u011finiz gibi bir s\u0131n\u0131f birden fazla s\u0131n\u0131ftan t\u00fcretilemiyor(extend edilemiyor). Siz birden fazla s\u0131n\u0131f\u0131n \u00f6zelli\u011fini kullanmak isterseniz ya hepsini birbirinden extend edeceksiniz -ki etmeyin- ya da trait kullanarak istedi\u011finiz methodlar\u0131 kullanacaksan\u0131z. Laravel&#8217;e bakt\u0131\u011f\u0131m\u0131zda trait kullan\u0131m\u0131n\u0131n yo\u011fun oldu\u011funu g\u00f6r\u00fcr\u00fcz. Traitler bize kodlar\u0131n yeniden kullan\u0131m\u0131 konusunda yard\u0131mc\u0131 olur. Tekrar yaz\u0131mlar\u0131n \u00f6n\u00fcne ge\u00e7er. Kodumuzu par\u00e7alara b\u00f6lebilmemizi sa\u011flar ve kodun kolay takibini sa\u011flar. \u00d6rnek olarak Laravel&#8217;in model s\u0131n\u0131f\u0131n\u0131n neler kulland\u0131\u011f\u0131na bakal\u0131m:<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\n\nabstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable\n{\n    use ConcernsHasAttributes,\n        ConcernsHasEvents,\n        ConcernsHasGlobalScopes,\n        ConcernsHasRelationships,\n        ConcernsHasTimestamps,\n        ConcernsHidesAttributes,\n        ConcernsGuardsAttributes;\n}\n<\/pre>\n<p>Model s\u0131n\u0131f\u0131 yorumlar da dahil 1460 sat\u0131r. Traitlerin i\u00e7indeki methodlar\u0131 da bu s\u0131n\u0131fa dahil etseydik kim bilir ka\u00e7 sat\u0131r olacakt\u0131. Kodun birbiriyle ilgili b\u00f6l\u00fcmlerini al\u0131p trait i\u00e7erisine koyup, traiti de model i\u00e7erisinde sadece use ile \u00e7a\u011f\u0131rmak olduk\u00e7a g\u00fczel bir fikir. Daha \u00f6v\u00fclecek \u00e7ok yan\u0131 vard\u0131r da, hem \u015fimdi akl\u0131ma gelmiyor(hepsini bilmiyor da olabilirim) hem de art\u0131k kendi trait kodumuza ge\u00e7elim.<\/p>\n<pre class=\"lang:php decode:true crayon-selected\" title=\"UuidsTrait.php\">&lt;?php\n\ntrait UuidsTrait\n{\n    protected static function boot()\n    {\n        parent::boot();\n\n        static::creating(function ($model) {\n            $model-&gt;{$model-&gt;getKeyName()} = \\Ramsey\\Uuid\\Uuid::uuid1()-&gt;toString();\n        });\n    }\n}\n<\/pre>\n<p>Tek yapmam\u0131z gereken, bunu modelimiz i\u00e7erisinde kullanmak:<\/p>\n<pre class=\"lang:php decode:true\">&lt;?php\n\nclass Bilmemne extends \\Illuminate\\Eloquent\\Database\\Model { \n\n    use UuidsTrait;\n}<\/pre>\n<p>Bu da tam olarak istedi\u011fimiz gibi sonu\u00e7 verecek ve integer yerine uuid kullanmam\u0131z\u0131 sa\u011flayacak.<\/p>\n<p>Trait olarak kullanmak ve extend etmek aras\u0131nda belli farklar var fakat onlar\u0131 ba\u015fka bir yaz\u0131 konusu yapabiliriz. \u015eimdilik ben size bu i\u015f i\u00e7in trait kullanman\u0131z\u0131 \u00f6neririm.<\/p>\n<p>Esenlikle kal\u0131n.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>G\u00fcncelleme: Laravel v9.30 s\u00fcr\u00fcm\u00fc ile birlikte modellerdeki primary keylerde UUID kullan\u0131m\u0131 i\u00e7in dahili bir trait geliyor. Detaylar: https:\/\/twitter.com\/enunomaduro\/status\/1589598736715370496 Buraya kadar geldi\u011finize g\u00f6re muhtemelen ne oldu\u011funu biliyorsunuzdur ama yine de Laravel&#8217;de UUID&#8217;nin nas\u0131l kullan\u0131ld\u0131\u011f\u0131n\u0131 anlatmaya ba\u015flamadan \u00f6nce k\u0131saca bir UUID tan\u0131m\u0131n\u0131 yapal\u0131m ve ne oldu\u011funu anlatmaya \u00e7al\u0131\u015fal\u0131m. UUID, &quot;Universally unique identifier&quot; nin k\u0131salt\u0131lm\u0131\u015f\u0131d\u0131r. Kabaca \u00e7evirirsek, evrensel(?) [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[345,367,369,368],"class_list":["post-2010","post","type-post","status-publish","format-standard","hentry","category-yazilim","tag-laravel","tag-laravel-uuid","tag-uuid-nedir","tag-veritabani-signed-unsigned"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2010","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/comments?post=2010"}],"version-history":[{"count":8,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2010\/revisions"}],"predecessor-version":[{"id":2501,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2010\/revisions\/2501"}],"wp:attachment":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/media?parent=2010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/categories?post=2010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/tags?post=2010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}