Laravel Inertia Vite - php

In production mode (on the server), there is an error on my site in the Chrome console:
Uncaught (in promise) Error: Page not found: ./Pages/Posts/Show.vue
Also, the Dashboard page isn't updating to changes with text and a new pagination table I've introduced in local development.
Everything works fine locally, but pushing to Digital Ocean Server doesn't show the latest changes.
I checked the source code online and they raw code is there. I can see the changes in text, the pagination table and the new routes. But they are not showing when I load the website. I suspect something to do with the cache or the build process?
I have done:
php artisan cache:clear
php artisan config:clear
php artisan view:clear
npm run build (new vite build of assets)
Can anyone help?
Shared Files:
resources/js/app.js
import './bootstrap';
import '../css/app.css';
import { createApp, h } from 'vue';
import { createInertiaApp } from '#inertiajs/inertia-vue3';
import { InertiaProgress } from '#inertiajs/progress';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
.use(plugin)
.use(ZiggyVue, Ziggy)
.mount(el);
},
});
InertiaProgress.init({ color: '#4B5563' });
Post Controller
<?php
namespace App\Http\Controllers\Post;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\Post;
class PostController extends Controller
{
/**
* Display all posts
*
* #return \Inertia\Response
*/
public function index(Request $request)
{
$posts = Post::paginate(10);
return Inertia::render('Dashboard', ['posts' => $posts]);
}
/**
* Display a post
*
* #return \Inertia\Response
*/
public function show(Request $request, $id)
{
$post = Post::findOrFail($id);
return Inertia::render('Posts/Show', ['post' => $post]);
}
}

This was an docker/nginx issue. The files generated by the app weren't routing correctly and so the static files from the original build weren't being replaced.
I changed to using volumes to sync data between the containers and it worked.

Related

Why I have "Not found" /admin in symfony easyAdminBundle 4 (php)

I can't open /admin page after installing easyAdminBundle in symfony app.
I do:
symfony composer req "admin:^4"
then
symfony console make:admin:dashboard
This line generate this code.
<?php
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class DashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
public function index(): Response
{
return parent::index();
// Option 1. You can make your dashboard redirect to some common page of your backend
//
// $adminUrlGenerator = $this->container->get(AdminUrlGenerator::class);
// return $this->redirect($adminUrlGenerator->setController(OneOfYourCrudController::class)->generateUrl());
// Option 2. You can make your dashboard redirect to different pages depending on the user
//
// if ('jane' === $this->getUser()->getUsername()) {
// return $this->redirect('...');
// }
// Option 3. You can render some custom template to display a proper dashboard with widgets, etc.
// (tip: it's easier if your template extends from #EasyAdmin/page/content.html.twig)
//
// return $this->render('some/path/my-dashboard.html.twig');
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('Symfony App');
}
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
// yield MenuItem::linkToCrud('The Label', 'fas fa-list', EntityClass::class);
}
}
But when I try to open /admin page I get this:
"Not Found
The requested URL was not found on this server."
This lines doesn't help:
symfony console cache:clear
symfony composer dump-autoload
rm -rf var/cache/*
I want to see the start page at easyAdminBundle like in symfony documentation. Why I can't get this?
I just solved this by changing the route for DashboardController::index from '/admin' to '/admin/d' then going to http://127.0.0.1:8000/admin/d
class DashboardController extends AbstractDashboardController
{
#[Route('/admin/d', name: 'admin')]
public function index(): Response
{
return parent::index();
}
/* ... */
}

how to use react-query with a Laravel api

