PHP İle Vue.js (v2.x) Kullanımı (Başlangıç Seviyesi)

Vue.js ile ilgili yazılara epey zamandır bir ara vermiş, farklı konuları önceliklendirmiştim. Geçtiğimiz günlerde vue-cli ile birlikte php dosyalarının nasıl çalıştırılabileceğine dair bir soru aldım.

AA

Sorunun devamında, veritabanına dair de işlemlerden bahsedildiği için süreci parçalara böldüm. Hem Vue.js’e dair bir tekrar olması hem de MySQL veritabanı işlemleriyle Vue.js örneklerinin birleştirilmesinin eğlenceli olacağını düşünerek 3 yazı ele alacağım. İlk konumuz ve en basit olanı Vue ve PHP’i beraber çalıştırmak.

PHP İçeriğinde Vue.js’e Yer Vermek

Öncelikle, belirtmem gereken konu bu yazıdaki PHP ifadesinin var olan örnekte çok da önemli bir husus olmaması. Çünkü, ilgili işlem bir HTML dosyası olsa da aynı şekilde gerçekleşecektir. İlgili işlemin tek farkı PHP dosyasının çalışabilmesi için Apache veya Nginx gibi bir HTTP sunucusuna ihtiyacınızın olması. Daha önce yayınladığım birkaç yazıyı bu maksatla öne çıkarmak isterim.

İşlemlerimizi Bulma CSS HTML boilerplate ile başlatalım ve dosyayı index.php adı ile kayıt edelim.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hello Bulma!</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css">
    <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
  </head>
  <body>
  <section class="section">
    <div class="container">
      <h1 class="title">
        Hello World
      </h1>
      <p class="subtitle">
        My first website with <strong>Bulma</strong>!
      </p>
    </div>
  </section>
  </body>
</html>

İlgili koda klasik vue entegrasyonumuzu yapalım. Aşağıda Vue v2.x için kullanabileceğiniz CDN yolunu görebilirsiniz.

<!-- Vue v2.x -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

Sonrasında, bildiğimiz üzere, Vue instance tanımlamalı ve bir elementi (Örneğin, app) işaretlemeliyiz.

<script>
// Vue v2.x
new Vue({
  el: "#app",
  data: {
    message: 'Hello Vue!'
  }
});
</script>

Son durumda index.php içeriğimiz aşağıdaki görüntüye yakın bir hale gelmeli.

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Hello Bulma!</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css" />
    <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
  </head>
  <body>

    <section class="section">
      <div id="app" class="container">
        <h1 class="title" v-text="message"></h1>
        <p class="subtitle" v-html="subtitle"></p>
      </div>
    </section>

    <script src="https://unpkg.com/vue/dist/vue.js"></script>

    <script>
      // Vue v2.x
      new Vue({
        el: "#app",
        data: {
          message: 'Hello Vue!',
          subtitle: 'My first website with <strong>Bulma</strong>!'
        }
      });
    </script>

  </body>
</html>

macOS ortamında kolaylıkla PHP dosyalarını çalıştırabilmekteydik. Dolayısıyla, ilgili dosyası httpd.conf içeriğinde tanımlı web root directory’e taşımamız yeterli.

cat /etc/apache2/httpd.conf | grep ^DocumentRoot

