Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sonata Vue Laravel Package

alxishin/sonata-vue

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require alxishin/sonata-vue
    

    Ensure your project meets the requirements (PHP 8.1+, Symfony 4.4/5.0/6.0, SonataAdminBundle 4.12+).

  2. Enable the Bundle Add to config/bundles.php:

    return [
        // ...
        Alxishin\SonataVueBundle\SonataVueBundle::class => ['all' => true],
    ];
    
  3. Configure Vue Integration Update config/packages/sonata_admin.yaml to include Vue-specific settings:

    sonata_admin:
        vue:
            enabled: true
            # Optional: Custom Vue build path (if not using default)
            build_path: 'assets/vue/build.js'
    
  4. First Use Case: Basic Admin Page with Vue Extend a Sonata admin class to enable Vue reactivity:

    use Sonata\AdminBundle\Admin\AbstractAdmin;
    use Sonata\AdminBundle\Datagrid\DatagridMapper;
    use Sonata\AdminBundle\Form\FormMapper;
    use Sonata\AdminBundle\Show\ShowMapper;
    
    class PostAdmin extends AbstractAdmin
    {
        protected function configureDatagridFilters(DatagridMapper $filter): void
        {
            $filter->add('title');
        }
    
        protected function configureFormFields(FormMapper $form): void
        {
            $form->add('title');
        }
    
        protected function configureShowFields(ShowMapper $show): void
        {
            $show->add('title');
        }
    
        // Enable Vue for this admin
        public function getVueOptions(): array
        {
            return [
                'reactive_fields' => ['title'], // Fields to make reactive
                'custom_components' => [
                    'post_editor' => '@SonataVueBundle/Component/post_editor.html.twig',
                ],
            ];
        }
    }
    
  5. Verify Vue Integration Check the generated admin page (e.g., /admin/app/post). Open browser dev tools (F12) and confirm Vue is loaded and reactive fields are bound.


Implementation Patterns

Common Workflows

1. Reactive Forms with Sonata

Use getVueOptions() to bind Sonata form fields to Vue:

public function getVueOptions(): array
{
    return [
        'reactive_fields' => ['price', 'stock'], // Sync with Vue
        'watchers' => [
            'price' => 'updateStockPrice', // Call JS method on change
        ],
    ];
}

Vue Component Example (resources/assets/vue/components/StockManager.vue):

<template>
    <div>
        <input v-model="price" @change="updateStockPrice">
        <p>Stock Price: {{ computedPrice }}</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            price: this.$options.data.price,
        };
    },
    computed: {
        computedPrice() {
            return this.price * 1.1; // Example logic
        },
    },
    methods: {
        updateStockPrice() {
            // Call Symfony controller via API
            axios.post('/api/stock/update', { price: this.price });
        },
    },
};
</script>

2. Custom Components

Create reusable Vue components for Sonata admins:

  • Step 1: Define a Twig template (templates/components/my_component.html.twig):
    <div id="my-component" data-sonata-vue-component="true">
        <input v-model="value" @input="updateValue">
    </div>
    
  • Step 2: Register in getVueOptions():
    public function getVueOptions(): array
    {
        return [
            'custom_components' => [
                'my_component' => '@SonataVueBundle/Component/my_component.html.twig',
            ],
        ];
    }
    
  • Step 3: Use in admin templates:
    {{ sonata_vue_component('my_component', { value: entity.someField }) }}
    

3. API-Driven Workflows

Fetch data via Symfony’s API platform or custom controllers:

<script>
export default {
    mounted() {
        this.fetchData();
    },
    methods: {
        fetchData() {
            axios.get('/api/posts')
                .then(response => {
                    this.posts = response.data;
                });
        },
    },
};
</script>

4. Dynamic Datagrid with Vue

Override the datagrid to use Vue for filtering/sorting:

public function getVueOptions(): array
{
    return [
        'datagrid_vue' => true,
        'datagrid_filters' => [
            'custom_filter' => [
                'type' => 'text',
                'label' => 'Custom Filter',
            ],
        ],
    ];
}

Vue Filter Component (resources/assets/vue/datagrid_filters.js):

Vue.component('custom-filter', {
    template: `
        <input v-model="value" @input="applyFilter">
    `,
    methods: {
        applyFilter() {
            this.$emit('filter', this.value);
        },
    },
});

Integration Tips

Symfony <-> Vue Communication

  • Pass Data to Vue: Use Twig variables in templates:

    {{ sonata_vue_init({
        'initialData': {
            'posts': app.posts,
            'user': app.user,
        }
    }) }}
    

    Access in Vue:

    data() {
        return {
            posts: this.$options.data.initialData.posts,
        };
    }
    
  • Call Symfony Controllers: Use Symfony’s router in Vue:

    const route = this.$options.data.routes.update;
    axios.post(route, { id: 1, title: 'New Title' });
    

    Pass routes via Twig:

    {{ sonata_vue_init({
        'routes': {
            'update': path('admin_post_update', { id: entity.id })
        }
    }) }}
    

Build Process

  • Custom Vue Build: Configure Webpack Encore to bundle Vue separately:
    // webpack.config.js
    Encore
        .enableVueLoader()
        .addEntry('sonata-vue', './assets/vue/sonata-vue.js')
        .setOutputPath('public/build/')
        .setPublicPath('/build');
    
    Update SonataVueBundle config:
    sonata_admin:
        vue:
            build_path: '/build/sonata-vue.js'
    

Security

  • CSRF Protection: Include CSRF token in Vue requests:
    axios.defaults.headers.common['X-CSRF-Token'] = document.querySelector('meta[name="csrf-token"]').content;
    
    Add to Twig:
    <meta name="csrf-token" content="{{ csrf_token() }}">
    

Gotchas and Tips

Pitfalls

  1. Vue Version Mismatch

    • Issue: The package assumes Vue 2.x. If using Vue 3, conflicts may arise.
    • Fix: Override the Vue build path or manually resolve dependencies.
  2. Template Caching

    • Issue: Twig templates for custom components may not update if cached.
    • Fix: Clear cache after changes:
      php bin/console cache:clear
      
  3. Reactive Fields Not Updating

    • Issue: Changes in Vue not reflected in Symfony form.
    • Fix: Ensure reactive_fields are correctly mapped and use @change events:
      <input v-model="formData.title" @change="submitForm">
      
  4. CSRF Token Missing

    • Issue: API requests fail with "CSRF token not found."
    • Fix: Always inject the CSRF token as shown in the integration tips.
  5. Symfony Router Not Available

    • Issue: path() function fails in Vue.
    • Fix: Pass routes explicitly via Twig:
      {{ sonata_vue_init({
          'routes': {
              'update': path('admin_post_update', { id: entity.id })
          }
      }) }}
      

Debugging Tips

  1. Check Vue DevTools

    • Inspect Vue instances, props, and events in browser dev tools (Vue tab).
  2. Log Symfony-Vue Data

    • Dump data passed from Symfony to Vue:
      {{ dump(sonata_vue_init_data) }}
      
  3. Verify Webpack Build

    • Ensure the Vue bundle is correctly loaded:
      console.log(Vue); // Should show Vue object
      
  4. Clear Cache Aggressively

    • If changes don’t reflect, clear all caches:
      php bin/console cache:clear --env=prod --no-debug
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware