laravel 5.3 sendgrid categories - laravel

In laravel 5.2 this worked just fine, but since migrating to 5.3 i'm having issues getting the category sent in my email.
public function build()
{
return $this->view('mail.enquiry')
->getSwiftMessage()->getHeaders()->addTextHeader('X-SMTPAPI', json_encode(array("category" => array(env('BUSINESS_NAME')))))
->subject('Website Enquiry')
->to(env('MAIL_DEFAULT_TO_EMAIL'), env('MAIL_DEFAULT_TO_NAME'))
->from(env('MAIL_DEFAULT_FROM_EMAIL'), env('MAIL_DEFAULT_FROM_NAME'))
->replyTo(\Request::get('email'), \Request::get('full_name'));
}
i get this error
BadMethodCallException in Mailable.php line 525:
Method [getSwiftMessage] does not exist on mailable.
every thing in this code works fine, but breaks as soon as I add this line:
->getSwiftMessage()->getHeaders()->addTextHeader('X-SMTPAPI', json_encode(array("category" => array(env('BUSINESS_NAME')))))

To achieve what you're after you can use the withSwiftMessage() method.
This method takes a callback which will be passed the instance of SwiftMessage:
->withSwiftMessage(function ($message) {
$message->getHeaders()->addTextHeader('X-SMTPAPI', json_encode(array("category" => array(env('BUSINESS_NAME')))));
})
So your method would look something like:
public function build()
{
return $this->view('mail.enquiry')
->withSwiftMessage(function ($message) {
$message->getHeaders()->addTextHeader('X-SMTPAPI', json_encode(array("category" => array(env('BUSINESS_NAME')))));
})
->subject('Website Enquiry')
->to(env('MAIL_DEFAULT_TO_EMAIL'), env('MAIL_DEFAULT_TO_NAME'))
->from(env('MAIL_DEFAULT_FROM_EMAIL'), env('MAIL_DEFAULT_FROM_NAME'))
->replyTo(\Request::get('email'), \Request::get('full_name'));
}
Hope this helps!

Since I visited this question when looking for a solution on Laravel 8 I'm adding some more info to the already accepted answer:
In Laravel 8 now you can follow instructions here: https://sendgrid.com/docs/for-developers/sending-email/laravel/ and check section titled "Adding a category or custom field".
It does still use withSwifthMessage() - more info for this on laravel's site: https://laravel.com/docs/8.x/mail#customizing-the-swiftmailer-message
The gist of it is simillar to the already accepted answer, but provides some nice helpers too and clearer code:
In your build() function:
$headerData = [
'category' => 'category',
'unique_args' => [
'variable_1' => 'abc'
]
];
$header = $this->asString($headerData);
$this->withSwiftMessage(function ($message) use ($header) {
$message->getHeaders()
->addTextHeader('X-SMTPAPI', $header);
});
return $this->view('emails.test')
->from($address, $name)
Helpers:
private function asJSON($data)
{
$json = json_encode($data);
$json = preg_replace('/(["\]}])([,:])(["\[{])/', '$1$2 $3', $json);
return $json;
}
private function asString($data)
{
$json = $this->asJSON($data);
return wordwrap($json, 76, "\n ");
}
Might be useful to someone.

Related

laravel 8 passing data to redirect url

i have store function for save data to database and i want redirect to another url with passing $invoice variable
this is my store function :
$order = Order::create([
'no' => $invoice,
'spg' => $request->spg,
'nama' => $request->nama,
'hp' => $request->hp,
'alamat' => $request->alamat,
]);
return redirect('invoicelink', compact('invoice'));
this is my route file:
Route::resource('/', OrderController::class);
Route::get('invoicelink/{invoice}', [OrderController::class, 'invoicelink'])->name('invoicelink');
and this is my invoicelink function:
public function invoicelink($invoice)
{
dd($invoice);
}
How to do it? very grateful if someone help to solve my problem. thanks
If you look at the helper function you are calling, I don't think it is what you are looking for.
function redirect($to = null, $status = 302, $headers = [], $secure = null)
{
if (is_null($to)) {
return app('redirect');
}
return app('redirect')->to($to, $status, $headers, $secure);
}
I think what you want is
Redirect::route('invoiceLink', $invoice);
You can also use the redirect function, but it would look like this
redirect()->route('invoiceLink', $invoice);
You can see this documented here https://laravel.com/docs/8.x/responses#redirecting-named-routes
i found the solution:
web.php
Route::get('invoicelink/{invoice}', [OrderController::class, 'invoicelink'])->name('invoicelink');
controller:
public function invoicelink($invoice)
{
//dd($invoice);
return $invoice;
}
then use redirect:
return redirect()->route('invoicelink', [$invoice]);

How to check data exists in the database

