How to develop package into Laravel ?Laravel

How to develop package into Laravel ?Laravel
In our daily life, we are going through lots of packages, and some of us don't know how to build our own package into Laravel.
We are going to perform the core steps to create your own package in laravel. In this tutorial we are going to build zoom package, so we will perform steps related to it.
Setup Fresh Laravel Repo
Setup fresh laravel repo, and then create directories within it.
for e.g Create infyomlabs/zoom-api directory into root.
Now create src directory into zoom-api
Run Composer init Into src Directory
After hitting composer init it will ask some information from you, as you can see in below image I have entered some of information. you can just hit enter if you do not want to add other information.
Add your config file (Optional)
Create directory config into src directory and add your config.php file there from where you can manage your env variables.
Add Service Provider
Create your service provider from where you can do lots of actions. like you can publish config/routes/ migrations files from there. here we are publishing the zoom config file.
Add your class (Which contains all functions)
Here we have added a Zoom class which will be contained all zoom functions.
Update Composer.json

Finally, Test it in your existing project
Put the following code to your main composer.json (in your project's root). and hit composer update
"repositories": [
{
"type": "path",
"url": "infyomlabs/zoom-api",
"options": {
"symlink": true
}
}
],
"license": "MIT",
"require": {
"infyomlabs/zoom-api": "dev-develop"
},
How to create custom validation rules in Laravel ?Laravel

How to create custom validation rules in Laravel ?Laravel
Generate Custom Validation Class
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Ramsey\Uuid\Uuid;
class UuidExists implements Rule
{
protected $table;
protected $column;
public function __construct($table, $column)
{
$this->table = $table;
$this->column = $column;
}
public function passes($attribute, $value)
{
$value = Uuid::fromString(strtolower($value))->getBytes();
return \DB::table($this->table)->where($this->column, $value)->exists();
}
public function message()
{
return 'The validation error message.';
}
}
Add Rule to AppService Provider
Add your rule to AppServiceProvider.php into boot() method. here I have to give the named uuid_exists to my custom rule. you can give your own name whatever you want.
\Validator::extend('uuid_exists', function ($attribute, $value, $parameters, $validator) {
list($table, $column) = $parameters;
return (new UuidExists($table, $column))->passes($attribute, $value);
});
How to use custom Rule ?
You can use your custom rule as follows. here we have using required and uuid_exists rule, where we are passing attribute and values to our custom rule, which will be used to passes($attribute, $value) function.
'tenant_id' => ['required', 'uuid_exists:tenant_id,uuid']
Keep connected to us for more interesting posts about Laravel.
How to do payments with stripe checkoutLaravel

How to do payments with stripe checkoutLaravel
Stripe Configuration with Laravel
composer require stripe/stripe-php
STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
Publish Migrations Files From Stripe
php artisan vendor:publish --tag="cashier-migrations"
php artisan migrate
Setup Stripe Controller
php artisan make:controller StripeController
namespace App\Http\Controllers;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Stripe\Checkout\Session;
use Stripe\Exception\ApiErrorException;
/**
* Class FeaturedCompanySubscriptionController
*/
class StripeControlle extends AppBaseController
{
public function createSession(Request $request)
{
setStripeApiKey();
$session = Session::create([
'payment_method_types' => ['card'],
'customer_email' => $userEmail,
'line_items' => [
[
'price_data' => [
'product_data' => [
'name' => 'Make '.$company->user->first_name.' as featured Company',
],
'unit_amount' => 100 * 100,
'currency' => 'USD',
],
'quantity' => 1,
'description' => '',
],
],
'client_reference_id' => '1234',
'mode' => 'payment',
'success_url' => url('payment-success').'?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => url('failed-payment?error=payment_cancelled'),
]);
$result = [
'sessionId' => $session['id'],
];
return $this->sendResponse($result, 'Session created successfully.');
}
public function paymentSuccess(Request $request)
{
$sessionId = $request->get('session_id');
//
}
public function handleFailedPayment()
{
//
}
}
Define Routes
Route::post('stripe-charge', 'StripeController@createSession');
Route::get('payment-success', 'StripeController@paymentSuccess');
Route::get('failed-payment', 'StripeController@handleFailedPayment');
Setup From View file
$(document).on('click', '#makePayment', function () {
$(this).addClass('disabled');
$.post(makePaymentURL, payloadData).done((result) => {
let sessionId = result.data.sessionId;
stripe.redirectToCheckout({
sessionId: sessionId,
}).then(function (result) {
$(this).html('Make Featured').removeClass('disabled');
manageAjaxErrors(result);
});
}).catch(error => {
$(this).html('Make Featured').removeClass('disabled');
manageAjaxErrors(error);
});
});
How to generate thumbnails by using Spatie Media LibraryLaravel

How to generate thumbnails by using Spatie Media LibraryLaravel
It's also providing support to convert your images to thumbnails while storing images. you can generate a thumbnail of the image with the size (height, width) you want.
They are calling thumbnails to Conversions. You can generate multiple thumbnails with different sizes as you want.
So let's see some short example which helps us to create thumbnails of an uploaded image.
Implement the HasMediaTrait into your Model
Here we have a User model and we want to generate a thumbnail of the user upload his profile image. you have to add HasMediaTrait
to the User model and need to extend HasMedia
.use IlluminateDatabaseEloquentModel;
use SpatieMediaLibraryModelsMedia;
use SpatieMediaLibraryHasMediaHasMedia;
use SpatieMediaLibraryHasMediaHasMediaTrait;
class User extends Model implements HasMedia
{
use HasMediaTrait;
public function registerMediaConversions(Media $media = null)
{
$this->addMediaConversion('profile-thumb')
->width(150)
->height(150);
}
}
registerMediaConversions
in which we can manage the size of a thumbnail, which means how much height or width we want for the thumbnail.So when we upload an image using the media library,
$media = User::first()->addMedia($pathToImage)->toMediaCollection();
How to fetch the generated thumbnail?
$media->getPath(); // the path to the where the original image is stored
$media->getPath('profile-thumb') // the path to the converted image with dimensions 150*150
$media->getUrl(); // the url to the where the original image is stored
$media->getUrl('profile-thumb') // the url to the converted image with dimensions 150*150
How to generate multiple thumbnails for a single image?
..... in User Model .....
use SpatieImageManipulations;
public function registerMediaConversions(Media $media = null)
{
$this->addMediaConversion('profile-thumb')
->width(150)
->height(150);
}
$this->addMediaConversion('old-profile-thumb')
->sepia()
->border(8, 'black', Manipulations::BORDER_OVERLAY);
}
That's it, you can read more about the spatie media library conversions (thumbnails) here.
Keep connected to us for more interesting posts about laravel.
How to integrate Zoom Meeting APIs with LaravelLaravel

