vendredi 18 août 2023

How to convert a mailable object to plain text version?

I have an old Laravel 5.7 application.

I have a mailable Illuminate\Mail\Mailable object.

I want to use a 3rd party to send my emails which is not within Laravel's default driver. For the API, I need to send the plain-text and the html-text of the mail.

I can retrieve html text like this:

$htmlText = $mailable->render();

But how to I retrieve the plain text?

This is my build of the mailable:

public function build()
{
    return $this->view('emails.newsletter.master')
                    ->text('emails.newsletter.master_text')
                    ->subject('Hallo');
} 

I could not find how to retrieve plain text from mailable from Laravel docs. I also did not find a method inside the Mailable class that would generate the text. I only see that the plain text blade path gets assigned to textView variable.



via Chebli Mohamed

jeudi 17 août 2023

after changing theme for one Mailable file in laravel it messup other email which dont have $theme variable set

below is my code to change the theme for particular emails where customize mailable is extended.

class TablerMailable extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Instruct to use tabler theme.
     *
     * @var string
     */
    public $theme = 'tabler';

    /**
     * Build the Markdown view for the message.
     *
     * @return array
     */
    protected function buildMarkdownView()
    {
        $markdown = Container::getInstance()->make(Markdown::class);
        $markdown->loadComponentsFrom([resource_path('views/vendor/tabler-mail')]);

        if (isset($this->theme)) {
            $markdown->theme($this->theme);
        }
        
        $data = $this->buildViewData();

        $views= [
            'html' => $markdown->render($this->markdown, $data),
            'text' => $this->buildMarkdownText($markdown, $data),
        ];
        
        return $views;
    }
}

my problem is other emails that don't extend this class also get affected by this change. I don't know how to unset this theme for those emails where the $theme variable is already not set.



via Chebli Mohamed

vendredi 11 août 2023

Unable to communicate with Sanctum - I am getting a 503 error

I have successfully set up Sanctum on Laravel 8. However, when I try to use Postman with the bearer token obtained from the personal_access_tokens table, I encounter the following error message. Could it be the stateful setting? As I am not communicating to the API form the same domain but from Postman and then my real project will be sending data from another window computer to my website. I have been for 4 days on this, I cannot find an answer to the issue.

"I would like to reassure you that the page is not undergoing maintenance(php artisan up)."

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>

<head>
    <title>503 Service Unavailable</title>
</head>

<body>
    <h1>Service Unavailable</h1>
    <p>The server is temporarily unable to service your
        request due to maintenance downtime or capacity
        problems. Please try again later.</p>
</body>

</html>

api.php:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\V2\Api\KeywordsController;


Route::middleware(['auth:sanctum', 'abilities:db:view,db:update,db:store'])->group(function () {
        Route::get('fetch-keyword', [KeywordsController::class, 'fetchKeyword']);
        Route::put('update-keyword/{keywordName}', [KeywordsController::class, 'updateKeyword']);
});

auth.php:

<?php

return [

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'sanctum',
            'provider' => 'users',
            'hash' => false,
        ],
    ],


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

    ],

    'verification' => [
        'expire' => 1440,
    ],


    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 180,
            'throttle' => 60,
        ],
    ],

    'password_timeout' => 10800,

];

Sanctum.php:

<?php

use Laravel\Sanctum\Sanctum;

return [

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),


 'guard' => ['api'],

    'expiration' => null,

    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],

];

Traits in the User Model:

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Paddle\Billable;
use Spatie\Permission\Traits\HasRoles;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasFactory, Notifiable, Billable, HasRoles;

.....more code not attached

Kernal.php:

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];


    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
        'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class,
        'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class,
    ];

}

This is how my token is created:

 public function update(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => ['required', Rule::unique('users')->ignore($id)],
            'has_token' => 'nullable|boolean',
            'password' => $request->filled('password') ? 'required|min:8' : '',
            'token_name' => [
                'nullable',
                'string',
                Rule::requiredIf(function () use ($request) {
                    return $request->has_token === 1;
                }),
            ],
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        try {
            $user = User::find($id);

            if ($request->email !== $user->email) {
                return $this->changeEmail($request->email, $request->password, $id);
            }

            // Update fields
            $user->name = $request->name;
            $user->current_credits = $request->current_credits;

            if ($request->filled('password')) {
                $user->password = Hash::make($request->password);
            }

            $user->save();

            $user = User::where('email', $request->email)->first();
            if ($request->has_token === 1 && $request->filled('token_name')) {
                $user->createToken($request->token_name, ['db:view', 'db:update', 'db:store']);
            } elseif ($request->has_token === 0) {
                $user->tokens()->delete(); 
            }

        } catch (Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }

        return response()->json(['success' => 'success'], 200);
    }

I can see the token in the database, image attached: https://i.stack.imgur.com/az8vS.png

Thanks in advance!



via Chebli Mohamed

mercredi 9 août 2023

laravel 5 error: SQLSTATE[42000]: Syntax error or access violation: 1305 SAVEPOINT trans2 does not exist

I have a question about Laravel 5.7. I have a multi-tenant project, and the issue is that when generating migrations, the admin is created without any problems. However, when I try to create a client, the client's database is not created, and the following error appears:

SQLSTATE[42000]: Syntax error or access violation: 1305 SAVEPOINT trans2 does not exist

The problem seems to be related to the database, in my case, mysql Ver 14.14 Distrib 5.7.43, Laravel 5.7 and PHP 7.4.33. I hope someone has found a solution. Thanks in advance.

Add my MySQL user in the .env file, but it's not creating the client's database.



via Chebli Mohamed

Error "Whoops, looks like something went wrong." in Laravel page

First of all thank you very much for reading me and helping me in this as I am a newbie in laravel.

I have done a deployment of a website given to me by a company and everything works except the search in the post_categories table in the database.

When I enter a link that performs a query to the database to get all the posts of that category I get the following error (In this case for category 13):

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '>'$. "en"' asc' at line 1 (SQL: select * from `post_categories` where `post_categories`.`parent_id` = 13 and `post_categories`.`parent_id` is not null order by `title`->'$. "en"' asc)

However, if I go directly to any post in that category it is perfectly visible, so it is affecting only the search engine.

The error is caused because the title->'$. "es"' part doesn't seem to work, but I don't know why, since the query is generated directly from here as far as I can tell from reading the code.

public function select($query, $bindings = [], $useReadPdo = true)
    {
        return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
            if ($this->pretending()) {
                return [];
            }

            // For select statements, we'll simply execute the query and return an array
            // of the database result set. Each element in the array will be a single
            // row from the database table, and will either be an array or objects.
            $statement = $this->prepared($this->getPdoForSelect($useReadPdo)
                              ->prepare($query));

            $this->bindValues($statement, $this->prepareBindings($bindings));

            $statement->execute();

            return $statement->fetchAll();
        });
    }

I thought that maybe it is failing some php variable that is not being defined well, but I have not touched any of the code since I have only deployed and the web, on the company's server, makes the search correctly.

Would anyone know how to guide me to solve this error?

Thank you all!

all the data and evidence have been provided above



via Chebli Mohamed

vendredi 4 août 2023

Invalid XSL format (or) file name when running php artisan commands on laravel 5.8

I'm getting the "Invalid XSL format (or) file name" error message when running php artisan commands, its only on my laravel 5.8 project, in others it runs perfectly

The command works but take way too long, occurs only in this project, anyone knows why is that?

I tried a feel solutions directly in the windows, but the commands works in others projects, so the problemn is in the project



via Chebli Mohamed

mercredi 2 août 2023

How to implement aws cloudfront in my laravel application?

Here is the code already used in my laravel application. This code directly get image url from my s3 storage. But I need to implement cloudfront and generate signed url for to get and download images.

foreach($fileInfos['files'] as $file) {
       $dlFileName = $file['name'];
       $fileDLUrls[] = FileIO::getUrl(FILE_ORIGINAL_DIRECTORY . '/'.$file['path'], $effectiveTime, ['ResponseContentType' => 
'application/octet-stream','ResponseContentDisposition' => 
'attachment; filename*=UTF-8\'\''. rawurlencode($dlFileName)]);
}
    public static function getUrl($fullPathName, $expires = '+1440 minutes', $headers = [])
    {
        if ($fullPathName == '') {
            return null;
        }

        switch (Storage::getDefaultDriver()) {
            case 's3':
                $disk = Storage::disk('s3');
                $headers = array_merge([
                    'Bucket' => env('AWS_S3_BUCKET'),
                    'Key' => $fullPathName
                ], $headers);
                $command = $disk->getDriver()
                    ->getAdapter()
                    ->getClient()
                    ->getCommand('getObject', $headers);
                $request = $disk->getDriver()
                    ->getAdapter()
                    ->getClient()
                    ->createPresignedRequest($command, $expires);
                return (string) $request->getUri();
            case 'local':
                return URL::to('/' . env('AWS_LOCAL_UPLOADDIR')) .
                         '/' . $fullPathName;
            default:
                return null;
        }
    }

I have changed above code as below,

public static function getUrl($fullPathName, $expires = '+1440 minutes', $headers = [])
    {
        if ($fullPathName == '') {
            return null;
        }


        switch (Storage::getDefaultDriver()) {
            case 's3':
                $resourceKey = env('CLOUDFRONT_URL').$fullPathName;
                $expired = strtotime($expires);
                $privateKey = env('AWS_PRIVATE_KEY');
                $keyPairId = env('AWS_KEY_PAIR_ID');
                
                $cloudFrontClient = new CloudFrontClient([
                    'profile' => 'default',
                    'version' => '2014-11-06',
                    'region' => env('AWS_REGION')
                ]);
                    $result = $cloudFrontClient->getSignedUrl([
                        'url' => $resourceKey,
                        'expires' => $expired,
                        'private_key' => $privateKey,
                        'key_pair_id' => $keyPairId,
                        
                    ]);
                    
                    return $result;
            case 'local':
                return URL::to('/' . env('AWS_LOCAL_UPLOADDIR')) .
                    '/' . $fullPathName;
            default:
                return null;
        }
    }

But I didn't use the headers in the first code. So that am not able to download the images. Can anyone help me to know about the reason or any solutions?



via Chebli Mohamed