I am following a example that uses react-query, the example works fine with the test data, but when it hits a backend that I am building is not working as expected, I mean, it retrieves the information, but don't cache the information, always hits the server, but using the example, that was not happening.
hooks/user.js
import { useQuery } from "react-query";
import axios from "axios";
export const useUsers = (activePage) => {
return useQuery(
// Add activePage as a dependency
["users", activePage],
async () => {
const { data } = await axios.get(
//works fine here
`https://reqres.in/api/users?page=${activePage}`
//Here not works properly
//`http://127.0.0.1:8000/api/users?page=${activePage}`
);
return data;
},
// This tells React-Query that this is Query is part of
// a paginated component
{ keepPreviousData: true }
);
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
const queryClient = new QueryClient(); // Global Store Instance
ReactDOM.render(
<QueryClientProvider client={queryClient}>
<React.StrictMode>
<App />
</React.StrictMode>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>,
document.getElementById('root')
);
reportWebVitals();
App.js
import { useState } from "react";
import TableHeader from "./components/tableHeader/TableHeader";
import TableRow from "./components/tableRow/TableRow";
import Pagination from "./components/pagination/Pagination";
// Import the hook
import { useUsers } from "./hooks/users";
const App = () => {
const [activePage, setActivePage] = useState(1);
// React Query takes care of calling
// userUsers hook when App.js is rendered.
const usersList = useUsers(activePage);
return (
<>
<TableHeader />
{/* map through users list */}
{usersList.data &&
usersList.data.data.map((user) => <TableRow user={user} key={user.id} />)}
<Pagination
activePage={activePage}
setActivePage={setActivePage}
pages={2}
/>
</>
);
};
export default App;
In the example, when I hit the api again, I mean, I go to other page twice, in the network tab is says this: (disk cache)
Which is the expected behaviour, but when it is using my laravel api, then is not working properly, it is able to retrieve the information, but always hits the server, not the cache
In my laravel app I have this:
routes/api.php
Route::get('/users', [UsersController::class, 'index']);
UsersController.php
...
public function index()
{
return User::paginate(10);
}
...
The frontend is using this url:
http://localhost:3000/
and the backend is using this:
http://localhost:8000/
maybe is because of the port? but using the external api: https://reqres.in/api/users?page=1 it works without problem, it uses the cache as expected, do weird. I think I need to modify my api
This is the response of my local api:
{
"current_page":1,
"data":[
{
"id":1,
"first_name":"sergio",
"avatar_url":"https:\/\/url",
"age":30,
"created_at":"2022-09-11T22:29:52.000000Z",
"updated_at":"2022-09-11T22:29:52.000000Z"
},
{
"id":2,
"first_name":"jhon",
"avatar_url":"https:\/\/url",
"age":39,
"created_at":"2022-09-11T22:30:03.000000Z",
"updated_at":"2022-09-11T22:30:03.000000Z"
},
...
...
],
"first_page_url":"http:\/\/127.0.0.1:8000\/api\/users?page=1",
"from":1,
"last_page":9,
"last_page_url":"http:\/\/127.0.0.1:8000\/api\/users?page=9",
"next_page_url":"http:\/\/127.0.0.1:8000\/api\/users?page=2",
"path":"http:\/\/127.0.0.1:8000\/api\/users",
"per_page":3,
"prev_page_url":null,
"to":3,
"total":25
}
What can I do? thanks.
Replace return in your controller by this one
return response()->json(User::paginate(10));

Laravel and react, How to give a notification from Laravel to my react application (Unexpected use of 'self' no restricted-globals error)

I can create Notifications In laravel and in React. I have followed the tutorials, but I don't know how to send the notification from laravel to my react application. This is the code that I got in my Laravel Controller.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Feature\HttpHandler;
use App\Notifications\PushDemo;
use App\Models\Users;
use Illuminate\Support\Facades\Auth;
use Notification;
use Illuminate\Support\Facades\Log;
use NotificationChannels\WebPush\PushSubscription;
use Illuminate\Support\Facades\Http;
use App\Feature\ApiResponse;
class PushController extends Controller
{
use ApiResponse;
use HttpHandler;
public function __construct(){
}
public function push(){
Log::info('Push push function called');
$users = Users::all();
Notification::send($users,new PushDemo);
return redirect()->back();
}
public function store(Request $request)
{
Log::info('Push store called');
// get user from request
//$user = Users::findOrFail($request->userId);
$user = Users::whereUrl($request->post('URL'))->firstOrFail();
$b = $request['body'];
// create PushSubscription and connect to this user
$pushsub = $user->updatePushSubscription($request->body['endpoint'], $request->body['keys']['p256dh'], $request->body['keys']['auth']);
Log::info('WORKED');
return $pushsub;
}
}
The store function works.
In react I have this piece of code in my service-worker.js to listen to a event. (this is the piece of code that needs to work, but it says unexpected use of 'self' no restriced-globals)
self.addEventListener('push', function (e) {
console.log('push');
if (!(self.Notification && self.Notification.permission === 'granted')) {
//notifications aren't supported or permission not granted!
return;
}
if (e.data) {
var msg = e.data.json();
console.log(msg)
e.waitUntil(self.registration.showNotification(msg.title, {
body: msg.body,
icon: msg.icon,
actions: msg.actions
}));
}
});
This code is never called it seems but it should be called when I click on this button:
<button onClick={() => test()}>
test notification
</button>
This is the function to go through the Laravel application:
function test(){
console.log('test');
workerApi.makePushNotification({ URL, token})
.then(response => {
if (response.hasOwnProperty('message') && response.hasOwnProperty('type')) {
}
else {
console.log(JSON.stringify(response.data));
}
})
})
}
This function call works. only it seemd like the service worker function is never called and it doesn't send the notification to my react application. How do I solve this?
hey you should use some real-time library for listener real-time events like pusher then you can send the message from the server to the frontend
for installing pusher on laravel application please check this article
https://www.codecheef.org/article/real-time-event-broadcasting-with-laravel-6-and-pusher
and for your react app
npm install --save pusher-js
your component file
import Pusher from 'pusher-js';
useEffect(() => {
var pusher = new Pusher("your-pusher-key", {
cluster: "ap2",
encrypted: true,
});
var channel = pusher.subscribe("notifyChannel");
channel.bind("notifyChannel", async function (response) {
alert('some notification');
})
});