How to integrate Zoom Meeting APIs with LaravelLaravel
Create a Zoom Application
- Go to Zoom marketplace and do sign in
- Click
Develop
button on header and selectBuild App
menu. - Choose the
JWT
and create an application with the app name that you want. - Input required information and click
Continue
until your app will be activated.
composer.json
to integrate the zoom API.composer require firebase/php-jwt
composer require guzzlehttp/guzzle
composer update
And don't forget that we also need to modify
.env
files to set the zoom API credentials.ZOOM_API_URL="https://api.zoom.us/v2/"
ZOOM_API_KEY="INPUT_YOUR_ZOOM_API_KEY"
ZOOM_API_SECRET="INPUT_YOUR_ZOOM_API_SECRET"
You can find the zoom credentials from your zoom app.
Now just copy given
ZoomMeetingTrait
to your controller and call-related methods.<?php
namespace App\Traits;
use GuzzleHttp\Client;
use Log;
/**
* trait ZoomMeetingTrait
*/
trait ZoomMeetingTrait
{
public $client;
public $jwt;
public $headers;
public function __construct()
{
$this->client = new Client();
$this->jwt = $this->generateZoomToken();
$this->headers = [
'Authorization' => 'Bearer '.$this->jwt,
'Content-Type' => 'application/json',
'Accept' => 'application/json',
];
}
public function generateZoomToken()
{
$key = env('ZOOM_API_KEY', '');
$secret = env('ZOOM_API_SECRET', '');
$payload = [
'iss' => $key,
'exp' => strtotime('+1 minute'),
];
return \Firebase\JWT\JWT::encode($payload, $secret, 'HS256');
}
private function retrieveZoomUrl()
{
return env('ZOOM_API_URL', '');
}
public function toZoomTimeFormat(string $dateTime)
{
try {
$date = new \DateTime($dateTime);
return $date->format('Y-m-d\TH:i:s');
} catch (\Exception $e) {
Log::error('ZoomJWT->toZoomTimeFormat : '.$e->getMessage());
return '';
}
}
public function create($data)
{
$path = 'users/me/meetings';
$url = $this->retrieveZoomUrl();
$body = [
'headers' => $this->headers,
'body' => json_encode([
'topic' => $data['topic'],
'type' => self::MEETING_TYPE_SCHEDULE,
'start_time' => $this->toZoomTimeFormat($data['start_time']),
'duration' => $data['duration'],
'agenda' => (! empty($data['agenda'])) ? $data['agenda'] : null,
'timezone' => 'Asia/Kolkata',
'settings' => [
'host_video' => ($data['host_video'] == "1") ? true : false,
'participant_video' => ($data['participant_video'] == "1") ? true : false,
'waiting_room' => true,
],
]),
];
$response = $this->client->post($url.$path, $body);
return [
'success' => $response->getStatusCode() === 201,
'data' => json_decode($response->getBody(), true),
];
}
public function update($id, $data)
{
$path = 'meetings/'.$id;
$url = $this->retrieveZoomUrl();
$body = [
'headers' => $this->headers,
'body' => json_encode([
'topic' => $data['topic'],
'type' => self::MEETING_TYPE_SCHEDULE,
'start_time' => $this->toZoomTimeFormat($data['start_time']),
'duration' => $data['duration'],
'agenda' => (! empty($data['agenda'])) ? $data['agenda'] : null,
'timezone' => 'Asia/Kolkata',
'settings' => [
'host_video' => ($data['host_video'] == "1") ? true : false,
'participant_video' => ($data['participant_video'] == "1") ? true : false,
'waiting_room' => true,
],
]),
];
$response = $this->client->patch($url.$path, $body);
return [
'success' => $response->getStatusCode() === 204,
'data' => json_decode($response->getBody(), true),
];
}
public function get($id)
{
$path = 'meetings/'.$id;
$url = $this->retrieveZoomUrl();
$this->jwt = $this->generateZoomToken();
$body = [
'headers' => $this->headers,
'body' => json_encode([]),
];
$response = $this->client->get($url.$path, $body);
return [
'success' => $response->getStatusCode() === 204,
'data' => json_decode($response->getBody(), true),
];
}
/**
* @param string $id
*
* @return bool[]
*/
public function delete($id)
{
$path = 'meetings/'.$id;
$url = $this->retrieveZoomUrl();
$body = [
'headers' => $this->headers,
'body' => json_encode([]),
];
$response = $this->client->delete($url.$path, $body);
return [
'success' => $response->getStatusCode() === 204,
];
}
}
const MEETING_TYPE_INSTANT = 1;
const MEETING_TYPE_SCHEDULE = 2;
const MEETING_TYPE_RECURRING = 3;
const MEETING_TYPE_FIXED_RECURRING_FIXED = 8;
<?php
namespace App\Http\Controllers;
use App\Models\ZoomMeeting;
use App\Traits\ZoomMeetingTrait;
use Illuminate\Http\Request;
class MeetingController extends AppBaseController
{
use ZoomMeetingTrait;
const MEETING_TYPE_INSTANT = 1;
const MEETING_TYPE_SCHEDULE = 2;
const MEETING_TYPE_RECURRING = 3;
const MEETING_TYPE_FIXED_RECURRING_FIXED = 8;
public function show($id)
{
$meeting = $this->get($id);
return view('meetings.index', compact('meeting'));
}
public function store(Request $request)
{
$this->create($request->all());
return redirect()->route('meetings.index');
}
public function update($meeting, Request $request)
{
$this->update($meeting->zoom_meeting_id, $request->all());
return redirect()->route('meetings.index');
}
public function destroy(ZoomMeeting $meeting)
{
$this->delete($meeting->id);
return $this->sendSuccess('Meeting deleted successfully.');
}
}
Make fully configurable livewire searching componentLaravel