I have a function to add new property. But i want to check for duplicate data at column "code" before add new data into database. If data exists will appear a message error.
function addPro(Request $req)
{
$id = $req->type_id;
$type = AssetType::find($id);
if($req->save == 'save'){
$pro = new TypeProperties;
$pro->name = $req->name;
$pro->code = $req->code;
$pro->type = $req->type;
$pro->assettype_id = $req->type_id;
$pro->save();
Schema::table($type->code, function ($table) use ($pro) {
if ($pro->type == "textbox")
$table->string($pro->code )->nullable();
if ($pro->type == "textarea")
$table->text($pro->code )->nullable();
});
return redirect(url($type->id.'/add/property'))->with('message','Save successful');
}
return redirect(url('asset/type/'.$type->id));
}
You can use laravel Request Validation
function addPro(Request $req)
{
$id = $req->type_id;
$type = AssetType::find($id);
if($req->save == 'save'){
$req->validate([
'code' => 'required|unique:tablename'
]);
$pro = new TypeProperties;
$pro->name = $req->name;
$pro->code = $req->code;
$pro->type = $req->type;
$pro->assettype_id = $req->type_id;
$pro->save();
Schema::table($type->code, function ($table) use ($pro) {
if ($pro->type == "textbox")
$table->string($pro->code )->nullable();
if ($pro->type == "textarea")
$table->text($pro->code )->nullable();
});
return redirect(url($type->id.'/add/property'))->with('message','Save successful');
}
return redirect(url('asset/type/'.$type->id));
}
The most simple way to do this is by checking if code is_null :
if (is_null($pro->code)) {
// It does not exist
} else {
// It exists
}
The other way is to make a validation using Laravel's built in ValidateRequest class. The most simple use-case for this validation, is to call it directly in your store() method like this:
$this->validate($req, [
'code' => 'required|unique,
//... and so on
], $this->messages);
With this, you're validating users $req by saying that specified columns are required and that they need to be unique, in order for validation to pass. In your controller, you can also create messages function to display error messages, if the condition isn't met:
private $messages = [
'code.required' => 'Code is required',
'code.unique' => 'Code already exists',
//... and so on
];
You can also achieve this by creating a new custom validation class:
php artisan make:request StorePro
The generated class will be placed in the app/Http/Requests directory. Now, you can add a few validation rules to the rules method:
public function rules()
{
return [
'code' => 'required|unique,
//... and so on
];
}
All you need to do now is type-hint the request on your controller method. The incoming form request is validated before the controller method is called, meaning you do not need to clutter your controller with any validation logic:
public function store(StorePro $req)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $req->validated();
}
If you have any additional question about this, feel free to ask. Source: Laravel official documentation.
What does your migration look like for AssetType?
I ask because you can do this in the schema with ->unique() added to the column on the creation or make a migration to add the constraint.
You can also check with something like this:
// Search database table for entry
$entry = AssetType::where('code', '=', $pro->code)->first();
// If not found
if ($entry === null) {
// Save method here.
}
Otherwise, you can use the manual validator or create a Request with validation
References:
https://laravel.com/docs/5.8/queries#where-clauses
https://laravel.com/docs/5.8/validation#creating-form-requests
https://laravel.com/docs/5.8/validation#manually-creating-validators

Laravel blog slug route definition