Next js - Call a function on server side each time a route is changed

I am moving an old stack to next js and i need some help.
I have a php backend and I want to check a controller from this backend each time a route is changed, and I want to do it on server side.
For changing route, I use Link of next-routes, which have an effect only on the client side.
Is there any way I can call the controller on server-side without refreshing the app?
You can take advantage of Router's events and Custom App watching for a route change and perform the actions you need. Below you can find two sample implementations, one using class component and one using hooks. Both should do the trick.
// class component
import NextApp from 'next/app';
import Router from 'next/router';
class App extends NextApp {
componentDidMount() {
Router.events.on('routeChangeStart', () => {
// call to your backend
});
}
render() {
const { Component, pageProps } = this.props;
return <Component {...pageProps} />;
}
}
export default App;
// using hooks
import Router from 'next/router';
const App = ({ Component, pageProps }) => {
React.useEffect(() => {
const doMagic = () => {
// do your thing
}
Router.events.on('routeChangeStart', doMagic); // add listener
return () => {
Router.events.off('routeChangeStart', doMagic); // remove listener
}
}, []);
return <Component {...pageProps} />;
}
export default App;

BotMan - Conversations method is not replying

i am working on facebook messenger bot. I am using Botman (botman.io) without Laravel or botman studio. Version of PHP is 7.4.
Simple hears and reply method works fine, but conversation replying method does not working.
If I try type hi|hello or some greetings, chatbot answer me "Hello! What is your firstname?", then I write my name and chatbot does not returns any text :-/
Can you help me where is a bug?
There is a conversation class:
namespace LiborMatejka\Conversations;
use BotMan\BotMan\Messages\Conversations\Conversation;
use BotMan\BotMan\Messages\Incoming\Answer;
class OnboardingConversation extends Conversation {
protected $firstname;
protected $email;
function askFirstname() {
$this->ask('Hello! What is your firstname?', function (Answer $answer) {
// Save result
$this->firstname = $answer->getText();
$this->say('Nice to meet you ' . $this->firstname);
$this->askEmail();
});
}
public function askEmail() {
$this->ask('One more thing - what is your email?', function (Answer $answer) {
// Save result
$this->email = $answer->getText();
$this->say('Great - that is all we need, ' . $this->firstname);
});
//$this->bot->typesAndWaits(2);
}
public function run() {
// This will be called immediately
$this->askFirstname();
}
}
and there is config:
require_once "vendor/autoload.php";
require_once "class/onboardingConversation.php";
use BotMan\BotMan\BotMan;
use BotMan\BotMan\BotManFactory;
use BotMan\BotMan\Drivers\DriverManager;
use BotMan\Drivers\Facebook\FacebookDriver;
use LiborMatejka\Conversations\OnboardingConversation;
$config = [
// Your driver-specific configuration
'facebook' => [
'token' => 'my_token',
'app_secret' => 'my_secret_app_code',
'verification' => 'verification_code',
],
'botman' => [
'conversation_cache_time' => 0,
],
];
// Load the driver(s) you want to use
DriverManager::loadDriver(\BotMan\Drivers\Facebook\FacebookDriver::class);
// Create an instance
$botman = BotManFactory::create($config);
$botman->hears('ahoj|hi|hello|cau|cus|zdar|zdarec|cago|hey|ciao', function (BotMan $bot) {
$bot->startConversation(new OnboardingConversation);
});
// Start listening
$botman->listen();
Add symfony/cache to your project using composer
composer require symfony/cache
Put following at top of index.php (or other) file where you're setting up BotMan
use BotMan\BotMan\Cache\SymfonyCache;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
Then create your BotMan using the following:
$adapter = new FilesystemAdapter();
$botman = BotManFactory::create($config, new SymfonyCache($adapter));
Then use your $botman variable accordingly, like example below:
$botman->hears('Hi', function (BotMan $bot) {
$bot->typesAndWaits(2);
$bot->reply('Hello and welcome');
$bot->typesAndWaits(2);
$bot->ask('Anything I can do for you today?',function($answer, $bot){
$bot->say("Oh, really! You said '{$answer->getText()}'... is that right?");
});
});
I would rather to use auto-wiring to inject the SymfonyCache anywhere you create the Botman instance, without creating the adapter and cache again and again.
Step 1: config the cache in cache.yaml
framework:
cache:
# botman: cache adapter
app: cache.adapter.filesystem
Step 2: autowiring in services.yaml
services:
BotMan\BotMan\Cache\SymfonyCache:
arguments:
$adapter: '#cache.app'
Step 3: Inject the SymfonyCache where you need, for example in ChatController::message()
public function message(SymfonyCache $symfonyCache): Response
{
....
$botman = BotManFactory::create([], $symfonyCache);
....
$botman->hears(
'survey',
function (BotMan $bot) {
$bot->startConversation(new OnBoardingConversation());
}
);
}
To create the OnBoardingConversation, just follow the documentation on create a conversation in botman

Categories