Make fully configurable livewire searching componentLaravel
Recently we have developed the livewire common searchable component which makes your searching easier, as you can specify which fields you want to search by just giving the field name into the component.
What you have to do is just create SearchableComponent a class into your App\Http\Livewire directory. just copy the following class on the given namespace.
<?php namespace App\Http\Livewire; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Livewire\Component; use Livewire\WithPagination; use Str; abstract class SearchableComponent extends Component { use WithPagination; /** * @var string */ public $search = ''; /** * @var int */ protected $paginate = 12; /** @var Builder */ private $query; /** * SearchableComponent constructor. * * @param $id */ public function __construct($id) { parent::__construct($id); $this->prepareModelQuery(); } /** * Prepare query */ private function prepareModelQuery() { /** @var Model $model */ $model = app($this->model()); $this->query = $model->newQuery(); } /** * @return mixed */ abstract function model(); /** * Reset model query */ protected function resetQuery() { $this->prepareModelQuery(); } /** * @return Builder */ protected function getQuery() { return $this->query; } /** * @param Builder $query */ protected function setQuery(Builder $query) { $this->query = $query; } /** * @param bool $search * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ protected function paginate($search = true) { if ($search) { $this->filterResults(); } $all = $this->query->paginate($this->paginate); $currentPage = $all->currentPage(); $lastPage = $all->lastPage(); if ($currentPage > $lastPage) { $this->page = $lastPage; } return $this->query->paginate($this->paginate); } /** * @return Builder */ protected function filterResults() { $searchableFields = $this->searchableFields(); $search = $this->search; $this->query->when(! empty($search), function (Builder $q) use ($search, $searchableFields) { $searchString = '%'.$search.'%'; foreach ($searchableFields as $field) { if (Str::contains($field, '.')) { $field = explode('.', $field); $q->orWhereHas($field[0], function (Builder $query) use ($field, $searchString) { $query->whereRaw("lower($field[1]) like ?", $searchString); }); } else { $q->orWhereRaw("lower($field) like ?", $searchString); } } }); return $this->query; } /** * @return mixed */ abstract function searchableFields(); }
<?php namespace App\Http\Livewire; use App\Models\Tag; use Illuminate\Contracts\Pagination\LengthAwarePaginator; class Tags extends SearchableComponent { public function render() { $tags = $this->searchTags(); return view('livewire.tags', [ 'tags' => $tags, ])->with("search"); } /** * @return LengthAwarePaginator */ public function searchTags() { $this->setQuery($this->getQuery()); return $this->paginate(); } function model() { return Tag::class; } function searchableFields() { return [
'name',
];
}
}
In searchable fields you can specify the field name that you want to search. and replace the Model with your records Model.
That it. Now you don't need to write search queries again and again. just extend your livewire component by searchable component.
Here are some Interesting livewire tutorials that you need to check :
How to use select2 with livewireLaravel