I am following a blog tutorial and i found this interesting blog route used to display a blog post
http://sweet-blog.herokuapp.com/interesting-articles-wide-pharmaceutical-and-produts
This is the migration file https://github.com/28harishkumar/blog/blob/master/database/migrations/2015_05_23_133926_posts.php
This is the function https://github.com/28harishkumar/blog/blob/master/app/Http/Controllers/PostController.php#L85
public function show($slug)
{
$post = Posts::where('slug',$slug)->first();
if($post)
{
if($post->active == false)
return redirect('/')->withErrors('requested page not found');
$comments = $post->comments;
}
else
{
return redirect('/')->withErrors('requested page not found');
}
return view('posts.show')->withPost($post)->withComments($comments);
}
and this is the route
https://github.com/28harishkumar/blog/blob/master/app/Http/routes.php#L62
Route::get('/{slug}',['as' => 'post', 'uses' => 'PostController#show'])->where('slug', '[A-Za-z0-9-_]+');
When i look at this lines
public function show($slug)
{
$post = Posts::where('slug',$slug)->first();
is laravel getting the slug for us without using $request to get the uri segment?
If so, how would we handle multiple parameters in the uri?.
multiple parameters in the uri can be as:
Route::get('/{slug}/{other}',['as' => 'post', 'uses' => 'PostController#show'])->where('slug', '[A-Za-z0-9-_]+');
Here I used other as a second parameter to this uri.You can use many parameters as per your requirements.
In Controller:
public function show($slug, $other) {
// Your code here
}
Hope it helps.

URL friendly in routes

I'm creating url friendly in my app, but it's not working, the app is giving me some issues related with "-".
It's giving me an error of:
ErrorException in PostController.php line 60:
Trying to get property of non-object
My ideal URL is:
http://domain.com/CATEGORY-title-of-post-ID
My route is:
Route::get('{category}-{title}-{id}', 'PostController#show');
PostController show function:
public function show($category,$title,$id)
{
$post = Post::find($id);
$user = Auth::user();
$comments = Comment::where('post_id',$id)
->where('approved',1)
->get();
return view('posts.show',compact('post','comments','user'));
}
Blade View:
<?php
$title_seo = str_slug($feature->title, '-');
?>
<a href="{{url($feature->categories[0]->internal_name."-".$title_seo."-".$feature->id)}}" rel="bookmark">
...</a>
There's a library called Eloquent-Sluggable that will create a unique slug for each post and correctly URL encode it.
To install (taken from the docs):
composer require cviebrock/eloquent-sluggable:^4.1
Then, update config/app.php by adding an entry for the service provider.
'providers' => [
// ...
Cviebrock\EloquentSluggable\ServiceProvider::class,
];
Finally, from the command line again, publish the default configuration file:
php artisan vendor:publish --provider="Cviebrock\EloquentSluggable\ServiceProvider"
To use, add the Sluggable trait to your model:
use Cviebrock\EloquentSluggable\Sluggable;
class Post extends Model
{
use Sluggable;
/**
* Return the sluggable configuration array for this model.
*
* #return array
*/
public function sluggable()
{
return [
'slug' => [
'source' => 'title'
]
];
}
}
When you save an instance of your model, the library will automatically create a slug and save it to the newly created slug column of your model's table. So to access the slug you'd use $model->slug
To achieve your desired slug, rather than create it from title set by default. You can pass the source attribute of the sluggable method an array of field names, using a dot notation to access the attributes of a related model, like so:
public function sluggable()
{
return [
'slug' => [
'source' => ['category.name','title','id']
]
];
}
}
Why are you genering your "friendly URL" manually?
You have route helper function that builds for you a URL based on the given parameters.
Route::get('{category}-{title}-{id}', [
'as => 'post.show',
'uses' => 'PostController#show'
]);
echo route('post.show', ['testing', 'title', 'id']); // http://domain.dev/testing-title-id
This is not the best approach to implement SEO friendly URLs, anyway.
In your controller you ALWAYS use your ID to find a post, that means that category and title are completely useless to determine which resource needs to be served to the user.
You can make your life easier by doing something like:
Route::get('{id}-{slug}', [
'as => 'post.show',
'uses' => 'PostController#show'
]);
echo route('post.show', ['id', 'slug']); // http://domain.dev/id-slug
In your model you create an helper function that generates the slug for your post:
class Post
{
[...]
public function slug()
{
return str_slug("{$this->category}-{$this->title}");
}
}
Then, in your controller you need to check that the slug used to access the article is correct or not, since you don't want Google to index post with wrong slugs. You essentially force a URL to be in a certain way, and you don't lose index points.
class PostController
{
[...]
public function show($id, $slug)
{
$post = Post::findOrFail($id);
$user = Auth::user();
if ($post->slug() !== $slug) {
return redirect()->route('posts.show', ['id' => 1, 'slug' => $post->slug()]);
}
$comments = Comment::where('post_id', $id)->where('approved', 1)->get();
return view('posts.show', compact('post', 'comments', 'user'));
}
}

Laravel password recovery template

I have the following code which sends a passowrds recovery mail:
public function recovery(Request $request)
{
$validator = Validator::make($request->only('email'), [
'email' => 'required'
]);
if($validator->fails()) {
throw new ValidationHttpException($validator->errors()->all());
}
$response = Password::sendResetLink($request->only('email'), function (Message $message) {
$message->subject(Config::get('boilerplate.recovery_email_subject'));
});
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->response->noContent();
case Password::INVALID_USER:
return $this->response->errorNotFound();
}
}
Which I found out uses the following template: resources/views/auth/emails/password.php
which is an empty file.
How I can access the token from this template?
Isn't there any built-in view to use from laravel?
The function in your questions doesn't return a view.
Also, I'm unfamiliar with that path to the view that is in your question. Which version of Laravel are you using?
Anyhow, you can get the reset token from the DB, just like any other value in the DB. E.g. from a controller that is returning a view:
$user = User::find(Auth::id());
$remeber_token = $user->remember_token;
return view('to_your_view.blade.php', compact('remember_token');
And then in the view file:
{{ $remember_token }}
This will output it, no need to use echo or anything.
But, again, the function you pasted into your question is not a function that is returning a view, so I'm not sure where to tell you to put the above code.
As for your questoin about Laravel having an in-built view for 'this', in Laravel 5.3, at least, the view I assume you want will be within `resources/views/auth/passwords/'.

Resources