Send single email according to Weblesson - ajax

I'm new to programming, currently searching for ways to only send a single email like what Web lesson had taught me (bulk email I don't want), here is the link:'How to Send Bulk Email in PHP using PHPMailer with Ajax JQuery'.
I have two places to run this function, one is index.blade.php, and one is ClientController.
index.blade.php
<form action="{{ route('clients.destroy',$client->id) }}" method="POST">
<a href="{{ route('clients.edit',$client->id) }}">
<i class="fas fa-pencil-alt"></i>
</a>
<button type="button" name="email_button" class="email_button"
id="{{ $client->_id }}"
method="post" action="single" email_data="{{ $client->email }}">
<i class="fas fa-envelope"></i>
</button>
#csrf
#method('DELETE')
<button type="submit"><i class="far fa-trash-alt"></i></button>
</form>
here's my JQuery and Ajax at the bottom of index.blade.php
<script>
$(document).ready(function(){
$('.email_button').click(function(){
$(this).attr('disabled', 'disabled');
var id = $(this).attr("id");
var action = $(this).data("action");
var email_data = $(this).data("email_data");
$.ajax({
url:'{{ route('send-email-test') }}',
method:'POST',
data:{email_button: email_data, _token: '{{csrf_token()}}'},
beforeSend:function(){
$('#'+id).html('Sending...');
$('#'+id).addClass('uk-text-danger');
},
success:function(data){
if(data = 'ok')
{
$('#'+id).text('Success');
$('#'+id).removeClass('uk-text-danger');
$('#'+id).removeClass('uk-text-info');
$('#'+id).addClass('uk-text-success');
}
else
{
$('#'+id).text(data);
}
$('#'+id).attr('disabled', false);
}
});
});
});
</script>
Here's my route and script
// Here's my script in layout
<script src="{{ asset('js/jquery.min.js') }}" type="text/javascript"></script>
// Here's my route
Route::post('send-email-test','ClientController#send_mail')->name('send-email-test');
After creating the index, I'm trying to use ajax to route to my controller.
ClientController
namespace App\Http\Controllers;
use App\Models\Company\Client\Client;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
class ClientController extends Controller
{
public function send_mail()
{
if(isset($_POST["email_data"]))
{
require 'vendor/phpmailer/phpmailer/src/Exception.php';
require 'vendor/phpmailer/phpmailer/src/PHPMailer.php';
require 'vendor/phpmailer/phpmailer/src/SMTP.php';
require 'class/class.phpmailer.php';
$output = '';
foreach($_POST['email_data'] as $row)
{
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->Port = '587'; //Initially is 465, doesn't work
$mail->SMTPAuth = true;
$mail->Username = 'xxxxxxx#gmail.com';
$mail->Password = 'xxxxxxx';
$mail->SMTPSecure = 'tls'; //Initially is SSL, doesn't work either
$mail->From = 'xxxxxxxx#gmail.com';
$mail->FromName = 'Coverage Giant';
$mail->addAddress($row["email_data"]);
$mail->To($row["email_data"]);
$mail->WordWrap = 50;
$mail->IsHTML(true);
$mail->Subject = 'Welcome To Coverage Giant';
$mail->Body = '
<p>Sed at odio sapien. Vivamus efficitur</p>
';
$mail->AltBody = '';
$client_email = $mail->Send();
if($$client_email["code"] == '400')
{
$output .= html_entity_decode($client_email['full_error']);
}
}
if($output == '')
{
echo 'ok';
}
else
{
echo $output;
}
}
}
}
As you can see, I'm doing something opposite from the Web lesson because Webslesson uses index.php and send_mail.php, I'm using index.blade.php and ClientController. Since after applying what Websleeson has shown to me, it doesn't function well, so I reverse the engine a bit, thinking maybe it might work the other way round.
My problem now is, my JQuery and Ajax are functioning correctly, and it's able to route to ClientController from index.blade.php. Still, after routing to the controller, it seems that I can't send a single email using PHPMailer; maybe something is wrong with my controller and PHPMailer?
I was also wondering, is there a better way to send a single email?
BTW, I'm using MongoDB and Laravel. My UI is Uikit instead of Boostrap.