Ardından, localhost üzerinden index.php dosyasını görüntüleyebiliriz. Bu aşamaya kadar php dosyasının bizim için sağladığı ek bir avantaj söz konusu olmadı. Örneği çeşitlendirmek adına HTML içeriğini biraz zenginleştirelim, component’ler ve routing ile basit bazı tanımlar ekleyelim. Klasikleşen edebiyat eserlerinden bazı pasajlara yer verdiğim örneğin son hali aşağıdaki gibidir.

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>Vue + PHP</title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css" />
    <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>

    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

  </head>
  <body>
  <div id="app">

    <section class="section">
      <div class="container">

        <nav class="navbar" role="navigation" aria-label="dropdown navigation">
          <h1 class="title"><a href="/" v-text="maintitle"></a></h1>
          <div class="navbar-end">
            <div class="navbar-item has-dropdown is-hoverable">
              <a class="navbar-link">Menu</a>
              <div class="navbar-dropdown">
                <router-link class="navbar-item" to="/">Go to Home</router-link>
                <router-link class="navbar-item" to="/foo">Go to Foo</router-link>
                <router-link class="navbar-item" to="/bar">Go to Bar</router-link>
                <hr class="navbar-divider">
                <a class="navbar-item" @click="getMessage()">Get new one!</a>
              </div>
            </div>
          </div>
        </nav>

      </div>
    </section>

    <router-view :title="title" :subtitle="subtitle" :passage="passage"></router-view>

  </div>

  <script>
    const Section = {
      props: ['title', 'subtitle', 'passage'],
      template: `
        <div>
          <section class="hero is-light">
            <div class="hero-body">
              <div class="container">
                <h2 class="title">{{ this.title }}</h2>
                <h3 class="subtitle">{{ this.subtitle }}</h3>
              </div>
            </div>
          </section>

          <section class="section">
            <div class="container">
              <p>{{ this.passage }}</p>
            </div>
          </section>
        </div>
      `
    };

    const Default = {
      template: `<component-section :title="title" :subtitle="subtitle" :passage="passage" />`,
      components: {
        'component-section': Section
      },
      data() {
        return {
          title: 'Nineteen Eighty-Four',
          subtitle: 'by George Orwell',
          passage: 'The Ministry of Truth, which concerned itself with news, entertainment, education and the fine arts. The Ministry of Peace, which concerned itself with war. The Ministry of Love, which maintained law and order. And the Ministry of Plenty, which was responsible for economic affairs. Their names, in Newspeak: Minitrue, Minipax, Miniluv and Miniplenty.'
        }
      }
    };

    const Foo = {
      template: `<component-section :title="title" :subtitle="subtitle" :passage="passage" />`,
      components: {
        'component-section': Section
      },
      data() {
        return {
          title: 'In Search of Lost Time',
          subtitle: 'Marcel Proust',
          passage: 'We believe that we can change the things around us in accordance with our desires—we believe it because otherwise we can see no favourable outcome. We do not think of the outcome which generally comes to pass and is also favourable: we do not succeed in changing things in accordance with our desires, but gradually our desires change. The situation that we hoped to change because it was intolerable becomes unimportant to us. We have failed to surmount the obstacle, as we were absolutely determined to do, but life has taken us round it, led us beyond it, and then if we turn round to gaze into the distance of the past, we can barely see it, so imperceptible has it become.'
        }
      }
    };

    const Bar = {
      template: `<component-section :title="title" :subtitle="subtitle" :passage="passage" />`,
      components: {
        'component-section': Section
      },
      data() {
        return {
          title: 'Death of a Salesman',
          subtitle: 'Arthur Miller',
          passage: 'When today fails to offer the justification for hope, tomorrow becomes the only grail worth pursuing.'
        }
      }
    };

    const routes = [
        { path: '/foo', component: Foo },
        { path: '/bar', component: Bar },
        { path: '*', component: Default }
    ];

    const router = new VueRouter({
        mode: 'history',
        routes: routes
    });

    // Vue v2.x
    const app = new Vue({
      el: "#app",
      router: router,
      data() {
        return {
          maintitle: 'Classic Novels',
          title: null,
          subtitle: null,
          passage: null,
          showmodal: false,
          newpassage: []
        }
      },
      methods: {
        getMessage(){
          axios
            .get('api.php')
            .then(function (response) {
                console.log(response.data)
                app.$data.newpassage = response.data
              })
              .catch(function (error) {
                console.log(error);
          });
        }
      }
    }).$mount('#app');
</script>

  </body>
</html>

Peki, PHP bunun neresinde? Aslında istediğimiz gibi PHP kodlarını bu yapı içerisine yerleştirebiliriz. Benim özellikle vurgulamak istediğim işlem axios ile POST işlemi gerçekleştirmek ve dönen değeri almak. Bunun için api.php adında yeni bir dosya oluşturdum ve içeriğini şöyle tanımladım.

<?php
header("Content-type: application/json");
const newPassage = [
  "title" => "Catch-22",
  "subtitle" => "Joseph Heller",
  "passage" => "Like Olympic medals and tennis trophies, all they signified was that the owner had done something of no benefit to anyone more capably than everyone else."
];
echo json_encode(newPassage);
?>

Görüldüğü üzere sayfa bir json dökümanı gibi görüntüleniyor. İçeriğinde ise yine diğer sayfada olduğu gibi bir kitap alıntısı mevcut. Postman ile api.php dosyasını test edelim. Birazdan aynı işlemi index.php içeriğinde, bir method aracılığıyla da gerçekleştireceğiz.

Postman Post Request

Console’u açıp, sayfadaki menü içeriğinde yer alan “Get a new one!” linkini tıkladığınızda api.php‘e bir POST request gerçekleştirmekteyiz. Ardından içeriğinde bir kitap alıntısı olan JSON data’sı dönmekte ve dönen cevabı console.log() ile dökmekteyiz.

Axios Post Request

Özellikle bu işlemi seçmemin nedeni, Vue.js ve PHP İle MySQL Database İşlemleri başlıklı yazı için bir ön alıştırma gerekliliğiydi. Artık bir sonraki aşamaya geçebiliriz. Unutmadan, yukarıda Vue v2.x ile geliştirilen örneğe ait kodları GitLab Vue.js ve PHP Örneği snippet'ı olarak da görüntüleyebilirsiniz. Daha fazla örneğe ise Vue-Examples üzerinden ulaşabilirsiniz.