How to use select2 with livewireLaravel
We can resolve this issue by using a livewire javascript hook.
Here is my screen with select2 before livewire component rendering.

And when the livewire component is refreshed means re-render the select2 style is gone ☹️

How to Fix it ?? 🤔
document.addEventListener('livewire:load', function (event) { window.livewire.hook('afterDomUpdate', () => { $('#select2ID').select2(); }); });
livewire:load is listening events when livewire component is load and we can add our code within it.
And now when your livewire component is refreshed your select2 style will be still there as we are again applying it.
Other Livewire Posts :
Setup Laravel Livewire with Basic Component ExampleLaravel

Setup Laravel Livewire with Basic Component ExampleLaravel
composer require livewire/livewire
... @livewireStyles </head> <body> ... @livewireScripts </body> </html>
php artisan make:livewire Summation
// app/Http/Livewire/Summation/php namespace App\Http\Livewire; use Livewire\Component; class Summation extends Component { public function render() { return view('livewire.summation'); } } // resources/views/livewire/summation.blade.php <div> ... </div>
<head> ... @livewireStyles </head> <body> <livewire:summation /> ... @livewireScripts </body> </html>
namespace App\Http\Livewire; use Livewire\Component; class Summation extends Component { public $value1 = 0; public $value2 = 0; public $sum = 0; public function mount() { $this->sum = 0; } public function render() { $this->sum = $this->value1 + $this->value2; return view('livewire.summation'); } }
<div> <input type="text" class="" wire:model="value1"> <input type="text" class="" wire:model="value2"> <input type="text" disabled wire:model="sum"> </div>