Development

Documentation/id_ID/book/1.0/02-Exploring-Symfony-s-Code (diff)

You must first sign up to be able to contribute.

Changes from Version 1 of Documentation/id_ID/book/1.0/02-Exploring-Symfony-s-Code

Show
Ignore:
Author:
tohenk (IP: 202.95.150.6)
Timestamp:
03/02/09 04:17:03 (9 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/id_ID/book/1.0/02-Exploring-Symfony-s-Code

    v0 v1  
     1{{{ 
     2#!WikiMarkdown 
     3 
     4Bab 2 - Menjelajah Kode Symfony 
     5=============================== 
     6 
     7Sekilas, kode di belakang aplikasi yang dibangun dengan symfony begitu membingungkan. Terdiri dari beberapa direktori dan skrip, dan file-file tersebut bercampur antara kelas-kelas PHP, HTML, dan bahkan percampuran antara keduanya. Anda juga akan melihat referensi ke kelas-kelas yang tidak akan ditemukan dalam folder aplikasi, dan kedalaman direktori aplikasi bahkan mencapai enam tingkatan. Tetapi sekali anda memahami alasan di belakang ke-kompleks-an tersebut, anda akan merasa hal tersebut begitu wajar sehingga anda tidak akan membandingkan struktur aplikasi symfony dengan yang lain. Bab ini mencoba menjelaskan untuk menghilangkan anggapan tersebut. 
     8 
     9Pola MVC 
     10-------- 
     11 
     12Symfony didasarkan pada pola desain web klasik yang dikenal dengan arsitektur MVC, yang terdiri dari tiga tingkatan: 
     13 
     14  * Model, mewakili informasi yang mana aplikasi beroperasi--logika bisnis. 
     15  * View menggambarkan model ke dalam halaman web yang sesuai untuk interaksi dengan pemakai. 
     16  * Controller merespon aksi pemakai dan mengaplikasikan perubahan pada model atau pada view. 
     17 
     18Figur 2-1 mengilustrasikan pola MVC. 
     19 
     20Arsitektur MVC memisahkan logika bisnis (model), dan presentasi (view), sehingga menghasilkan kemudahan pemeliharaan. Sebagai contoh, jika aplikasi anda seharusnya bisa berjalan pada browser web standar dan peralatan genggam, anda hanya memerlukan sebuah view baru; anda dapat membiarkan controller dan model sesuai aslinya. Controller membantu menyembunyikan detail dari protokol yang digunakan untuk request (HTTP, modus konsol, mail, dll) dari model dan view. Dan model mengabstraksi logika data, yang mana membuat view dan action menjadi independen, contohnya, tipe database yang dipakai oleh aplikasi. 
     21 
     22Figur 2-1 - Pola MVC 
     23 
     24![The MVC pattern](/images/book/F0201.png "The MVC pattern") 
     25 
     26### Pelapisan MVC 
     27 
     28Untuk membantu memahami keuntungan MVC, mari kita mengubah sebuah aplikasi PHP sederhana ke aplikasi berarsitektur MVC. Sebuah daftar postingan pada aplikasi weblog akan menjadi contoh yang sesuai. 
     29 
     30#### Pemrograman Datar 
     31 
     32Dalam sebuah file skrip PHP datar, untuk menampilkan daftar dari entri-entri database kemungkinan terlihat seperti skrip pada Listing 2-1. 
     33 
     34Listing 2-1 - Sebuah Skrip Datar 
     35 
     36    [php] 
     37    <?php 
     38 
     39    // Koneksi, memilih database 
     40    $link = mysql_connect('localhost', 'myuser', 'mypassword'); 
     41    mysql_select_db('blog_db', $link); 
     42 
     43    // Mengeksekusi query SQL 
     44    $result = mysql_query('SELECT date, title FROM post', $link); 
     45 
     46    ?> 
     47 
     48    <html> 
     49      <head> 
     50        <title>List of Posts</title> 
     51      </head> 
     52      <body> 
     53       <h1>List of Posts</h1> 
     54       <table> 
     55         <tr><th>Date</th><th>Title</th></tr> 
     56    <?php 
     57    // Menampilkan hasil sebagai HTML 
     58    while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) 
     59    { 
     60    echo "\t<tr>\n"; 
     61    printf("\t\t<td> %s </td>\n", $row['date']); 
     62    printf("\t\t<td> %s </td>\n", $row['title']); 
     63    echo "\t</tr>\n"; 
     64    } 
     65    ?> 
     66        </table> 
     67      </body> 
     68    </html> 
     69 
     70    <?php 
     71 
     72    // Menutup koneksi 
     73    mysql_close($link); 
     74 
     75    ?> 
     76 
     77Contoh tersebut sebentar untuk ditulis, cepat dieksekusi, dan sulit dipelihara. Berikut kelemahan terbesar dari kode tersebut: 
     78 
     79  * Tidak ada pengecekan kesalahan (bagaimana jika koneksi ke database gagal?). 
     80  * HTML dan kode PHP bercampur, bahkan campur aduk. 
     81  * Kode hanya diperuntukkan untuk database MySQL. 
     82 
     83#### Mengisolasi Presentasi 
     84 
     85Perintah `echo` dan `printf` pada Listing 2-1 membuat kode sulit dipahami. Modifikasi kode HTML untuk memisahkan presentasi dengan sintaks yang ada akan membutuhkan sedikit usaha. Jadi kode tersebut dapat dipisahkan menjadi dua bagian. Pertama, kode PHP murni yang berisi logika bisnis berada pada skrip controller, seperti ditunjukkan pada Listing 2-2. 
     86 
     87Listing 2-2 - Bagian Controller, pada `index.php` 
     88 
     89    [php] 
     90    <?php 
     91 
     92     // Koneksi, memilih database 
     93     $link = mysql_connect('localhost', 'myuser', 'mypassword'); 
     94     mysql_select_db('blog_db', $link); 
     95 
     96     // Mengeksekusi query SQL 
     97     $result = mysql_query('SELECT date, title FROM post', $link); 
     98 
     99     // Mempersiapkan array untuk view 
     100     $posts = array(); 
     101     while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) 
     102     { 
     103        $posts[] = $row; 
     104     } 
     105 
     106     // Menutup koneksi 
     107     mysql_close($link); 
     108 
     109     // Menyertkan view 
     110     require('view.php'); 
     111 
     112     ?> 
     113 
     114Kode HTML, berisi sintaks PHP dengan model template, disimpan dalam skrip view, seperti ditunjukkan pada Listing 2-3. 
     115 
     116Listing 2-3 - Bagian View, pada `view.php` 
     117 
     118    [php] 
     119    <html> 
     120      <head> 
     121        <title>List of Posts</title> 
     122      </head> 
     123      <body> 
     124        <h1>List of Posts</h1> 
     125        <table> 
     126          <tr><th>Date</th><th>Title</th></tr> 
     127        <?php foreach ($posts as $post): ?> 
     128          <tr> 
     129            <td><?php echo $post['date'] ?></td> 
     130            <td><?php echo $post['title'] ?></td> 
     131          </tr> 
     132        <?php endforeach; ?> 
     133        </table> 
     134      </body> 
     135    </html> 
     136 
     137Sebuah aturan yang baik untuk menentukan apakah view sudah cukup bersih jika view tersebut hanya berisi sedikit kode PHP saja, agar mudah dimengerti oleh seorang desainer HTML tanpa perlu pengetahuan tentang PHP. Kebanyakan statemen umum yang dijumpai dalam view yaitu echo, if/endif, foreach/endforeach, dan hanya itu semua. Juga, seharusnya tidak ada kode PHP yang meng-echo-kan tag HTML. 
     138 
     139Semua logika berapa pada skrip controller, dan hanya berisi kode PHP murni, tanpa ada HTML di dalamnya. Sebagai faktanya, anda dapat membayangkan bahwa controller tersebut dapat digunakan kembali untuk presentasi yang sama sekali berbeda, seperti untuk file PDF atau sebuah struktur XML. 
     140 
     141#### Mengisolasi Manipulasi Data 
     142 
     143Kebanyakan skrip pada controller digunakan untuk memanipulasi data. Tetapi bagaimana jika anda membutuhkan daftar postingan untuk controller yang lain, katakan untuk kontroller yang akan menghasilkan umpan RSS dari postingan weblog? Bagaimana jika anda ingin menempatkan semua query ke database dalam satu tempat, untuk menghindari pengulangan kode? Bagaimana jika anda memutuskan untuk mengubah model data sehingga tabel `post` berubah menjadi `weblog_post`? Bagaimana jika anda ingin berpindah ke PostgreSQL daripada MySQL? Agar semua itu terwujud, anda harus menghilangkan kode manipulasi data dari controller dan meletakkannya pada skrip lain, yang disebut model, seperti ditunjukkan pada Listing 2-4. 
     144 
     145Listing 2-4 - Bagian Model, pada `model.php` 
     146 
     147    [php] 
     148    <?php 
     149 
     150    function getAllPosts() 
     151    { 
     152      // Koneksi, memilih database 
     153      $link = mysql_connect('localhost', 'myuser', 'mypassword'); 
     154      mysql_select_db('blog_db', $link); 
     155 
     156      // Mengeksekusi query SQL 
     157      $result = mysql_query('SELECT date, title FROM post', $link); 
     158 
     159      // Mempersiapkan array 
     160      $posts = array(); 
     161      while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) 
     162      { 
     163         $posts[] = $row; 
     164      } 
     165 
     166      // Menutup koneksi 
     167      mysql_close($link); 
     168 
     169      return $posts; 
     170    } 
     171 
     172    ?> 
     173 
     174Controller yang sudah diperbarui seperti ditunjukkan pada Listing 2-5. 
     175 
     176Listing 2-5 - Bagian Revisi Controller, pada `index.php` 
     177 
     178    [php] 
     179    <?php 
     180 
     181    // Menyertakan model 
     182    require_once('model.php'); 
     183 
     184    // Mengambil semua daftar postingan 
     185    $posts = getAllPosts(); 
     186 
     187    // Menyertakan view 
     188    require('view.php'); 
     189 
     190    ?> 
     191 
     192Controller menjadi mudah dipahami. Tugas utamanya yaitu mengambil data dari model dan memberikannya pada view. Pada aplikasi yang lebih kompleks, controller juga berhubungan dengan request, sesi pemakai, otentikasi, dll. Penggunaan nama fungsi eksplisit pada model bahkan tidak membutuhkan komentar khusus pada controller. 
     193 
     194Skrip model ditujukan untuk akses data dan dapat diorganisir menyesuaikannya. Semua parameter yang tidak tergantung pada lapisan data (seperti parameter request) harus diberikan oleh controller dan tidak diakses secara langsung oleh model. Fungsi-fungsi pada model dapat dengan mudah digunakan untuk controller yang lain. 
     195 
     196### Pemisahan Lapisan Di Luar MVC 
     197 
     198Jadi prinsip arsitektur MVC adalah memisahkan kode ke dalam tiga lapisan, sesuai dengan fungsinya. Logika data ditempatkan pada model, kode presentasi pada view, dan logika aplikasi pada controller. 
     199 
     200Dengan tambahan pola desain yang lain, pengalaman pengkodean bahkan menjadi lebih mudah. Model, view, dan controller dapat dibagi lebih jauh lagi. 
     201 
     202#### Abstraksi Database 
     203 
     204Lapisan model dapat dipisahkan menjadi lapisan akses data dan lapisan abstraksi database. Dengan cara tersebut, fungsi-fungsi akses data tidak akan menggunakan statemen query yang tergantung pada database tertentu, akan tetapi memanggil fungsi-fungsi lain yang berfungsi untuk melakukan query tersebut. Jika anda kemudian mengubah sistem database, hanya lapisan abstraksi database saja yang perlu diperbarui. 
     205 
     206Sebuah contoh lapisan abstraksi database seperti ditunjukkan pada Listing 2-6, diikuti sebuah contoh lapisan akses data khusus untuk MySQL pada Listing 2-7. 
     207 
     208Listing 2-6 - Bagian Abstraksi Database pada Model 
     209 
     210    [php] 
     211    <?php 
     212 
     213    function open_connection($host, $user, $password) 
     214    { 
     215      return mysql_connect($host, $user, $password); 
     216    } 
     217 
     218    function close_connection($link) 
     219    { 
     220      mysql_close($link); 
     221    } 
     222 
     223    function query_database($query, $database, $link) 
     224    { 
     225      mysql_select_db($database, $link); 
     226 
     227      return mysql_query($query, $link); 
     228    } 
     229 
     230    function fetch_results($result) 
     231    { 
     232      return mysql_fetch_array($result, MYSQL_ASSOC); 
     233    } 
     234 
     235Listing 2-7 - Bagian Akses Data pada Model 
     236 
     237    [php] 
     238    function getAllPosts() 
     239    { 
     240      // Koneksi ke database 
     241      $link = open_connection('localhost', 'myuser', 'mypassword'); 
     242 
     243      // Eksekusi query SQL 
     244      $result = query_database('SELECT date, title FROM post', 'blog_db', $link); 
     245 
     246      // Mempersiapkan array 
     247      $posts = array(); 
     248      while ($row = fetch_results($result)) 
     249      { 
     250         $posts[] = $row; 
     251      } 
     252 
     253      // Menutup koneksi 
     254      close_connection($link); 
     255 
     256      return $posts; 
     257    } 
     258 
     259    ?> 
     260 
     261Anda dapat memeriksa bahwa tidak ada fungsi-fungsi yang bergantung database tertentu dapat ditemukan pada lapisan akses data, hal ini membuat data akses tidak tergantung database yang digunakan. Sebagai tambahan, fungsi-fungsi yang dibuat dalam lapisan abstraksi database dapat digunakan kembali oleh banyak fungsi-fungsi model yang lain ketika membutuhkan akses ke database tersebut. 
     262 
     263>**CATATAN** 
     264>Contoh pada Listings 2-6 and 2-7 masih belum memuaskan, masih ada pekerjaan yang tersisa agar menjadi abstraksi database yang utuh (mengabstraksi kode SQL melalui sebuah query builder yang independen-database, memindah semua fungsi ke dalam kelas, dll). Tetapi tujuan dari buku ini bukan untuk menunjukkan cara membuat semua kode tersebut dengan tangan, dan anda akan melihat pada Bab 8 bahwa symfony secara alami mampu menangani abstraksi tersebut dengan baik. 
     265 
     266#### Elemen-Elemen View 
     267 
     268Lapisan view juga mendapatkan keuntungan dari pemisahan kode. Sebuah halaman web sering berisi elemen-elemen yang konsisten pada keseluruhan aplikasi: header halaman, tata letak grafis, footer, dan navigasi umum. Hanya bagian terdalam halaman yang berubah. Itulah sebabnya mengapa view dipisahkan menjadi layout dan template. Layout biasanya berlaku menyeluruh ke aplikasi, atau terhadap sebuah grup halaman. Template hanya menggambarkan variabel-variabel yang disediakan oleh controller. Beberapa logika dibutuhkan agar semua komponen tersebut bekerja bersama-sama, dan lapisan logika view akan disatukan dan dinamakan view. Menurut prinsip tersebut, bagian view pada Listing 2-3 dapat dipisahkan ke dalam tiga bagian, seperti ditunjukkan pada Listings 2-8, 2-9, dan 2-10. 
     269 
     270Listing 2-8 - Bagian Template pada View, pada `mytemplate.php` 
     271 
     272    [php] 
     273    <h1>List of Posts</h1> 
     274    <table> 
     275    <tr><th>Date</th><th>Title</th></tr> 
     276    <?php foreach ($posts as $post): ?> 
     277      <tr> 
     278        <td><?php echo $post['date'] ?></td> 
     279        <td><?php echo $post['title'] ?></td> 
     280      </tr> 
     281    <?php endforeach; ?> 
     282    </table> 
     283 
     284Listing 2-9 - Bagian Logika View pada View 
     285 
     286    [php] 
     287    <?php 
     288 
     289    $title = 'List of Posts'; 
     290    $content = include('mytemplate.php'); 
     291 
     292    ?> 
     293 
     294Listing 2-10 - Bagian Layout pada View 
     295 
     296    [php] 
     297    <html> 
     298      <head> 
     299        <title><?php echo $title ?></title> 
     300      </head> 
     301      <body> 
     302        <?php echo $content ?> 
     303      </body> 
     304    </html> 
     305 
     306#### Action dan Front Controller 
     307 
     308Controller tidak banyak melakukan tugasnya pada contoh sebelumnya, tetapi pada aplikasi web yang nyata, controller punya banyak pekerjaan. Bagian terpenting dari pekerjaan tersebut berlaku umum ke seluruh aplikasi. Tugas umum tersebut termasuk penanganan request, penanganan keamanan, memuat konfigurasi aplikasi, dan pekerjaan lain yang serupa. Itulah mengapa controller sering dipisahkan menjadi front controller, yang mana bersifat unik dalam keseluruhan aplikasi, dan action-action, yang berupa kode controller yang diperuntukkan hanya untuk satu halaman tertentu. 
     309 
     310Salah satu keuntungan dari front controller yaitu menyediakan jalur masuk unik terhadap keseluruhan aplikasi. Jika anda merencanakan untuk menutup akses ke aplikasi, anda hanya perlu mengubah skrip yang ada pada front controller. Pada aplikasi tanpa front controller, masing-masing controller harus dimatikan satu per satu. 
     311 
     312#### Orientasi Obyek 
     313 
     314Semua contoh-contoh sebelumnya menggunakan pemrograman prosedural. Kemampuan OOP dari bahasa pemrograman modern bahkan membuat pemrograman menjadi lebih mudah, dikarenakan obyek-obyek dapat membungkus logika, pewarisan terhadap satu dengan yang lain, dan menyediakan konvensi penamaan yang bersih. 
     315 
     316Penerapan arsitektur MVC pada bahasa yang tidak berorientasi obyek menimbulkan masalah namespace dan duplikasi kode, dan keseluruhan kode menjadi sulit dipahami. 
     317 
     318Orientasi obyek memperbolehkan pengembang untuk memperlakukan obyek-obyek sebagai obyek view, obyek controller, dan kelas-kelas model, dan untuk mengubah semua fungsi-fungsi pada contoh sebelumnya menjadi metode-metode. Adalah seuatu keharusan pada arsitektur MVC. 
     319 
     320>**TIP** 
     321>Jika anda ingin belajar lebih banyak mengenai pola desain untuk aplikasi web dengan konteks orientasi obyek, baca Patterns of Enterprise Application Architecture oleh Martin Fowler (Addison-Wesley, ISBN: 0-32112-742-0). Contoh kode dalam buku tersebut menggunakan Java atau C#, tetapi masih bisa dipahami oleh seorang pengembang PHP. 
     322 
     323### Penerapaan MVC pada Symfony 
     324 
     325Tunggu sebentar. Untuk sebuah halaman yang menampilkan daftar postingan sebuah weblog, berapa banyak komponen yang dibutuhkan? Seperti diilustrasikan pada Figur 2-2, kita memiliki bagian-bagian berikut: 
     326 
     327  * Lapisan model 
     328    * Abstraksi database 
     329    * Akses data 
     330  * Lapisan view 
     331    * View 
     332    * Template 
     333    * Layout 
     334  * Lapisan controller 
     335    * Front controller 
     336    * Action 
     337 
     338Tujuh skrip--begitu banyak file-file harus dibuka dan dimodifikasi setiap akan membuat halaman baru! Akan tetapi, symfony membuat semuanya mudah. Sementara mengambil kebaikan dari arsitektur MVC, symfony menerapkan arsitektur tersebut sehingga membuat pengembangan aplikasi dapat dipercepat dan tidak menyusahkan. 
     339 
     340Satu dari semuanya, front controller dan layout biasanya berlaku umum terhadap semua action-action dalam aplikasi. Anda boleh memiliki beberapa controller dan layout, tetapi yang diperlukan cukup satu. Front controller adalah komponen logika MVC murni, dan anda tidak akan perlu membuatnya sediri, karena symfony akan membuatnya untuk anda. 
     341 
     342Berita baik lainnya bahwa kelas-kelas pada lapisan model juga diciptakan otomatis, berdasarkan struktur data yang anda buat. Tugas ini ditangani oleh librari Propel, yang menyediakan kerangka-kerangka kelas dan penciptaan kode. Jika Propel menemukan batasan foreign key atau field-field tanggal, dia akan menyediakan pengakses khusus dan metode-metode pemutasian yang akan membuat manipulasi data seperti sebuah potong kue. Dan abstraksi database secara keseluruhan tidak nampak bagi anda, karena dia ditangani oleh komponen lain, yang disebut Creole. Jadi jika suatu ketika anda memutuskan untuk mengubah database, anda tidak perlu menulis kode lagi. Anda hanya perlu mengubah parameter konfigurasi. 
     343 
     344Dan yang terakhir adalah logika view dapat dengan mudah diterjemahkan menjadi file konfigurasi sederhana, tanpa perlu pengetahuan pemrograman. 
     345 
     346Figur 2-2 - Alur symfony 
     347 
     348![Symfony workflow](/images/book/F0202.png "Symfony workflow") 
     349 
     350Itu berarti bahwa daftar postingan seperti digambarkan pada contoh hanya membutuhkan tiga file agar bekerja di symfony, seperti ditunjukkan pada Listings 2-11, 2-12, dan 2-13. 
     351 
     352Listing 2-11 - Action `list`, pada `myproject/apps/myapp/modules/weblog/actions/actions.class.php` 
     353 
     354    [php] 
     355    <?php 
     356    class weblogActions extends sfActions 
     357    { 
     358      public function executeList() 
     359      { 
     360        $this->posts = PostPeer::doSelect(new Criteria()); 
     361      } 
     362    } 
     363 
     364    ?> 
     365 
     366Listing 2-12 - Template `list`, pada `myproject/apps/myapp/modules/weblog/templates/listSuccess.php` 
     367 
     368    [php] 
     369    <h1>List of Posts</h1> 
     370    <table> 
     371    <tr><th>Date</th><th>Title</th></tr> 
     372    <?php foreach ($posts as $post): ?> 
     373      <tr> 
     374        <td><?php echo $post->getDate() ?></td> 
     375        <td><?php echo $post->getTitle() ?></td> 
     376      </tr> 
     377    <?php endforeach; ?> 
     378    </table> 
     379 
     380Listing 2-13 - View `list`, pada `myproject/apps/myapp/modules/weblog/config/view.yml` 
     381 
     382    listSuccess: 
     383      metas: { title: List of Posts } 
     384 
     385Sebagai tambahan, anda masih perlu menentukan sebuah layout, seperti ditunjukkan pada Listing 2-14, tetapi layout tersebut dapat dipakai berkali-kali. 
     386 
     387Listing 2-14 - Layout, pada `myproject/apps/myapp/templates/layout.php` 
     388 
     389    [php] 
     390    <html> 
     391      <head> 
     392        <?php echo include_title() ?> 
     393      </head> 
     394      <body> 
     395        <?php echo $sf_data->getRaw('sf_content') ?> 
     396      </body> 
     397    </html> 
     398 
     399Dan hanya itu yang dibutuhkan. Itulah persisnya kode yang dibutuhkan untuk menampilkan halaman yang sama persis seperti pada skrip datar sebelumnya pada Listing 2-1. Sisanya (membuat semua komponen berkerja bersama) ditangani oleh symfony. Jika anda menghitung jumlah baris, anda akan melihat bahwa membuat daftar postingan dengan arsitektur MVC menggunakan symfony tidak membutuhkan lebih banyak waktu atau coding dibandingkan dengan menulis file datar. Sebaliknya, anda akan memperoleh banyak keuntungan, khususnya pengorganisasian kode yang bersih, daya pakai ulang, kefleksibelan, dan banyak lagi kesenangan lain. Dan sebagai hadiah, anda memperoleh halaman yang berstandar XHTML, kemampuan debugging, kemudahan konfigurasi, abstraksi database, perutean URL pintar, banyak lingkungan pengembangan, dan banyak lagi peralatan pengembangan yang lain. 
     400 
     401### Kelas-Kelas Inti Symfony 
     402 
     403Penerapan MVC pada symfony menggunakan beberapa kelas yang akan sering anda jumpai dalam buku ini: 
     404 
     405  * `sfController` adalah kelas controller. Tugasnya men-decode request dan melanjutkannya kepada action. 
     406  * `sfRequest` menyimpan semua elemen-elemen request (parameter-parameter, cookie-cokie, header-header, dll). 
     407  * `sfResponse` berisi header-header respon dan juga isi. Obyek ini sesungguhnya yang akan dikonversi sebagai respon HTML untuk dikirim kepada pengguna. 
     408  * Konteks tunggal (diambil dengan `sfContext::getInstance()`) menyimpan referensi ke semua obyek-obyek inti dan juga konfigurasi sekarang; yang dapat diakses dari manapun. 
     409 
     410Anda akan belajar banyak mengenai obyek-obyek ini pada Bab 6. 
     411 
     412Seperti anda lihat, semua kelas-kelas symfony menggunakan awalan `sf`, seperti juga variabel-variabel inti symfony dalam template. Hal ini bertujuan menghindari bentrokan nama dengan nama kelas dan variabel anda, dan membuat kelas-kelas inti dari framework tersosialiasi dan mudah dikenali. 
     413 
     414>**NOTE** 
     415>Di antara standarisasi kode yang digunakan oleh symfony, UpperCamelCase adalah standar yang digunakan untuk nama kelas dan nama variabel. Dua pengecualian: kelas-kelas inti symfony diawali `sf`, dalam bentuk huruf kecil, dan variabel-variabel yang ditemukan dalam template menggunakan sintaks dipisah garis bawah (underscore-separated). 
     416 
     417Organisasi Kode 
     418--------------- 
     419 
     420Sekarang anda mengetahui perbedaan komponen-komponen dari aplikasi symfony, anda mungkin kagum bagaimana kode tersebut diorganisir. Symfony mengorganisasi kode dalam sebuah struktur proyek dan meletakkan file-file proyek ke dalam struktur tree yang standar. 
     421 
     422### Struktur Proyek: Aplikasi, Modul, dan Action 
     423 
     424Dalam symfony, sebuah proyek terdiri dari kumpulan servis-servis dan operasi-operasi yang tersedia di bawah satu nama domain, yang berbagi obyek model yang sama. 
     425 
     426Di dalam sebuah proyek, operasi-operasi dikelompokkan secara logis ke dalam aplikasi. Sebuah aplikasi secara normal dapat berjalan independen dari aplikasi lain dalam satu proyek yang sama. Dalam kebanyakan kasus, sebuah proyek berisi dua aplikasi: satu untuk front-office dan satunya back-office, yang keduanya memakai database yang sama. Tetapi anda dapat memiliki sebuah proyek yang terdiri dari beberapa situs mini, dengan masing-masing situs sebagai aplikasi yang berbeda. Dengan catatan bahwa hyperlink antara aplikasi harus dalam bentuk absolut. 
     427 
     428Masing-masing aplikasi terdiri dari satu atau serangkaian modul. Sebuah modul biasanya mewakili sebuah halaman atau sekelompok halaman dengan fungsi yang mirip. Sebagai contoh, anda bisa memiliki modul `home`, `articles`, `help`, `shoppingCart`, `account`, dll. 
     429 
     430Modul menampung action-action, yang mewakili bermacam-macam action yang dapat dikerjakan dalam sebuah modul. Sebagai contoh, sebuah modul `shoppingCart` dapat memiliki action-action `add`, `show`, dan `update`. Umumnya, action-action dapat digambarkan sebagai kata. Bekerja dengan action hampir sama dengan mengerjakan halaman-halaman pada aplikasi web klasik, meskipun dua action dapat menghasilkan satu halaman yang sama (sebagai contoh, menambah sebuah komentar pada postingan weblog akan menampilkan ulang postingan tersebut dengan komentar yang baru dibuat). 
     431 
     432>**TIP** 
     433>Jika terlalu banyak tingkatan dalam proyek permulaan, sangat mudah untuk mengelompokkan semua action-action dalam sebuah modul tunggal, sehingga struktur file dapat dibuat tetap sederhana. Ketika aplikasi bertambah kompleks, sekarang waktunya untuk mengorganisir action ke dalam modul terpisah. Seperti disebutkan pada Bab 1, menulis ulang kode untuk memperbaiki struktur atau kemudahan memahaminya (tetapi tetap menjaga tingkah lakunya) disebut refactoring, dan anda akan banyak melakukannya ketika menerapkan prinsip RAD. 
     434 
     435Figur 2-3 menunjukkan sebuah contoh organisasi kode pada sebuah proyek weblog, dengan struktur project/application/module/action. Tetapi ingat struktur tree file sesungguhnya dari sebuah proyek akan berbeda dari contoh yang ditunjukkan pada gambar. 
     436 
     437Figur 2-3 - Contoh organisasi kode 
     438 
     439![Example of code organization](/images/book/F0203.png "Example of code organization") 
     440 
     441### Struktur Tree File 
     442 
     443Semua proyek-proyek web umumnya berbagi pakai banyak tipe isi, seperti berikut: 
     444 
     445  * Database, semisal MySQL atau PostgreSQL 
     446  * File-file statis (HTML, gambar-gambar, file-file JavaScript, stylesheet, dll) 
     447  * File-file yang diupload oleh pengguna dan administrator situs 
     448  * Kelas-kelas dan librari-librari PHP 
     449  * Librari-librari asing (skrip pihak ketiga) 
     450  * File-file batch (skrip untuk dijalankan dari baris perintah atau melalui tabel cron) 
     451  * File-file log (jejak yang dibuat oleh aplikasi dan/atau server) 
     452  * File-file konfigurasi 
     453 
     454Symfony menyediakan sebuah struktur tree file standar untuk mengorganisir semua isi-isi secara logis, yang konsisten dengan arsitektur yang digunakan (pola MVC dan pengelompokan project/application/module). Struktur tree file tersebut secara otomatis dibuat ketika menginisialiasi setiap proyek, aplikasi, atau modul. Tentunya, anda dapat mengkustomisasi sepenuhnya, untuk mengorganisasi ulang file-file dan direktori-direktori sesuai kebutuhan anda atau untuk menyesuaikan dengan persyaratan klien anda. 
     455 
     456#### Struktur Tree Dasar 
     457 
     458Direktori berikut ditemukan pada dasar dari sebuah proyek symfony: 
     459 
     460    apps/ 
     461      frontend/ 
     462      backend/ 
     463    batch/ 
     464    cache/ 
     465    config/ 
     466    data/ 
     467      sql/ 
     468    doc/ 
     469    lib/ 
     470      model/ 
     471    log/ 
     472    plugins/ 
     473    test/ 
     474      unit/ 
     475      functional/ 
     476    web/ 
     477      css/ 
     478      images/ 
     479      js/ 
     480      uploads/ 
     481 
     482Tabel 2-1 menggambarkan isi dari direktori-direktori tersebut. 
     483 
     484Tabel 2-1 - Direktori-Direktori Dasar 
     485 
     486Direktori  |  Deskripsi 
     487---------- | ------------ 
     488`apps/`    | Berisi sebuah direktori untuk setiap aplikasi dalam proyek (umumnya, `frontend` dan `backend` untuk front dan back office). 
     489`batch/`   | Berisi skrip-skrip PHP yang dipanggil dari baris perintah atau oleh sebuah skeduler, untuk menjalankan proses-proses batch. 
     490`cache/`   | Berisi versi caache dari konfigurasi, dan (jika anda mengaktifkannya) versi cache dari action-action dan template-template proyek. Mekanisme cache (detailnya ada pada Bab 12) menggunakan file-file tersebut untuk mempercepat respon pada request web. Setiap aplikasi akan memiliki sub direktori, yang berisi file PHP pra-proses dan file-file HTML. 
     491`config/`  | Menyimpan konfigurasi umum pada proyek. 
     492`data/`    | Di sini, anda dapat menyimpan file-file data proyek, seperti skema database, file-file SQL untuk membuat tabel-tabel, atau bahkan file database SQLite. 
     493`doc/`     | Menyimpan dokumentasi proyek, termasuk dokumentasi anda sendiri atau dokumentasi yang dibuat dengan PHPdoc. 
     494`lib/`     | Didedikasikan untuk kelas-kelas asing atau librai-librari. Di sini, anda dapat menambah kode yang dibutuhkan agar dapat digunakan bersama di antara aplikasi-aplikasi. Sub direktori `model/` menyimpan obyek model dari proyek (dijelaskan pada Bab 8). 
     495`log/`     | Menyimpan file-file log yang dibuat langsung oleh symfony. Dapat juga berisi file-file log server web, file-file log database, atau file-file log dari bagian lain proyek. Symfony membuat sebuah file log per aplikasi dan per lingkungan (file-file log didiskusikan pada Bab 16). 
     496`plugins/` | Menyimpan plug-ins yang terpasang dalam aplikasi (plug-ins didiskusikan pada Bab 17). 
     497`test/`    | Berisi pengujian unit dan fungsionalitas yang ditulis menggunakan PHP dan kompatibel dengan framework pengujian symfony (didiskusikan pada Bab 15). Sewaktu setup proyek, symfony otomatis menambahkan beberapa potongan-potongan pengujian dasar. 
     498`web/`     | Root server web. File yang hanya dapat diakses dari Internet diletakkan dalam direktori ini. 
     499 
     500#### Struktur Tree Aplikasi 
     501 
     502Struktur tree dari semua direktori aplikasi adalah sama: 
     503 
     504    apps/ 
     505      [application name]/ 
     506        config/ 
     507        i18n/ 
     508        lib/ 
     509        modules/ 
     510        templates/ 
     511          layout.php 
     512          error.php 
     513          error.txt 
     514 
     515Tabel 2-2 menggambarkan sub direktori aplikasi. 
     516 
     517Tabel 2-2 - Subdirektori Aplikasi 
     518 
     519Direktori    | Deskripsi 
     520------------ | ----------- 
     521`config/`    | Menyimpan sejumlah file konfigurasi YAML. Kebanyakan adalah konfigurasi aplikasi, yang berbeda dari parameter default yang dapat ditemukan dalam framework. Perlu dicatat bahwa parameter default masih dapat diambil-alih jika diperlukan di sini. Anda akan belajar banyak tentang konfigurasi aplikasi pada Bab 5. 
     522`i18n/`      | Berisi file-file yang digunakan untuk internasionalisasi aplikasi--kebanyakan file-file translasi antar muka (Bab 13 berhubungan dengan internasionalisasi). And dapat melewati direktori ini jika anda memilih menggunakan database untuk internasionalisasi. 
     523`lib/`       | Berisi kelas-kelas dan librari-librari yang spesifik terhapad aplikasi. 
     524`modules/`   | Menyimpan semua modul-modul yang berisi fitur-fitur aplikasi. 
     525`templates/` | Daftar template-template global aplikasi--yang dipakai bersama oleh semua modul-modul. Secara default, berisi sebuah file `layout.php`, yang merupakan layout utama dimana template dari modul nantinya akan disisipkan. 
     526 
     527>**CATATAN** 
     528>Direktori `i18n/`, `lib/`, dan `modules/` masih kosong pada sebuah aplikasi baru. 
     529 
     530Kelas-kelas dari suatu aplikasi tidak dapat mengakses metode-metode atau atribut-atribut dari aplikasi lain dalam satu proyek yang sama. Juga perlu dicatat bahwa hyperlink antara aplikasi dalam satu proyek yang sama harus dalam bentuk absolut. Anda perlu mengingat batasan ini selama inisialisasi, ketika anda memutuskan untuk membagi proyek anda ke dalam aplikasi-aplikasi. 
     531 
     532#### Struktur Tree Modul 
     533 
     534Setiap aplikasi berisi satu atau beberapa modul. Setiap modul memiliki subdirektori sendiri pada direktori `modules`, dan nama direktori tersebut ditentukan ketika setup. 
     535 
     536Berikut ini struktur tree umum pada sebuah modul: 
     537 
     538    apps/ 
     539      [application name]/ 
     540        modules/ 
     541          [module name]/ 
     542              actions/ 
     543                actions.class.php 
     544              config/ 
     545              lib/ 
     546              templates/ 
     547                indexSuccess.php 
     548              validate/ 
     549 
     550Tabel 2-3 menggambarkan subdirektori pada modul. 
     551 
     552Tabel 2-3 - Subdirektori-Subdirektori Modul 
     553 
     554Direktori    | Deskripsi 
     555------------ | ------------ 
     556`actions/`   | Umumnya berisi kelas tunggal dengan nama `actions.class.php`, yang mana anda dapat menyimpan semua action-action dari modul tersebut. Anda juga dapat menulis action-action yang berbeda dari modul tersebut pada file-file yang terpisah. 
     557`config/`    | Dapat berisi file-file konfigurasi kustom yang berisi parameter-paramter modul lokal. 
     558`lib/`       | Menyimpan kelas-kelas dan librari-librari khusus untuk modul. 
     559`templates/` | Berisi template-template yang berhubungan dengan action-action pada modul. Template default, dinamakan `indexSuccess.php`, dibuat ketika setup modul. 
     560`validate/`  | Didedikasikan untuk file-file konfigurasi yang digunakan pada waktu validasi form (didiskusikan pada Bab 10). 
     561 
     562>**CATATAN** 
     563>Direktori `config/`, `lib/`, dan `validate/` masih kosong pada sebuah modul yang baru. 
     564 
     565#### Struktur Tree Web 
     566 
     567Ada sedikit batasan untuk direktori `web`, yang mana direktori ini berisi file-file yang dapat diakses secara umum. Mengikuti sedikit konvensi penamaan dasar yang menyediakan tingkah laku default dan jalan pintas berguna pada template-template. Berikut sebuah contoh struktur direktori `web`: 
     568 
     569    web/ 
     570      css/ 
     571      images/ 
     572      js/ 
     573      uploads/ 
     574 
     575Secara konvensional, file-file statis didistribusikan pada direktori yang terdaftar pada Tabel 2-4. 
     576 
     577Table 2-4 - Subdirektori Web Umum 
     578 
     579Direktori  | Deskripsi 
     580---------- | ----------- 
     581`css/`     | Berisi stylesheet dengan ekstensi `.css`. 
     582`images/`  | Berisi gambar-gambar dengan format `.jpg`, `.png`, atau `.gif`. 
     583`js/`      | Menyimpan file-file JavaScript dengan exstensi `.js`. 
     584`uploads/` | Berisi file-file yang diupload oleh pengguna. Meskipun direktori ini biasanya berisi gambar-gambar, namum berbeda dengan direktori images sehingga sinkronisasi antara server pengembangan dan produksi tidak mempengaruhi gambar-gambar yang diupload. 
     585 
     586>**NOTE** 
     587>Meskipun sangat direkomendasikan untuk meggunakan struktur tree standar, sangat dimungkinkan mengubahnya sesuai kebutuhan spesifik, sehingga memungkinkan sebuah proyek dapat dijalankan pada server dengan aturan struktur tree dan konvensi pengkodean yang berbeda. Lihat Bab 19 untuk informasi lebih jauh tentang memodifikasi struktur tree file. 
     588 
     589Instrumen-Instrumen Umum 
     590------------------------ 
     591 
     592Ada sedikit teknik yang digunakan berulang-ulang dalam symfony, dan anda akan cukup sering menemuinya dalam buku ini dan dalam proyek anda sendiri. Hal ini meliputi parameter holder, konstanta, dan autoloading kelas. 
     593 
     594### Parameter Holder 
     595 
     596Banyak dari kelas-kelas symfony yang berisi parameter holder. Ini adalah cara yang meyakinkan untuk membungkus attribut-atribut dengan metode getter dan setter yang bersih. Sebagai contoh, kelas sfResponse menyimpan sebuah parameter holder yang mana anda dapat mengambilnya dengan memanggil metode `getParameterHolder()`. Setiap parameter holder menyimpan data dengan cara yang sama, seperti diilustrasikan pada Listing 2-15. 
     597 
     598Listing 2-15 - Menggunakan Parameter Holder `sfResponse` 
     599 
     600    [php] 
     601    $response->getParameterHolder()->set('foo', 'bar'); 
     602    echo $response->getParameterHolder()->get('foo'); 
     603     => 'bar' 
     604 
     605Kebanyakan kelas-kelas yang menggunakan parameter holder menyediakan metode-metode perantara dengan tujuan memperpendek kode yang dibutuhkan pada operasi-operasi get/set. Hal ini juga berlaku pada obyek `sfResponse`, sehingga anda dapat melakukan hal yang sama dengan Listing 2-15 dengan kode pada Listing 2-16. 
     606 
     607Listing 2-16 - Menggunakan Metode Perantara Parameter Holder `sfResponse` 
     608 
     609    [php] 
     610    $response->setParameter('foo', 'bar'); 
     611    echo $response->getParameter('foo'); 
     612     => 'bar' 
     613 
     614Getter parameter holder menerima nilai default sebagai argumen kedua. Hal ini menyediakan mekanisme fallback yang lebih ringkas dibandingkan menggunakan statemen kondisonal. Lihat Listing 2-17 sebagai contohnya. 
     615 
     616Listing 2-17 - Menggunakan Nilai Default Getter Parameter Holder 
     617 
     618    [php] 
     619    // Parameter 'foobar' belum ditentukan, sehingga getter mengembalikan nilai kosong 
     620    echo $response->getParameter('foobar'); 
     621     => null 
     622 
     623    // Nilai default dapat dipakai dengan meletakkan getter dalam sebuah kondisi 
     624    if ($response->hasParameter('foobar')) 
     625    { 
     626      echo $response->getParameter('foobar'); 
     627    } 
     628    else 
     629    { 
     630      echo 'default'; 
     631    } 
     632     => default 
     633 
     634    // Tetapi lebih cepat menggunakan argumen kedua getter untuk melakukannya daripada sebelumnya 
     635    echo $response->getParameter('foobar', 'default'); 
     636     => default 
     637 
     638Parameter holder bahkan mendukung namespace. Jika anda menentukan argumen ketiga pada setter atau getter, argumen tersebut digunakan sebagai namespace, dan parameter hanya akan berlaku dalam namespace tersebut. Listing 2-18 menunjukkan contohnya. 
     639 
     640Listing 2-18 - Menggunakan Namespace Parameter Holder `sfResponse` 
     641 
     642    [php] 
     643    $response->setParameter('foo', 'bar1'); 
     644    $response->setParameter('foo', 'bar2', 'my/name/space'); 
     645    echo $response->getParameter('foo'); 
     646     => 'bar1' 
     647    echo $response->getParameter('foo', null, 'my/name/space'); 
     648     => 'bar2' 
     649 
     650Dan tentunya, anda dapat menambahkan sebuah parameter holder pada kelas-kelas anda sendiri untuk mendapatkan keuntungan dari fasilitias sintaksnya. Listing 2-19 menunjukkan bagaimana membuat sebuah kelas dengan parameter holder. 
     651 
     652Listing 2-19 - Menambahkan Parameter Holder ke Suatu Kelas 
     653 
     654    [php] 
     655    class MyClass 
     656    { 
     657      protected $parameter_holder = null; 
     658 
     659      public function initialize ($parameters = array()) 
     660      { 
     661        $this->parameter_holder = new sfParameterHolder(); 
     662        $this->parameter_holder->add($parameters); 
     663      } 
     664 
     665      public function getParameterHolder() 
     666      { 
     667        return $this->parameter_holder; 
     668      } 
     669    } 
     670 
     671### Konstanta 
     672 
     673Anehnya, anda hanya akan menjumpai sedikit konstanta dalam symfony. Hal ini dikarenakan konstanta memiliki kekurangan besar dalam PHP: anda tidak dapat mengubah nilainya sekali anda mendefinisikannya. Sehingga symfony menggunakan obyek konfigurasinya sendiri, yang dinamakan sfConfig, yang berfungsi menggantikan konstanta. Kelas ini menyediakan metode statis yang dapat digunakan untuk mengakses parameter dari manapun. Listing 2-20 mendemonstrasikan penggunaan metode-metode kelas sfConfig. 
     674 
     675Listing 2-20 - Menggunakan Metode Kelas `sfConfig` daripada Konstanta 
     676 
     677    [php] 
     678    // Daripada menggunakan konstanta PHP, 
     679    define('SF_FOO', 'bar'); 
     680    echo SF_FOO; 
     681    // Symfony mennggunakan obyek sfConfig 
     682    sfConfig::set('sf_foo', 'bar'); 
     683    echo sfConfig::get('sf_foo'); 
     684 
     685Metode-metode sfConfig mendukung nilai-nilai default, dan anda dapat memanggil metode sfConfig::set() lebih dari sekali pada parameter yang untuk mengubah nilainya. Bab 5 mendiskusikan metode `sfConfig` dengan lebih detail. 
     686 
     687### Autoloading Kelas 
     688 
     689Secara klasik, ketika anda menggunakan metode dari sebuah kelas atau ketika membuat obyek dalam PHP, anda perlu menyertakan pendefinisian kelas sebelumnya. 
     690 
     691    [php] 
     692    include 'classes/MyClass.php'; 
     693    $myObject = new MyClass(); 
     694 
     695Tetapi pada proyek yang besar dengan banyak kelas-kelas dengan struktur direktori yang dalam, mengingat semua file-file kelas dan menyertakan path file kelas tersebut akan banyak membutuhkan waktu. Dengan menyediakan sebuah fungsi `__autoload()` (atau sebuah fungsi `spl_autoload_register()`), symfony membuat statemen `include` tidak dibutuhkan lagi, dan anda dapat menulis langsung: 
     696 
     697    [php] 
     698    $myObject = new MyClass(); 
     699 
     700Symfony kemudian akan mencari definisi `MyClass` pada semua file dengan akhiran `php` pada salah satu direktori `lib/` proyek. Jika definisi kelas ditemukan, symfony kemudian otomatis menyertakannya. 
     701 
     702Jadi jika anda menyimpan semua kelas-kelas pada direktori lib/, anda tidak perlu lagi menyertakan kelas. Itulah mengapa proyek-proyek symfony umumnya tidak mengandung statemen-statemen `include` atau `require`. 
     703 
     704>**CATATAN** 
     705>Untuk performa yang lebih baik, autoloading symfony memeriksa sebuah daftar direktori (didefinisikan pada file konfigurasi internal) sewaktu request yang pertama. Kemudian semua kelas-kelas pada direktori tersebut didaftarkan dan disimpan pada file PHP sebagai array assosatif. Dengan cara tersebut, request selanjutnya tidak membutuhkan pemeriksaan direktori lagi. Inilah mengapa anda perlu membersihkan cache setiap kali anda menambah atau memindahkan sebuah file kelas dalam proyek dengan memanggil perintah `symfony clear-cache`. Anda akan banyak belajar lebih banyak tentang cache pada Bab 12, dan tentang konfigurasi autoloading pada Bab 19. 
     706 
     707Kesimpulan 
     708---------- 
     709 
     710Menggunakan framework MVC memaksa anda untuk membagi dan mengorganisasi kode menurut konvensi framework tersebut. Kode presentasi berada pada view, kode manipulasi data berada pada model, dan logika manipulasi request berada pada controller. Hal ini membuat aplikasi dengan kedua pola MVC tersebut sangat membantu dan juga membatasi. 
     711 
     712Symfony adalah sebuah framework MVC yang ditulis menggunakan PHP 5. Strukturnya didesain untuk mendapatkan yang terbaik dari pola MVC, tetapi dengan kemudahan penggunaannya. Dengan dukungan kepandaian yang bermacam-macam dan dapat dikonfigurasi, symfony cocok digunakan untuk semua proyek-proyek aplikasi web. 
     713 
     714Sekarang anda mengerti teori yang mendasari di belakang symfoni, anda hampir siap untuk membangun aplikasi yang pertama. Tetapi sebelumnya, anda perlu memasang dan menjalankan symfony pada server pengembangan anda. 
     715 
     716}}}