Slow request with simple query in Laravel using Axios - php

I'm making a request with Axios and the time it takes for making a request is approximately ~1.21s.
This is my sample controller for the delete method.
public function destroy($id)
{
$business = Business::findOrFail($id);
if($business->delete())
{
return new BusinessResource($business);
}
}
And this is my Axios script.
deleteBusiness: function(id)
{
let vm = this;
axios.delete('api/business/'+id)
.then(function (response){
alert("Business Deleted");
vm.fetchBusiness();
})
.catch(function (error) {
console.log(error);
});
},
This is my model, implementing Laravel Scout & TNTSearch:.
namespace App;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Business extends Model
{
use Searchable;
protected $table = 'business';
public function toSearchableArray()
{
return [
'id' => $this->id,
'businessName' => $this->businessName,
];
}
public function searchableAs()
{
return 'business_index';
}
}
When I remove the use Searchable in the model, the request time reduces to approximately ~300ms. Is there any way to reduce the time of this request without removing the use Searchable in the model? Do I need to use Redis?

Related

Lumen: The new record with default values was added to database

I'm new to PHP and I've tried to make the small test full-stack project. I have Vue.js app on the client (frontend) and PHP (Lumen) on the server (backend). The code looks as following:
Client:
Vue component:
async createPerson() {
const optionAxios = {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}
try {
await axios.post(`http://localhost:8000/api/persons/`, {
firstName: 'Edward',
lastName: 'Edwardson',
address: 'Address8'
}, optionAxios)
} catch (error) {
console.log(error)
}
},
Server:
Router:
$router->group(['prefix' => 'api'], function () use ($router) {
$router->post('persons', ['uses' => 'PersonController#create']);
});
Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
protected $connection = 'mysql';
protected $table = 'person';
protected $primaryKey = 'id';
public $incrementing = true;
public $timestamps = false;
protected $fillable = [
'firstName', 'lastName', 'address'
];
protected $hidden = [];
}
Controller:
<?php
namespace App\Http\Controllers;
use App\Person;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class PersonController extends Controller
{
public function __construct() {
header("Access-Control-Allow-Origin: *");
}
public function create(Request $request)
{
$person = Person::create($request->all());
error_log($person);
return response()->json($person, 201);
}
}
Database:
Debug session on server side - $request value:
The issue is the new record was added to database, but with default values that I set on database level. I'm not sure why the object I've passed on the client is not added.
{
firstName: 'Edward',
lastName: 'Edwardson',
address: 'Address8'
}
And the last thing - it works if I use Postman. But, as you can see, it doesn't work with Axios.
Your problem is that you are changing what the content type of your request is. Do not write headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, as axios sends this as 'Content-Type': 'application/json', so when it arrives to Lumen, it "decodes" it correctly and you can do $request->all() and get any data you want. You don't even have to write any content-type header, it is all automatically done by axios in this case.
So your javascript code should be like:
async createPerson() {
await axios.post('/api/persons/', {
firstName: 'Edward',
lastName: 'Edwardson',
address: 'Address8'
})
},

Laravel trait saving event is fired on database query

In my code, I created a trait to clear out some cache. It's code looks like below.
<?php
namespace App\Models\Traits;
use App\Classes\Utilities\ResponseCache as ResponseCache;
trait ClearsResponseCache {
public static function bootClearsResponseCache() {
static::saving(function () {
ResponseCache::removeAll();
});
static::updating(function () {
ResponseCache::removeAll();
});
static::deleting(function () {
ResponseCache::removeAll();
});
}
}
In my controller I have a custom query to select some rows from the database.
public function fetchAllItems() {
$items = DB::select('My custom query');
return response()->json($items);
}
Now, when this function is run, the saving event of ClearsResponseCache is fired, leading to my cache being deleted. Any idea why that event is being fired?

Receive Notificatoin Pusher + Echo in Laravel

I am trying to receive notification using echo + pusher. I can post to pusher and pusher console receive the event and channel but i can't get this data on laravel. I read many documents, but none of them work for me.
WebNotification Class // Notification file
private $subscription;
public function __construct($data)
{
$this->subscription = $data;
}
public function via($notifiable)
{
return ['database','broadcast'];
}
public function toBroadcast($notifiable)
{
return new BroadcastMessage([
'data' => $this->subscription,
'count' => $notifiable->unreadNotifications->count()
]);
}
Account Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
class account extends Model
{
use Notifiable;
public function receivesBroadcastNotificationsOn()
{
return 'accounts.'.$this->id;
}
}
MyNotification // To call event to send data to pusher
public function DatabaseNot(){
$user = Account::where('id', Cookie::get('uid'))->first();
$data = collect(['title'=>'Hello Title', 'body'=>'my body']);
$user->notify(new WebNotification($data));
return view('layout.test',['user'=>$user]);
}
Pusher log
Channel: private-accounts.23, Event: Illuminate\Notifications\Events\BroadcastNotificationCreated
I call Echo in resorces/js/app.js
Echo.private('App.accounts.23')
.notification((notification) => {
console.log(notification.type);
});
I did not get any response from this.
I already add csrf token in meta, I compiled js code using NPM run watch. I tried many other ways, no one provide clear document, its so confusing.

