PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Vue.js for the PHP developer – Options API, Composition API, Magento REST communication

by Henryk Tews / Tuesday, 08 September 2020 / Published in JavaScript

As a PHP developer you have probably had some contact with jQuery and maybe a bit of plain JS. Vue.js is the next step – a reactive framework that increasingly appears in e-commerce projects as a frontend layer for headless Magento or as a replacement for the older knockout.js. I show the basics from the perspective of someone who thinks in PHP day to day.

Why Vue rather than React or Angular?

React requires thinking in JSX and has a steeper learning curve. Angular is a full framework with an elaborate architecture – overkill for small components. Vue sits in the middle: simple template syntax close to HTML, built-in reactivity without ceremony, good documentation. For a PHP developer who is not a frontend developer by choice, Vue is the gentlest entry into the world of components.

Basic Vue 3 component structure – Options API

// Vue 3 component - Options API (simpler for PHP newcomers)
const ProductCard = {
    // Component data - equivalent to PHP class properties
    data() {
        return {
            quantity: 1,
            addedToCart: false,
        };
    },

    // Properties passed from outside - equivalent to method parameters
    props: {
        product:     { type: Object, required: true },
        maxQuantity: { type: Number, default: 99 },
    },

    // Computed properties - equivalent to PHP getters
    computed: {
        totalPrice() {
            return (this.product.price * this.quantity).toFixed(2);
        },
        canAddMore() {
            return this.quantity < this.maxQuantity;
        },
    },

    // Methods - equivalent to PHP class methods
    methods: {
        addToCart() {
            if (!this.canAddMore) return;
            this.$emit('add-to-cart', { productId: this.product.id, quantity: this.quantity });
            this.addedToCart = true;
        },
        increment() { if (this.quantity < this.maxQuantity) this.quantity++; },
        decrement() { if (this.quantity > 1) this.quantity--; },
    },

    template: `
        <div class="product-card">
            <h3>{{ product.name }}</h3>
            <p>{{ totalPrice }} PLN</p>
            <div>
                <button @click="decrement" :disabled="quantity <= 1">-</button>
                <span>{{ quantity }}</span>
                <button @click="increment" :disabled="!canAddMore">+</button>
            </div>
            <button @click="addToCart" :class="{ 'btn-success': addedToCart }">
                {{ addedToCart ? 'Added!' : 'Add to cart' }}
            </button>
        </div>
    `,
};

Vue directives - equivalents from PHP

Vue directive What it does PHP/Twig analogy
{{ variable }} Outputs a value <?= $var ?>
v-if="condition" Conditional rendering {% if condition %}
v-for="item in items" Loop over array {% for item in items %}
v-model="variable" Two-way input binding No direct equivalent
@click="method" Handle click event No equivalent (this is JS)
:class="object" Dynamic CSS classes class="{{ condition ? 'a' : 'b' }}"

Communicating with the Magento API from Vue

const ProductList = {
    data() {
        return { products: [], loading: false, error: null };
    },

    async mounted() {
        await this.fetchProducts();
    },

    methods: {
        async fetchProducts() {
            this.loading = true;
            this.error   = null;
            try {
                const response = await fetch(
                    '/rest/V1/products?searchCriteria[pageSize]=12&searchCriteria[currentPage]=1',
                    { headers: { 'Content-Type': 'application/json' } }
                );
                if (!response.ok) throw new Error('API error: ' + response.status);
                const data   = await response.json();
                this.products = data.items;
            } catch (err) {
                this.error = err.message;
            } finally {
                this.loading = false;
            }
        },
    },

    template: `
        <div>
            <div v-if="loading">Loading...</div>
            <div v-else-if="error">Error: {{ error }}</div>
            <product-card v-else v-for="product in products" :key="product.id" :product="product" />
        </div>
    `,
};

Composition API - more PHP-like approach

import { ref, computed, onMounted } from 'vue';

export default {
    props: ['productId'],

    setup(props) {
        const product  = ref(null);  // ref() = reactive class property
        const quantity = ref(1);
        const loading  = ref(false);

        const totalPrice = computed(() =>    // computed = getter
            product.value ? (product.value.price * quantity.value).toFixed(2) : '0.00'
        );

        async function loadProduct() {
            loading.value    = true;
            const response   = await fetch('/rest/V1/products/' + props.productId);
            product.value    = await response.json();
            loading.value    = false;
        }

        onMounted(loadProduct);  // lifecycle hook

        return { product, quantity, totalPrice, loading };
    },
};

Summary

Vue.js has a gentle learning curve - a component with Options API is structurally similar to a PHP class with properties and methods. Reactivity (automatic view updates when data changes) is the biggest mindset shift from classic PHP, where rendering is a one-time process. If you plan to work with Vue Storefront or build interactive components for a Magento shop - Vue is worth a few weekends.

About Henryk Tews

What you can read next

TypeScript for the PHP developer – types, interfaces, generics, async/await
React.js – JSX, useState, useEffect, custom hooks, comparison with Vue
Next.js for the PHP developer – SSR, Server Components, GraphQL with Magento

© 2026 Created by

TOP
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Always active
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
Zobacz preferencje
  • {title}
  • {title}
  • {title}