This is my laravel model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Library\Log as MailLog;
class SendingServerPhpMail extends SendingServer
{
protected $table = 'sending_servers';
public function send($message, $params = array())
{
try {
$transport = \Swift_MailTransport::newInstance();
// Create the Mailer using your created Transport
$mailer = \Swift_Mailer::newInstance($transport);
// Actually send
$sent = $mailer->send($message);
if ($sent) {
MailLog::info('Sent!');
return array(
'status' => self::DELIVERY_STATUS_SENT,
);
} else {
**MailLog::warning('Sending failed');**
return array(
'status' => self::DELIVERY_STATUS_FAILED,
'error' => 'Unknown SMTP error',
);
}
} catch (\Exception $e) {
MailLog::warning('Sending failed');
MailLog::warning($e->getMessage());
return array(
'status' => self::DELIVERY_STATUS_FAILED,
'error' => $e->getMessage(),
'message_id' => null,
);
}
}
}
?>
This is the library which i am using as mail log
<?php
namespace App\Library;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
class Log
{
public static $logger;
public static $path;
public static function warning($message)
{
self::$logger->warning($message);
}
}
?>
I am getting this error while calling warning function which is declared in mail log library. you can see modal where I am calling warning function
"message": "Call to a member function warning() on null"
In modal, I have used the maillog library and after that, I am calling warning and other function in the model, which is defined in the mail log library.
but for warning function, I am getting error Call to a member function warning() on null
I think this is because the $logger inside App\Library\Log class is never set
public static function warning($message)
{
if (! self::$logger) {
self::$logger = new Logger('name');
self::$logger->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
}
self::$logger->warning($message);
}
Hope this can help
Related
I want to create a payment intention with the Stripe API from Laravel.
I don't get a successful payment intent, but I get this error:
DELL#DELL-PC MINGW64 /c/xampp/htdocs/LaravelPayment
$ php artisan tinker
Psy Shell v0.11.2 (PHP 8.0.8 — cli) by Justin Hileman
$stripe = new App\Services\StripeService;
=> APP\Services\StripeService {#3555}
$stripe->createIntent(5.01, 'USD', 'pm_1KlyY1JJef7TvJrq8R8fD5B6');
GuzzleHttp\Exception\ClientException with message 'Client error: POST https://api.stripe.com/v1/payment_intents resulted in a 400 Bad Request response:
{
"error": {
"code": "parameter_missing",
"doc_url": "https://stripe.com/docs/error-codes/parameter-missing",
(truncated...)
'
Below, you can find my code:
<?php
namespace APP\Services;
use Illuminate\Http\Request;
use App\Traits\ConsumesExternalServices;
class StripeService
{
use ConsumesExternalServices;
protected $baseUri;
protected $key;
protected $secret;
public function __construct()
{
$this->baseUri = config('services.stripe.base_uri');
$this->key = config('services.stripe.key');
$this->secret = config('services.stripe.secret');
}
public function resolveAuthorization(&$queryParams, &$formParams, &$headers)
{
$headers['Authorization'] = $this->resolveAccessToken();
}
public function decodeResponse($response)
{
return json_decode($response);
}
public function resolveAccessToken()
{
return "Bearer {$this->secret}";
}
public function handlePayment(Request $request)
{
//
}
public function handleApproval()
{
//
}
public function createIntent($value, $currency, $paymentMethod)
{
return $this->makeRequest(
'POST',
'/v1/payment_intents',
[],
[
'amount' => round($value * $this->resolveFactor($currency)),
'currency' => strtolower($currency),
'payment_method' => $paymentMethod,
'confirmation_method' => 'manual',
],
);
}
public function resolveFactor($currency)
{
$zeroDecimalCurrencies = ['JPY'];
if (in_array(strtoupper($currency), $zeroDecimalCurrencies)) {
return 1;
}
return 100;
}
}
Could you please check with me what is the problem?
I've tried to debug and it seems that those values are sent correctly:
What should I do now?
I need to modify /vendor/laravel/fortify/src/Contracts/CreatesNewUsers.php interface
and to add 1 more bool parameter, as using CreateNewUser in different places of the app
validations rules are different, say in some places password is not filled on user creation, but must be separate function.
So I copied file /project/resources/fortify/CreatesNewUsers.php with content :
<?php
namespace Laravel\Fortify\Contracts;
interface CreatesNewUsers
{
public function create(array $input, bool $makeValidation);
}
and in app/Actions/Fortify/CreateNewUser.php I modified :
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
//use Laravel\Fortify\Contracts\CreatesNewUsers;
use Resources\Fortify\CreatesNewUsers; // Reference to my interface
use Laravel\Jetstream\Jetstream;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
public function create(array $input, bool $makeValidation)
{
...
But trying to use this class I got error
Interface "Resources\Fortify\CreatesNewUsers" not found
Which is the valid way ?
Thanks!
I moved interface at file app/Actions/Fortify/CreatesNewUsers.php :
<?php
namespace App\Actions\Fortify;
interface CreatesNewUsers
{
public function create(array $input, bool $make_validation, array $hasPermissions);
}
and modified app/Actions/Fortify/CreateNewUser.php :
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use DB;
use App\Actions\Fortify\CreatesNewUsers;
use Laravel\Jetstream\Jetstream;
use Spatie\Permission\Models\Permission;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
/**
* Validate and create a newly registered user.
*
* #param array $input
*
* #return \App\Models\User
*/
public function create(array $input, bool $make_validation, array $hasPermissions)
{
if ($make_validation) {
$userValidationRulesArray = User::getUserValidationRulesArray(null, '', []);
if (\App::runningInConsole()) {
unset($userValidationRulesArray['password_2']);
}
$validator = Validator::make($input, $userValidationRulesArray);//->validate();
if ($validator->fails()) {
$errorMsg = $validator->getMessageBag();
if (\App::runningInConsole()) {
echo '::$errorMsg::' . print_r($errorMsg, true) . '</pre>';
}
return $errorMsg;
}
} // if($make_validation) {
$newUserData = [
'name' => $input['name'],
'email' => $input['email'],
'account_type' => $input['account_type'],
'phone' => $input['phone'],
'website' => $input['website'],
'notes' => $input['notes'],
'first_name' => $input['first_name'],
'last_name' => $input['last_name'],
];
if (isset($input['password'])) {
$newUserData['password'] = Hash::make($input['password']);
}
if (isset($input['status'])) {
$newUserData['status'] = $input['status'];
}
if (isset($input['activated_at'])) {
$newUserData['activated_at'] = $input['activated_at'];
}
if (isset($input['avatar'])) {
$newUserData['avatar'] = $input['avatar'];
}
try {
DB::beginTransaction();
$newUser = User::create($newUserData);
foreach ($hasPermissions as $nextHasPermission) {
$appAdminPermission = Permission::findByName($nextHasPermission);
if ($appAdminPermission) {
$newUser->givePermissionTo($appAdminPermission);
}
}
DB::commit();
return $newUser;
} catch (QueryException $e) {
DB::rollBack();
if (\App::runningInConsole()) {
echo '::$e->getMessage()::' . print_r($e->getMessage(), true) . '</pre>';
}
}
return false;
}
}
It allows me to use CreateNewUser from different parts of app, like seeders, adminarea, user registration
with different behaviour. For me it seems good way of using fortify and CreateNewUser...
In my Laravel-8 and Maatwebsite-3.1 package, I have this code:
use App\Models\User;
use App\Models\Country;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\SkipsErrors;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Validators\Failure;
use Throwable;
class CountryImport implements
ToModel,
WithValidation,
WithHeadingRow,
SkipsOnError,
SkipsOnFailure,
WithBatchInserts
{
private $rows = 0; // variable to count rows
use Importable, SkipsErrors, SkipsFailures;
public function model(array $row)
{
return new Country([
'name' => $row[0],
'nationality' => $row[1],
'created_at' => date("Y-m-d H:i:s"),
'created_by' => Auth::user()->id,
]);
}
public function headingRow(): int
{
return 1;
}
public function getRowCount(): int
{
return $this->rows;
}
public function customValidationAttributes()
{
return [
'0' => 'Country',
'1' => 'Nationality',
];
}
public function rules(): array
{
return [
'*.0' => [
'required',
'string',
'max:100',
Rule::unique('countries', 'name')
],
'*.1' => [
'nullable',
'string',
'max:50',
Rule::unique('countries', 'nationality')
],
];
}
public function batchSize(): int
{
return 1000;
}
public function chunkSize(): int
{
return 1000;
}
public function onFailure(Failure ...$failures)
{
// Handle the failures how you'd like.
}
}
Controller:
public function importCountry(Request $request)
{
DB::beginTransaction();
$user = Auth::user()->id;
$userEmail = Auth::user()->email;
try {
$validator = Validator::make($request->all(), [
'document' => 'file|mimes:xlsx|max:10000',
]);
if($validator->fails()) {
return $this->error($validator->errors(), 401);
} else {
$check = User::where('id', $user)->pluck('id');
if($check[0] !== null || $check[0] !== undefined) {
$file = $request->file('document');
$file->move(public_path('storage/file_imports/location_imports'), $file->getClientOriginalName());
Excel::import(new CountryImport, public_path('storage/file_imports/location_imports/' . $file->getClientOriginalName() ));
DB::commit();
return $this->success('Nationalities Successfully Imported.', [
'file' => $file
]);
} else {
return $this->error('Not allowed', 401);
}
}
} catch(\Exception $e) {
DB::rollback();
Log::error($e);
return $this->error($e->getMessage(), $e->getCode());
}
}
I am using Laravel as the API endpoint and Angular as the frontend.
It displays successful, and the Excel file found in storage/file_imports/location_imports as instructed.
But nothing was stored in the database without any error.
How do I resolve this?
Thanks
Your controller code is not correct. You are doing wrong stuff about the DB Transaction... See that, if you have any validation error, you are never reverting back or doing anything with the transaction itself...
Try this code:
public function importCountry(Request $request)
{
$request->validate([
'document' => 'file|mimes:xlsx|max:10000',
]);
try {
DB::beginTransaction();
$file = $request->file('document');
$file->move(
public_path('storage/file_imports/location_imports'),
$file->getClientOriginalName()
);
Excel::import(
new CountryImport,
public_path('storage/file_imports/location_imports/' . $file->getClientOriginalName())
);
DB::commit();
} catch(\Throwable $e) {
DB::rollback();
Log::error($e);
return $this->error($e->getMessage(), $e->getCode());
}
return $this->success('Nationalities Successfully Imported.', compact('file'));
}
Please, see how I removed a lot of code:
I have updated your validation, I know you were returning 401, but that is not correct, as you are having a validation error (422 error). If you still need 401 (that is unauthorized) you have to add your code again.
I have updated your if check, as it makes no sense to get the user and check if it is not null or undefined (undefined does not even exist in PHP, that should be a PHP error). It makes no sense, because you are using Auth::user()->id or Auth::id() (both are the same), and you will always get a user back, so why go to the database and get it again ? You already have it...
If you want to check if the user is logged in or similar, you have to add a middleware to the route... If you are in this part of the controller, it means that the previous layer "authorized" the entry to it, so it is the route's middleware responsibility to allow or not, not the controller in this case.
And if you want to still do that in the controller, simply do ->first() instead of ->pluck('id') and check if the variable is null or not.
I updated your catch exception, try to stick to Throwable as it is more correct. You can google more about it.
If MySQL go down, there is any fallback options to log Failed Queue Jobs to file?
I try
namespace App\Providers\AppServiceProvider;
function register()
Queue::failing(function (JobFailed $event) {
if($event->exception instanceof \PDOException){
$data = [
'code' => $event->exception->getCode(),
'connectionName' => $event->connectionName,
'getQueue' => $event->job->getQueue(),
'getRawBody' => $event->job->getRawBody(),
'exception' => (string)$event->exception,
];
\App\Repositories\FailedJobMysqlDown::set($data);
}
});
but this check the reasons of jobs go down,
i wanna catch inserting into failed_jobs exception
[2002] No such file or directory (SQL: insert into `failed_jobs` (`connection`, `queue`, `payload`, `exception`, `failed_at`) values (redis, superhigh, {"ty................
Any Ideas?
Thanks
found solutions
Create class
<?php
namespace App\Override;
use Illuminate\Queue\Failed\FailedJobProviderInterface;
use Illuminate\Queue\Failed\DatabaseFailedJobProvider ;
use Illuminate\Support\Facades\Date;
class FallbackDatabaseFailedJobProvider extends DatabaseFailedJobProvider implements FailedJobProviderInterface
{
public function log($connection, $queue, $payload, $exception)
{
try{
return parent::log(...func_get_args());
}catch (\Exception $e) {
$failed_at = Date::now();
$exception = (string) $exception;
$data = [
'connectionName' => $connection,
'getQueue' => $queue,
'getRawBody' => $payload,
'exception' => $exception,
'failed_at' => $failed_at,
];
\App\Repositories\FailedJobMysqlDown::set($data);
}
}
}
and register it in serviceprovider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Override\FallbackDatabaseFailedJobProvider;
class FailedLogServiceProvider extends ServiceProvider
{
public function boot()
{
// Get a default implementation to trigger a deferred binding
$_ = $this->app['queue.failer'];
// Swap the implementation
$this->app->singleton('queue.failer', function ($app) {
$config = $this->app['config']['queue.failed'];
return new FallbackDatabaseFailedJobProvider($this->app['db'], $config['database'], $config['table']);
});
}
}
add to condig/app.php in providers
'providers' => [
..............
App\Providers\FailedLogServiceProvider::class,
]
use current or create your own implementation log function
<?php
namespace App\Repositories;
/**
* Log failed job to file fallback
*/
class FailedJobMysqlDown
{
private static $file = '_xlogJobFailedMysqlDown'; //set full path
public static function get(){
$x = file(self::$file);
$data = [];
foreach($x as $line){
$data[] = json_decode($line);
}
return $data;
}
public static function set($message){
$message = json_encode($message);
file_put_contents(self::$file,$message.PHP_EOL , FILE_APPEND | LOCK_EX );
}
}
voilà
I am using Laravel accessor to access value of date field in specific format. But, I am getting error from carbon library of InvalidArgument. Below is my code.
<?php
namespace App\modules\hrm;
use App\Helper\DateFormat;
use Illuminate\Database\Eloquent\Model;
class Holiday extends Model
{
protected $guarded = [];
protected $dates = ['off_date'];
public function setOffDateAttribute($date)
{
$this->attributes['off_date'] = DateFormat::convertToDBFormat($date);
}
public function getOffDateAttribute($date){
return DateFormat::convertToUIFormat($date);
}
}
Helper File
<?php
namespace App\Helper;
use Carbon\Carbon;
class DateFormat
{
public static function convertToDBFormat($date) {
return Carbon::createFromFormat('d/m/Y', $date)->format('Y-m-d');
}
public static function convertToUIFormat($date) {
return Carbon::createFromFormat('Y-m-d', $date)->format('d/m/Y');
}
}
?>
Model Function
public function show(Request $request)
{
$data = Holiday::find(json_decode($request->get('data'),true)['id']);
if (empty($data)) {
return response()->json(array("status" => "error", "message" => "Invalid ID"));
} else {
return response()->json(array("status" => "success", "data" => $data));
}
}
I am getting error from Carbon but I think I am doing something wrong while sending those values, maybe i am not using the laravel accessor feature properly.
Error:
"message": "Trailing data",
"exception": "InvalidArgumentException",