Since you're using Laravel, it is indeed easier to use Laravel's built-in mail classes, but you've got this far with PHPMailer so I'll help you clean this up...
You're loading two different copies of PHPMailer at the same time. This is very likely to cause major problems! class.phpmailer.php is from a very old version that you should not be using. It also looks like you have based your code on a very old PHPMailer example – use the latest ones from the repo.
If you're using composer properly (which you should be given you've set up a Laravel project), you should not need any of those require lines - the autoloader will load the classes for you if you added phpmailer/phpmailer to your composer.json requires, as described in the readme.
Port should be an integer, not a string:
$mail->Port = 465;
There is no To() method; call addAddress to add recipients.
When sending multiple messages in a loop, create the instance outside the loop, and re-use it for each message, remembering to call $mail->clearAddresses(); at the end of each iteration, as shown in the mailing list example.
This is peculiar code, and wrong because send() returns a boolean, not an array:
if($$client_email["code"] == '400')
and it doesn't provide code or full_error properties. You're looking for ErrorInfo, as shown in all the examples.
Overall, always refer to the original docs and examples when using any open source package – making up random stuff and expecting it to work is not going to serve you well.

Related

Getting response back from server but .html not sowing anything in wordpress ajax

On click I'm sending the id as data and then using query showing the name of user from WordPress database. I'm getting the response back from server but It is not adding when try to use .html(response).May be this is something to do with permission ?Like only admin can use the response?
If that's the case what I can do.
This is the ajax function:
function get_user_id() {
let get_current_user_id =jQuery(this).attr('id');
cur_user = '<?php echo get_current_user_id() ;?>';
var postdata_name = {action: "incoming_user_name_ajax_call",
param_user_to_chat: get_current_user_id,};
jQuery.post(ajaxurl, postdata_name, function (response) {
jQuery("#name-incoming-user").html(response);});
}
This is the function in functions.php
add_action("wp_ajax_incoming_user_name_ajax_call", "incoming_user_name_ajax_call_fn");
add_action("wp_ajax_nopriv_incoming_user_name_ajax_call", "incoming_user_name_ajax_call_fn");
function incoming_user_name_ajax_call_fn() {
global $wpdb;
$param_user_to_chat=isset($_REQUEST['param_user_to_chat'])?trim($_REQUEST['param_user_to_chat']):"";
if (!empty($param_user_to_chat)) {
$posts = $wpdb->get_results("SELECT distinct(display_name) FROM wp_users where
ID=$param_user_to_chat");
echo $posts[0]->display_name;
}
wp_die();}
Posting the HTML as well for everyone who want to know what jQuery(this).attr('id'); is doing. It is getting id "4" or "2" depending on click.
<div id="target">
<div class="user-list-hide" id="user-hide" style="display: block;">
<div id="4"><span>Jason Bradley</span>/div>
<div id="2"><span>John Saddington</span></div>
</div>
</div>
There was issue in your jquery code i.e : the way you were calling your get_user_id() function here you have use wrong selector to get your inner divs . So, to make it work change :
jQuery("#target").on("click", "div", get_user_id);
to
jQuery("#user-hide").on("click", "div", get_user_id);

Cloning item. The GET method is not supported for this route. Supported methods: POST

I'm trying to clone a model but when I try to I get the error in the title. This is what I'm doing
Button in vue.js
<a class="btn-link-clone action-button" :href="'survey/clone/'+scope.row.id">
<i class="fas fa-clone col-margin"></i>
</a>
Route in web.php
Route::post('survey/clone/{id}', 'SurveyController#cloneSurvey');
CloneSurvey in SurveyController
public function cloneSurvey($id)
{
$survey = Survey::findOrFail($id);
DB::beginTransaction();
$now = Carbon::now();
$activePeriod = Period::whereDate('start_date', '<=', $now)
->whereDate('end_date', '>=', $now)->get();
$clone = new Survey();
$clone->fill($survey->toArray());
$clone->name .= ' Clonado';
$clone->save();
$eval = Evaluation::findOrFail($clone->id);
if (empty($eval)) {
$eval = new Evaluation();
}
$eval->survey_id = $clone->id;
if (!empty($activePeriod)) {
$eval->init_date = $activePeriod->start_date;
$eval->end_date = $activePeriod->end_date;
}
$report = $activePeriod->end_date;
$date = strtotime($report);
$date = strtotime('+ 1 week', $date);
$eval->report_date = $date;
$eval->save();
$questions = $survey->surveyQuestions()->get()->pluck('survey_question_id')->toArray();
if (count($questions) > 0) {
$clone->surveyQuestions()->sync($questions);
}
DB::commit();
return back();
}
What is making this happen?
I've also tried this
button in vue.js
<div class="btn-link-clone action-button"
#click="clone(scope.row)">
<i class="fas fa-clone col-margin"></i>
</div>
method in vue.js
clone(row) {
this.$http.post('survey/clone/' + row.id)
.then(
() => {
this.surveys = this.$page.surveys;
},
(res) => {}
)
},
with the route the same and I get a 419 (unknown status)
You need your Route to use the get method rather than the post method. Like so:
Route::get('survey/clone/{id}', 'SurveyController#cloneSurvey');
When a user clicks on a link, that is almost always a GET request.
EDIT:
Based on the comments, I agree that changes should not be done via a get request anyway. This example should be a POST request.
Your Vue component:
<template>
...
<form>
<button
class="btn-link-clone action-button"
#click.prevent="submit(scope.row.id)"
>
<i class="fas fa-clone col-margin"></i>
</button>
</form>
...
</template>
<script>
export default {
...
methods: {
submit (id) {
// use whatever http request library you choose to execute POST HTTP request.
}
}
...
</script>
Alternatively, you could use #submit.prevent on the form tag instead of the #click.prevent on the button.
Then, as long as scope.row.id was defined on the frontend, you can use:
Route::post('survey/clone/{id}', 'SurveyController#cloneSurvey');
The GET method is not supported for this route. Supported methods: POST
You are making a GET request to a Route that only supports the POST method.
Either your vue app is making a ajax request to your server with missing headers or form incorrect form action.
You may also be passing something like a GET parameter as part of your request
i.e. http://my-app/api/example?var1=asdasdasdas

how construct route pattern for an unknown number of tags - Laravel & Conner/Taggable

I have a blog and a quotationfamous sayings repository on one site.
The quotations are tagged and the entries are tagged too.
I use this rtconner/laravel-tagging package.
Now, what I want to do is to display ALL Quotation models which share the same tags as article.
The Eloquent syntax is simple, as the original docs provide an example:
Article::withAnyTag(['Gardening','Cooking'])->get();
possible solution
Optional routing parameters. The asker-picked answer in this question gives a solution:
//in routes.php
Route::get('/{book?}/{chapter?}/{topic?}/{article?}', 'controller#func');
//in your controller
public function func($book = null, $chapter = null, $topic = null, $article = null) {
...
}
my problem
In my app the shared tags might count more than 3 or 5. I will soon get an example with even 10 tags. Possibly more
My question
Does it mean that I have to construct an URL with 10 optional routing parameters? Do I really need sth like this:
Route::get('quotations/tags/{tag1?}/{tag2?}/{tag3?}/{tag4?}/{tag5?}/{tag6?}/{tag7?}', 'controller#func');
my question rephrased
I could create a form with only a button visible, and in a hidden select field I could put all the tags. The route would be a POST type then and it would work. But this solution is not URL-based.
I think you could process the slashes, as data:
Route::get('quotations/tags/{tagsData?}', 'controller#func')
->where('tagsData', '(.*)');
Controller:
public function controller($tagsData = null)
{
if($tagsData)
{
//process
}
}
Ok, this is my solution. As I have a tagged model, I dont't need to iterate through tags in url to get the whole list of tags.
The enough is this:
// Routes file:
Route::get('quotations/all-tags-in/{itemtype}/{modelid}', 'QuotationsController#all_tagged_in_model');
Then in my controller:
public function all_tagged_in_topic($itemtype, $id) {
if($itemtype == 'topic') {
$tags = Topic::find($id)->tags->pluck('name')->all();
$topic = Topic::find($id);
}
if($itemtype == 'quotation') {
$tags = Quotation::find($id)->tags->pluck('name')->all();
$quotation = Quotation::find($id);
}
// dd($tags);
$object = Quotation::withAnyTag($tags)->paginate(100);;
And it is done.
Now, the last issue is to show tags in the URL.
TO do that, the URL should have an extra OPTIONAL parameter tags:
// Routes file:
Route::get('quotations/all-tags-in/{itemtype}/{modelid}/{tags?}', 'QuotationsController#all_tagged_in_model');
And in the {url?} part you can just write anything which won't break the pattern accepted by route definition.
In your view you might generate an URL like this:
// A button to show quotes with the same set of tags as the article
// generated by iteration through `$o->tags`
<?php
$manual_slug = 'tag1-tag2-tag3-tag4`;
?>
<a href="{{ URL::to('quotations/all-tags-in/article/'.$o->id.'/'.$manual_slug) }}" class="btn btn-danger btn-sm" target="_blank">
<i class="fa fa-tags icon"></i> Tagi:
</a>

How to add/include views in Laravel using Ajax

I'm bit stuck at a place. I've got some views of small HTML sections which when combined gives the complete HTML page. I'm trying to build a website builder with Jquery, where I'm having a drop event which adds those particular views:
For example I've got HTML for slideshow:
<div id="slideshow" data-nitsid="2">
<div class="revolution-slider">
<ul>
<!-- SLIDE -->
#foreach($contents->slider as $sliders)
<li data-transition="{{ $sliders->transition }}" data-slotamount="{{ $sliders->slotamount }}" data-masterspeed="{{ $sliders->masterspeed }}">
<!-- MAIN IMAGE -->
<img src="{{ URL::asset($sliders->url) }}" alt="">
</li>
#endforeach
</ul>
</div>
</div>
In my JQuery code:
nitsbuilder.dropeventhandler = function ($item, $position) {
var nits_id = $item.data('nitsid');
$.ajax({
method: 'POST',
url: dropurl,
data: { nits_id: nits_id, _token: token},
dataType: 'json',
success: function (data) {
nitsbuilder.adder($item, $position, data);
}
});
}
Before I was having html codes in the database so it was easier to pull out the html and add to the HTML page, now I'm having html in views, how can I push/include this HTML code or view to ajax request so that my nitsbuilder.adder function executes placing the view through my controller.
My present Controller is:
class DropeventController extends Controller
{
public function htmlcode(Request $request)
{
$pluginid = $request['nits_id'];
$code = Plugins::findOrFail($pluginid);
$htmlcode = $code->code;
return response()->json(['htmlcode' => $htmlcode]);
}
}
Please guide me. Thanks
You can easily create html strings from blade views using \View::make
e.g. let's assume you have the following folder strucutre
project
...
ressources
views
snippets
snippetA
snippetB
You could now create a route / controller accepting a "name" parameter and then do the following
$name = "snippetA"; // get this from parameters
$html = \View::make("snippets.$name")->render();
You might need to also add variables depending on your views
$name = "snippetA"; // get this from parameters
$errors = []; // error variable might be needed
$html = \View::make("snippets.$name", compact('errors'))->render();
You can then return this html string
return ['html' => $html];
And access it from your ajax done function.
I hope this helps
Suppose your html is in view file called abc.blade.php, you can return the rendered view from your controller in json.
return response()->json([
'htmlcode' => View::make('abc')->render();
]);

AJAX doesn't work

My JQuery does not fire up the sanitize function.I need to take the value from the input field name ,and display it in path input field. Why isn't it working ? The page where all this code is written is called new_page.php , so when the ajax_request function gets fired it does not point to an external page but here on the same page. I use PHP 5.3 and HEIDISQL
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<?php
include('conect.php');
if(($_POST)&&(!empty($_POST['name']))&&(!empty($_POST['path'])) ){
$name=$_POST['name'];
$path=$_POST['path'];
if(isset($_POST['sanitize'])) {
$title=$_POST['sanitize'];
$title = strip_tags($title);
// Preserve escaped octets.
$title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title);
// Remove percent signs that are not part of an octet.
$title = str_replace('%', '', $title);
// Restore octets.
$title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title);
$title = strtolower($title);
$title = preg_replace('/&.+?;/', '', $title); // kill entities
$title = str_replace('.', '-', $title);
$title = preg_replace('/[^%a-z0-9 _-]/', '', $title);
$title = preg_replace('/\s+/', '-', $title);
$title = preg_replace('|-+|', '-', $title);
$title = trim($title, '-');
echo $title;
}
mysql_query("UPDATE menus SET name='$name' , path='$path'");
}
?>
<html>
<head>
<script type="text/javascript" src="/javascript/jquery-1.8.2.min.js"> </script>
<script>
// create the XMLHttpRequest object, according browser
function get_XmlHttp() {
// create the variable that will contain the instance of the XMLHttpRequest object (initially with null value)
var xmlHttp = null;
if(window.XMLHttpRequest) { // for Forefox, IE7+, Opera, Safari, ...
xmlHttp = new XMLHttpRequest();
}
else if(window.ActiveXObject) { // for Internet Explorer 5 or 6
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlHttp;
}
// sends data to a php file, via POST, and displays the received answer
function ajaxrequest(php_file, tagID) {
var request = get_XmlHttp(); // call the function for the XMLHttpRequest instance
// create pairs index=value with data that must be sent to server
var the_data = 'sanitize='+document.getElementById('name').innerHTML;
request.open("POST", php_file, true); // set the request
// adds a header to tell the PHP script to recognize the data as is sent via POST
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send(the_data); // calls the send() method with datas as parameter
// Check request status
// If the response is received completely, will be transferred to the HTML tag with tagID
request.onreadystatechange = function() {
if (request.readyState == 4) {
document.getElementById(tagID).innerHTML = request.responseText;
}
}
}
</script>
</head>
<body>
<form action="<?php $_PHP_SELF ?>" method="post">
<label for="nume">Name</label><input type="text" name="name" id="name" onchange="ajaxrequest('new_page.php', 'path')" />
<label for="cale">Path</label><input type="text" path="path" id="path" />
<input type="submit" name="submit"/>
</form>
</body>
</html>
As already mentioned, you cannot invoke PHP functions using JavaScript because one is a server-side technology and the other is client-side technology and is only executed on the local browser.
The suggested approach for dealing with data, databases, and user input is to use an MVC architecture with ActiveRecord paradigm for data access. If done correctly, all your data should be sanitized within the active record model before committing to the database.
I know this is an old post but I think this will help people searching for this question.
As Zorayr said, PHP is a server-side based language and Javascript or derivatives are client-side. That's because you can not invoke PHP functions from the JS code.
But instead of call a function, you can fire the function with a processed form as you have in your code. The other way is to make a PHP Class and in the same file initialize it.
Example:
<?php
Class MyClass {
function __construct()
{
echo "hello world.";
}
}
$init = new MyClass();
?>
This way you can pass arguments and do whatever more clear.

Resources