is it better to create separate request class for each new method in controller, or edit existing request class in laravel or any better idea?

Is it better to create separate request class for each new method in controller or edit existing request class in laravel or any better idea ?
example
class fooBarController {
public function a(fooBarARequest $r) {
}
public function b(fooBarBrequest $r) {
}
public function c(fooBarCDRequest $r) {
}
public function d(fooBarCDRequest $r) {
}
}
Using extra request classes allows you to define validation rules which your request is checked against before it reaches your controller. You can also handle authorization in the request class. An example would be:
class UpdateAccountEmail extends FormRequest
{
public function authorize()
{
return true; // authorization is handled on route/middleware level
}
public function rules()
{
return [
'new_email' => 'required|email|confirmed',
'new_email_confirmation' => 'required',
];
}
}
So, to sum it up: it does not make sense to use a custom request class for requests which do not have payload that needs to be validated. This means, for a normal GET request we most likely (of course there are exceptions) want to use the normal Request class provided by laravel. A controller like this would be quite normal:
class AccountController
{
public function show(Request $request)
{
return view('account.show', ['user' => $request->user()]);
}
public function edit()
{
return view('account.edit', ['user' => \Auth::user()]);
}
public function updateEmail(UpdateAccountEmail $request)
{
$user = $request->user();
$user->email = $request->input('new_email');
$user->save();
return redirect()->route('account.index');
}
public function logins(Request $request)
{
$logins = $request->user()->logins()
->when($request->get('filter_from'), function ($query, $from) {
$query->where('created_at', '>=', $from);
})
->when($request->get('filter_until'), function ($query, $until) {
$query->where('created_at', '<=', $until);
})
->get();
return view('account.logins', ['logins' => $logins]);
}
}
As you can see, for the GET request that is handled by logins(Request $request), we do not use a custom request class because we don't need to validate anything (well, we could validate the filter parameters, but for simplicity we don't).
The example above also shows different methods of retrieving the current user. Even for that you don't need a request at all.
This is no actual production code, just something off the top of my head...

Referencing to another model in Laravel

Just finished my "friends" system in Laravel (5.4) for a projet I'm working on. I call them "connections" in my case. Everything is working fine and I'm now trying to clean everything a little bit.
From the very beginning, following tutorials and SO answers, I put every method in my User model (which is not that bad: a connection is related to a user). But I'd like to clean and put everything related to my connections into a model named Connection.
Does the User model should handle everything related to connections, or my cleaning wish makes sense and a Connection model is legit?
How to achieve that regarding the code below? How to reference to User now I'm not inside the class anymore and $this becoming pointless?
Connection model
namespace App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Connection extends Authenticatable
{
const PENDING = 0;
const ACCEPTED = 1;
const REJECTED = 2;
}
User model
namespace App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
// Get connections the user initiated by himself
public function connectionsOfOwner() {
return $this->belongsToMany(User::class, 'connections', 'user_id', 'connection_id')->withPivot('status');
}
// Get connections the user has been invited to
public function connectionsOf() {
return $this->belongsToMany(User::class, 'connections', 'connection_id', 'user_id')->withPivot('status');
}
// Accessor allowing to call $this->connections
public function getConnectionsAttribute() {
if (!array_key_exists('connections', $this->relations)) {
$this->loadConnections();
}
return $this->getRelation('connections');
}
// Check if a Laravel relation named "connection" exists
protected function loadConnections() {
if (!array_key_exists('connections', $this->relations)) {
$this->setRelation('connections', $this->mergeConnections());
}
}
// Merge "connectionsOfOwner" and "connectionsOf"
protected function mergeConnections() {
return $this->connectionsOfOwner->merge($this->connectionsOf);
}
// Get pending connections
public function getPendingConnections() {
$filtered = $this->connections->filter(function ($value, $key) {
if ($value->pivot->status == 0) {
return $value;
}
});
return $filtered;
}
// Get accepted connections
public function getAcceptedConnections() {
$filtered = $this->connections->filter(function ($value, $key) {
if ($value->pivot->status == 1) {
return $value;
}
});
return $filtered;
}
// Add a connection
public function addConnection($user) {
$this->connectionsOfOwner()->attach($user->id);
}
// Accept a connection
public function acceptConnection($user) {
$this->connectionsOf()->syncWithoutDetaching([$user->id => ['status' => Connection::ACCEPTED]]);
$this->connectionsOfOwner()->attach($user->id, ['status' => Connection::ACCEPTED]);
}
// Remove a connection
public function removeConnection($user) {
$this->connectionsOfOwner()->detach($user->id);
$this->connectionsOf()->detach($user->id);
}
}
Possibly you could skip the Connection Model and keep that functionality in a trait "HasConnections" that you use in th User model.
Jeffrey Way briefly talks about this approach in Laracon2017: https://streamacon.com/video/laracon-us-2017/day-2-jeffrey-way
Good luck!

Categories